Sabina Sokol's Notebook - cps-vip/cps-cosimulation-env GitHub Wiki

Table of Contents


Spring-2024

Week 1

1/11/24 - Class Meeting

  • Discussed basic power grid and cyber-physical system concepts
  • Reviewed project structure and teams (ROS/HELICS and Device Modeling)
  • Completed Welcome Survey to indicate preference for team assignment (I chose ROS/HELICS)
  • Joined CPS Discord

Week 2

1/18/24 - Class Meeting

  • Reviewed Kickoff Presentation requirements and assignment dates (1/25/24)
  • Broke off into subteams and reviewed last semester's goals, progress, and major challenges --> main focus will be integrating ROS2 with HELICS, which I can use my HELICS background to help with
  • Set a student-only weekly subteam meeting slot (Tuesdays at 3:30 pm in Klaus 1446) to discuss individual progress, exchange ideas, etc.
  • Discussed the challenges of discrete time simulations with varying requirements (ie. ROS2 would run at the millisecond level vs. GridLab-D would run at the microsecond level)
  • Reviewed components of HELICS co-simulation: PyPower, GAZEBO, ROS2, GridLab-D

1/19/24 - Individual

Week 3

1/23/24 - Team Meeting

  • Reviewed previous background research, presentation slides, midterm paper, and other notes to construct Kickoff Presentation
  • Delegated presentation components based on status in the team (new vs. returning)
  • Discussed semester timeline for tasking
  • Polled each person's knowledge of OOP, C++, HELICS, GridLab-D, etc. to begin dividing up tasking --> most people don't know C++, so there will be a slight learning curve
  • Agreed to start the 22-hour ROS2 crash course with the goal of finishing it within 3 weeks before moving onto integration with HELICS

1/24/24 - Individual

  • Researched line inspection robots and previous power line/robot work to curate the "Background Research" slide of the Kickoff Presentation --> found 2022 article about motion precision capabilities using inertial measurement unit image
  • Rehearsed presentation part out loud 3 times

1/25/24 - Class Meeting

  • Presented Kickoff Presentation (roughly 20 min.)
  • Received feedback about better defining the significance of our work and the problem we're trying to solve at the beginning of the presentation (was just sprinkled in everyone's individual slides)

Week 4

1/29/24 - Individual

  • Began reading ROS2 documentation online about nodes, packages, client libraries, etc.

1/30/24 - Team Meeting

  • Roadblock with original ROS2 course (40 euro paywall) --> looked for alternative sources of information

2/1/24 - Individual

  • Began working through the official humble tutorial by reading about ROS2 background information, environment configuration, turtlesim, and rqt
  • Sourced setup files for workspace, checked environment variables, and set domain ID by referencing this documentation

image image

  • Explored turtlesim by creating a turtlesim node with ros2 run turtlesim turtlesim_node and then manipulating the graphic with ros2 run turtlesim turtle_teleop_key

image image

  • Attempted to "spawn" the turtlesim service via rqt, but ran into roadblock with the GUI (not showing all service options) image
  • Plan to raise issue with group during the next subteam meeting

Week 5

2/5/24 - Individual

  • Continued working through humble tutorial by reading about remapping and nodes
  • Explored remapping with turtlesim nodes by reviewing documents/rules with regards to non-default parameter configuration, name reassignment, logging settings, and other custom node configurations

image

  • Refined understanding of nodes by reviewing additional document here and here

2/6/24 - Individual

  • Had brief check-in with team via Discord and agreed that there was no need for a formal meeting as everyone was working through the tutorial
  • Continued working through humble tutorial by reading more about nodes and topics
  • Reminded me of MQTT communication in which there are also publishers and subscribers to different threads
  • Used rqt_graph to model communication between turtlesim and teleop_turtle

image image

  • Learned several new commands related to gathering more information about topics, publishers, and subscribers, which will be incredibly useful when debugging our own node networks in the future
  • ros2 topic echo <topic_name> (view the traffic being passed about the topic)
  • ros2 topic list -t (list all active topics with their type)
  • ros2 topic info <topic_name> (view type, publisher count, and subscriber count of topic)
  • ros2 interface show <msg_type> (breaks down the expected structure of sent/received data for that message type)
  • ros2 topic pub <topic_name> <msg_type> '' (publish data to a topic directly from the command line)
  • ros2 topic hz <topic_name> (view rate of data transmission for topic)

Example of command-line publication (one time vs loop): image

image

2/8/24 - Class Meeting

  • Gave brief summary of my week's work during the team stand-up
  • Continued working through humble tutorial by reading about services (call-response model), parameters, actions (client-service model), and logging
  • Learned several new commands for making service calls and setting/ammending parameters
  • ros2 service call <service_name> <service_type> (make a service call)
  • ros2 param get <node_name> <parameter_name> (view current value of a parameter)
  • ros2 param set <node_name> <parameter_name> (set new value for a parameter)
  • ros2 param dump <node_name> (view all current parameter values)
  • ros2 param load <node_name> <parameter_file> (configure parameters from a file)

Example of command-line service call to clear the turtlesim window: image

Example of rqt_console displaying error messages: image

Information about keyboard controls for teleop_turtle: image

2/9/24 - Individual

  • Continued working through humble tutorial by reading about launching multiple nodes from a single file
  • Can write simple python/yaml/xml script:
# turtlesim/launch/multisim.launch.py

from launch import LaunchDescription
import launch_ros.actions

def generate_launch_description():
    return LaunchDescription([
        launch_ros.actions.Node(
            namespace= "turtlesim1", package='turtlesim', executable='turtlesim_node', output='screen'),
        launch_ros.actions.Node(
            namespace= "turtlesim2", package='turtlesim', executable='turtlesim_node', output='screen'),
    ])

and then run ros2 launch turtlesim multisim.launch.py

image

Week 6

2/13/24 - Team Meeting

  • None of us finished the humble tutorial through the client libraries sections because of other class work loads --> agreed to move deadline for completing the tutorial to EOD Friday, 2/16/24
  • We seem to have an idea on what sub teams we each want to be on so we will decide on Thursday during class since it is a group work day
  • After we divide into subteams, we will spend some time doing research relevant to the paper
  • We will begin working on our midterm paper next Tuesday, 2/20/24 and divide up the sections to finish it by Wednesday, 2/21/24
  • To-Do:
  • continue working on humble tutorial by building packages, workspaces, and publishers/subscriber model
  • Note: make sure to run source /opt/ros/humble/setup.bash in the terminal if the Docker container restarts or else packages/builds won't go through image

Other important notes about overlays: image

Reference for publishers/subscribers: https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html

Demo of publisher/subscriber model with colcon sample package: image

2/15/24 - Class Meeting

  • Had full class standup to recap what we've done and what we're learning

  • Had team meeting with Will to re-establish semester goals, subteam divisions, and specific robot simulation milestones

  • Began discussing potential subteam assignments and corresponding paper sections (planning document)

  • Milestones for Robot Simulation

  • complete introductory tutorials for TurtleBot (link)
  • review fundamentals of nodes/publishers
  • complete TurtleBot simulations ("Seeing" the world and avoiding obstacles)
  • Translating to real life
  • Develop metric for safety and implement in code
  • Subteam Divisons
  • ROS2/HELICS integration
  • Substation environment + mission
  • mission and trajectory planning
  • nodes and sensors for TurtleBot
  • To-Do:
  • finish humble tutorial by EOD Friday
  • begin TurtleBot tutorial and finish by EOW/EO2W next week
  • begin writing the "Introduction" section of the paper and finish by next Wednesday, 2/21/24

2/16/24 - Individual

  • Finished up humble tutorial by building the simple service/client, creating custom msg/srv files, implementing custom interfaces, and using parameters
  • Used a vim cheat sheet to help me create and edit the appropriate cmake, xml, and cpp files

Reference for clients/servers: https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Service-And-Client.html

Demo of client/server model with sample package: image

Demo of custom msg and srv files with client/server model: image

Week 7

2/19/24 - Individual

  • Began the VIP Peer Evaluation but could not complete it due to a submission error on Question 15
  • Emailed [email protected] with a screenshot of the issue
  • Revised the introduction section of the midterm paper using our Kickoff presentation slides and planning document to better align with our vision for this semester image
  • Reviewed the rubric for the paper to ensure that my section meets all of the criteria
  • Began reviewing the turtlebot introduction we had agreed on during our class meeting, but it appears to have been written in February 2015. Given that the distribution of ROS and Ubuntu required for the tutorial (indigo and 14.04 LTS), I believe it is best that we pivot and find something more recent. I will raise this with the rest of the group during tomorrow's team meeting. I have found several other tutorials that we could reference instead:

2/20/24 - Team Meeting

  • Other group members encountered issues with running the TurtleBot tutorial with Ubuntu 22.04 LTS
  • There are only tutorials with indigo (deprecated) and foxy
  • Found a list of TurtleBot resources: https://robots.ros.org/turtlebot3/
  • Plan for midterm presentation: split off into the ROS2/HELICS integration and physical environment teams to start building custom federate (this is the biggest obstacle)
  • Reviewed assigned sections and agreed to finish midterm paper by tomorrow at 6:00 pm
  • To-Do: Reach out to HELICS developers at LLNL to ask about ROS integrations

2/22/24 - Class Meeting

  • Did quick class standup to go over our current progress
  • Worked with Will to debug an error with a link library by deleting the build directory from the ros2 workspace (the Docker container already builds it), which got the publisher/subscriber example to run image image
  • To-Do: Start brainstorming for midterm presentation (due next Wednesday!)

Week 8

2/27/24 - Team Meeting

  • Reviewed feedback from Kickoff Presentation and assigned roles for everyone in the IPR1 Presentation
  • Made a copy of the Kickoff Presentation slide deck and added/modified slides to fit the IPR1 rubric (referred to the midterm report notes)
  • Reworked the introduction slides to ensure we start with a high-level overview of the problem statement (this was our biggest piece of feedback last time) image image image
  • To-Do: Outline and practice talking points for introduction slides

2/28/24 - Individual

  • Reviewed the introduction I wrote in the midterm paper to compose my talking points for the slides in the IPR1 presentation
  • Checked with team on Discord to ensure that everyone finished their slides and that we submitted on time

2/29/24 - Class Meeting

  • Presented our IPR1 slides to Will, Sam, and the Device Modeling team
  • Received great feedback about our new introduction
  • Were advised to modify one of our end-of-semester goals to just hooking up a sensor to the TurtleBot and getting temperature/magnetic field readings instead of a full robotic arm

Week 9

3/4/24 - Individual

  • Began looking into HELICS source code and developer guide to find a way of integrating it with a ROS2 publisher/subscriber image image image

  • To-Do:

  • Talk to Safiy and other team members that were part of CPS last semester to locate existing code/resources

3/7/24 - Class Meeting

  • Will and Sam walked us through a cyber--physical system education activity that involved parsing through a packet capture file in Wireshark and identifying what the network traffic could be indicative of
  • Deduced based on ARP, DHCP, SMTP, IGMP, and communication patterns that there was a network of ublox robots communicating with at least one HMI
  • Talked to Safiy, who said to reference HELICS public API documentation and try to embed those headers into a basic "Hello, World" type publisher/subscriber in ROS2

Week 10

3/18/24 - Individual

  • Received a response from the lead developer of HELICS at LLNL about the best way to approach the HELICS/ROS2 integration image
  • Looked at the HELICS Installation documentation to determine the steps I needed to take specifically for implementing the C++98 API
  • Downloaded the latest release of pre-compiled libraries on my local machine and used docker cp (referencing this documentation) to copy the unzipped directory to my ROS2 VM
  • Watched this video to better understand how to link shared libraries together and reviewed this page on Stack Overflow to better understand what a header only library was
  • Referenced an older cpp example in the HELICS-examples GitHub repository and attempted to add the header and code required to print the HELICS software version to the pub/sub example introduced in the humble tutorial here image image image
  • Referenced a vim cheat sheet to help edit the member_function.cpp file quickly
  • After running rosdep install -i --from-path src --rosdistro humble -y as per the guidelines in the pub/sub humble tutorial to check for missing dependencies, I got an error indicating that HELICS was not linked properly

image

based on a response in the older ROS2 forum

  • After watching a video about the C interface (which is what is underneath the C++98 API) on the HELICS Youtube Channel, I realized that I needed to export the HELICS install path to the ~/.bashrc file, which I referenced this Stack Overflow page to do

image

  • I kept getting the same error, so I decided to take a break and come back at it from a different angle the next day

3/20/24 - Team Meeting & Individual

  • I decided to look into whether my CMakeLists.txt file was written correctly and referenced this Stack Overflow page for some guidance
  • I also double checked the HELICS documentation about linking it into other software
  • After a couple more hours of dead ends, I messaged the lead developer for HELICS at LLNL that I had previously spoken with about for help
  • We agreed that I would join Thursday's HELICS office hours at 11:00 am PT to troubleshoot the issue live

3/21/24 - Individual

  • Joined HELICS office hours and deduced that cmake was not finding my HELICS config.cmake file even after verifying that my ~/.bashrc file had all the necessary lines image
  • After playing around with the CMakeLists.txt file again and the ament_target_dependencies option, I decided to try linking the libraries via regular cmake commands like target_link_libraries and target_include_directories image
  • Linking the client libraries was now resolved, but I kept getting "could not import symbols" errors from HELICS when running the colcon build --packages-select examples_rclcpp_minimal_subscriber command, indicating that either there was some sort of cross-complication happening the background or that there was an architecture mismatch between the HELICS and ROS2 libraries
  • Using the dpkg --print-architecture in a new terminal on the ROS2 VM, I realized that the Docker container was an arm64 and not an amd64 like I had originally assumed, which explained the issue because the pre-compiled HELICS libraries I downloaded were for the latter architecture. Apparently, ROS2 has cross-compilation capabilities according to this Stack Overflow page!
  • I generated a custom config.cmake file for HELICS within my current directory using an example file from HELICS GitHub page here because the existing one was unsuitable for arm64
  • From there, I troubleshooted through a handful of ZMQ related errors (a dependency of HELICS) using the list of HELICS CMake options here image
  • I also found and reported several bugs in the HELICS CMakeLists.txt files that required me to roll back to a previous version (3.4.0) and manipulate some build files image
  • I rebuilt the examples_rclcpp_minimal_subscriber package and finally got no errors! image
  • I copied my custom HELICS config.cmake file and all of the additions I made in the CMakeLists.txt file to the minimal_publisher directory and built the examples_rclcpp_minimal_publisher package with no errors as well
  • Finally, I referenced the humble documentation once again to ensure I ran the publisher and subscriber packages correctly. The subscriber (top) is printing what the publisher (bottom) has sent along with the HELICS version using the helicsGetVersion() command found in the C++98 Doxygen documentation image

Week 11

3/26/24 - Team Meeting

  • Provided brief explanation of my integration process between ROS2 and HELICS
  • Agreed that the next step was to integrate GridLab-D and run the example posted in the cps-cosimulation-env repository
  • Posted code and steps to recreate my progress in my own repository here
  • To-Do: Build GridLab-D using the flags that automatically integrate it with HELICS

3/28/24 - Class Meeting

  • Provided a brief description of my progress with the ROS2/HELICS integration during the standup

  • Began trying to build GLD from source in the ROS2 Ubuntu VM using this documentation

  • In order to link GLD and HELICS, I added the flags -DGLD_USE_HELICS=ON and -DGLD_HELICS_DIR=~/software/HELICS/build/lib when running cmake -DCMAKE_INSTALL_PREFIX=~/software/GridLAB-D -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - Unix Makefiles" ..

  • Ran into the same "resolving symbols" issue I faced when first trying to build ROS2 packages with HELICS pre-compiled libraries installed, which was to be expected because of the architecture mismatch image

  • The only viable option for fixing this issue was to build HELICS from source so that GLD had access to correct the files, so I referenced the instructions to do so here image

  • After exporting the installation path to my .bashrc file, I did a quick version grab to verify that the build was successful image

  • I then re-built GLD and did a similar version check to verify that the installation was also successful image

  • I then rebuilt the publisher and subscriber packages so that I could re-run the program I had previously used to test my integration image image

  • While my the publisher/subscriber ran, the HELICS version that was printed out did not update from 3.4.0 (the version I originally downgraded to in order to get the original integration to work) to 3.5.1 with the new build from source. So I scoured my cmake cache, lib, and include files across my packages to remove all instances of the libhelics.so.3.4.0. However, after spending several hours doing so, I still couldn't resolve the issue. Tomorrow, I plan to start with a fresh ROS2 container and see if I can build HELICS and GLD from scratch along with ROS2 example packages.

3/29/24 - Individual

  • Created a fresh ROS2 container and followed this tutorial to pull the example packages

  • I then followed the GLD and HELICS tutorials from above to build the two softwares from source and successfully installed them image

  • I then exported the HELICS libraries to my $PATH in order to complete the integration between ROS2 and HELICS once more, which only required a few modifications to the CMakeLists.txt file image image

image

  • With these changes, I was able to successfully run the program! The next step is to run the GLD example from the cps-cosimulation-env repository image

Week 12

4/1/24 - Team Meeting

  • Met with group for 2 hours to guide them through the ROS2/HELICS integration process on their own Docker containers
  • Agreed that the next step was to convert the gld example from python to c++ using the HELICS cpp98 documentation
  • Managed to convert the Transmission_simulator.py and Relay_simulator.py files to cpp, without the PyPower or MATLAB code. image

We will need to check in Will and Sam on Thursday about how to incorporate the PyPower processing capabilities required for the TurtleBot to make decisions about what actions to take.

  • The next challenge is to figure out where the HELICS broker will run in relation to the ROS2 federates given that there is no command line utility for HELICS in c++ like there is for python. I believe that we'll need to mimic the CMakeLists.txt file like in this pi_exchange example. However, the example uses a bash script to run the broker and federates, which I'm not sure will work with the ROS2 model of launching a package. The best approach in my opinion is one that will be most realistic for our entire simulation: have a machine specifically to the run the HELICS broker that is on the same network as the ROS2 federates. When that json file is run, it will then look for the federates on the ROS2 container and initiate communication. That way, we just have to the include the code to create the federates in the publisher/subscriber nodes for ROS2, which can run infinitely. I will ask the developer at LLNL whether a simulation can have a python-based HELICS broker and then cpp-based federates.

4/4/24 - Class Meeting

  • Discussed with Safiy and Will about the easiest way to run the simple_gld_example. We decided to run all the federates on localhost with a simple subscribing federate on the ROS2 publisher node. I believe my work in converting the files to cpp is not a loss because we'll need to reference them to create the federate within the ROS2 publisher package.
  • The first step was to just run the co-simulation as is in the Docker container. So, I used docker cp to copy the downloaded files from my local machine to the container, and then used chmod to make the run_example.sh script an executable. I had to install pyhelics and pypower with pip install as well. I also had to run alias python=python3 to ensure that the bash script could locate the correct python library to use.
  • In attempting to the run the example, I encountered a couple errors with ZMQ and duplicate helics brokers. image image
  • Using netstat to check what ports were being used by the co-simulation and ps | grep to check whether there were any helics/gld instances hanging around. I found a couple, which I killed with kill -9 image
  • Finally, I was able to launch the relay federate with the run_example script image
  • Unfortunately, when I tried to helics run --path=cosim_runner.json to launch the transmission and distribution federates, I got an error that helics was not properly installed/confgired despite the fact that I made sure the helics apps worked (helics_broker --version) for example and that I had the latest version of pyhelics on my machine image
  • I scoured the web for documentation about pyhelics and found this, this, this, and this. I also checked internal documentation I wrote last summer when working with helics on a Raspberry Pi 4 with Ubuntu Jammy Jellyfish installed, but didn't find any indication that I dealt with that problem. Running python -c "import helics; print(helics.helicsGetVersion())" gave me 3.5.1, which was the version of helics I had installed, so I still wasn't sure what the problem was.
  • I decided to reach out to my contacts at LLNL to see if they could what I was missing.

Week 13

4/8/24 - Individual

  • As I was continuing to troubleshoot my PyHELICS error, I realized that my ~/.bashrc file was completely wiped. I attributed this to some weirdness with Honorlock running during my CS exam that morning. Luckily, I had screenshots of my ~/.bashrc file documented in this notebook, so I was able to copy a clean one from /etc/skel and manually add the ROS2, HELICS, and GridLAB-D paths I needed.

4/9/24 - Team Meeting

  • Had brief meeting with to discuss progress on GAZEBO and running the simple_gld_example
  • HELICS developers are currently on vacation until Thursday, 4/11, so I will check in with them again about my error

4/11/24 - Class Meeting

  • Agreed with team to prepare and construct our final presentation next Tuesday, 4/16, during our team meeting
  • Heard back from HELICS developer at PNNL with troubleshooting steps
  • After re-running pip install helics and redirecting the output into a text file to send the HELICS developer, I noticed a permissions error printed at the top indicating the PyHELICS wasn't being install system-wide. image I decided to run the command again with sudo in front, which worked! PyHELICS was now properly installed in the VM
  • I then tried running the co-simulation again and ran into an error running the gld code, which I attributed to a $PATH error. Apparently I accidentally exported the wrong path to the gld install location, which I fixed by editing my ~/.bashrc file image
  • Finally, I re-ran the co-simulation and got the desired graphical output! image

Week 14

4/15/24 - Individual

  • Recorded a demo video of the co-simulation running inside the VM for the final presentation image

  • Used docker cp to copy the "member_function.cpp" file from the minimal_publisher directory and added my converted Relay.py code to create a subscriber federate within the ROS2 publisher.

  • Began troubleshooting the federate instantiation

  • My biggest challenge thus far is my lacking understanding of C++, particularly with implementing hashmaps to store all of the subscriber and publisher data image

4/16/24 - Team Meeting

  • Broke up all of the slides in the final presentation
  • Agreed to add information about the applications of the ROS2/HELICS integration as well as next steps with adding sensors to the robot simulation image

4/17/24 - Individual

  • Finished up slides for presentation and turned them in
  • Made some personal notes for myself about what to discuss:
  • biggest challenges: cross-compiling x64-based HELICS binaries onto amr64 VM
  • how the simulation currently runs: distribution, relay, and transmission are all running within the VM outside of ROS2
  • next steps: currently working on creating a subscriber ROS2 federate to integrate with this existing simulation
  • current challenges: limited knowledge of intermediate/advanced C++ concepts
  • future milestones: have ROS2 publisher node publish data to ROS2 subscriber node that it subscribed to within co-simulation

4/18/24 - Class Meeting & Individual

  • Presented current progress on ROS2/HELICS integration and GAZEBO simulation
  • Continued debugging federate code with ROS2 publisher node using HELICS C API documentation to understand the methods being called, and their return values.
  • Reached out to HELICS develop at LLNL and PNNL with the following error and asked about the next HELICS office hours: image

Week 15

4/23/24 - Team Meeting

  • Divided up work for final paper
  • Agreed to finish writing by midnight tonight to leave time to edit and turn in tomorrow
  • Finished my sections about the ROS/HELICS integration and suggested modifications to the paper structure to minimize redundancy image

Fall-2024

Week 1

8/22/24 - Class Meeting

  • Reviewed premise of course
  • Filled out background information form to indicate research interests and team preference

Week 2

8/29/24 - Class Meeting

  • Reviewed more in-depth information about HELICS, GridLAB-D, and ROS
  • Gave a detailed explanation of existing proof-of-concept simulation with ROS2, HELICS, and GridLAB-D
  • Outlined room for growth and development
  • Established team meeting time on Mondays at 1 pm

Week 3

9/2/24 - Individual

  • Sent out previous semester's final paper and presentations for new members to review
  • Created new slides for kickoff presentation image
  • Created slide for new "Fault Detection" subteam image

9/4/24 - Individual

  • Pinged sub-team members to finish up slides
  • Assigned slides to individuals based on knowledge of content

9/5/24 - Class Meeting

  • Presented kickoff slides to class
  • Received feedback on our good subteam breakdown and introduction to the problem statement

Week 4

9/9/24 - Individual

  • Reviewed team meeting notes (unable to attend due to illness)
  • Review 1-2 papers about fault detection to present to team on Thursday
  • To-Do: connect with monitoring team on device modeling side
  • To-Do: ask Sam for information about existing GridLAB-D fault injection capabilities

9/10/24 - Individual

  • Went through the steps I created at the end of last semester to re-build the proof-of-concept: ros2-helics repo
  • Had to review numpy and pypower version history because the latest versions (released last week) are not compatible with our example
  • Encountered issues with broker and registering federates, which I was not yet able to resolve image
  • To-Do: Use Dedockify tool to build Dockerfile out of Docker image for easy of building

9/12/24 - Individual

  • Could not make it to class because I was ill and lost my voice completely, but I reviewed the notes posted in the Discord channel
  • Began researching into GridLAB-D fault injection capability

Week 5

9/16/24 - Team Meeting

  • Reviewed each subteam's tasking from the previous week
  • Discussed ways of making ROS framework more lightweight
  • Problem is building HELICS in order to compile
  • Lifting the lib files and the header files
  • Include HELICS as a submodule
  • Dockerized build environment: Create a docker image, HELICS is built from source with appropriate flags, ROS installed, Can be used to build our ROS package, Image hosted on container registry
  • To-Do: build bash script to help terminate helics simulations cleanly (helics kill-all-brokers; ps aux | grep helics --> sudo kill -9 "pid")

9/17/24 - Individual

  • Created and tested simple bash script to help clear all helics and gridlabd threads after killing a simulation image

9/19/24 - Class Meeting

  • Had an in-depth conversation with Safiy about next steps for the project. I felt that we should focus on building out a control center federate that all gridlabd data is funneled through because that's how information flows and faults are detected in the real world. He felt that we should focus on device-robot communication, which is valid but not necessarily as important to the project as a whole right now given that the device modeling team hasn't fleshed out their devices yet. We involved Sam and Will as well to get their perspectives on fault detection in the real world, and Sam pointed me towards a module in gridlabd that does fault injection.
  • To-Do: investigate gridlabd fault injection; build simple python "command and control" federate to subscribe to gridlabd data

Week 6

9/23/24 - Team Meeting

9/24/24 - Individual

  • Continued investigating reliability module and am unclear about where the eventgen is supposed to go. I understand that you can trigger a random event on objects in the GLM file, but I don't understand where that code actually goes. The gridlabd repo was a little more helpful because it has a reliability use case that seems to be pretty recent: https://github.com/gridlab-d/gridlab-d/tree/master/reliability. I will explore this in more detail once I have my base gridlabd --> helics --> python federate --> helics --> ros2 pipeline working.
  • I looked through the publications of Distribution (gridlabd federate) and Transmission (python federate) to see what my control center federate should subscribe to. However, when I ran my example again before changing my helics runner file to include my new federate, I experienced the following error: image I researched this is saw something on stack overflow about how this could be a docker issue and that I need to run my container with privileged access, which is odd because I haven't had to do that before. I tried running my container with the --privileged flag and received saying I needed to log in to docker, even though I was successfully logged in before. I'm not sure what's going on, so I'll raise the issue during the class meeting on Thursday to see if Sam or Will knows what's wrong.

9/26/24 - Class Meeting

  • Began discussing midterm paper due next Wednesday
  • Will provided resources to the Nodes & Sensors subteams to help them get started on exploring LiDAR

9/27/24 - Individual

  • Continued debugging time request issue I was experiencing earlier in the week
  • Looking at the helics request time documentation, I pondered the impact of setting "uninterruptable" to false such that the ROS2 federate didn't need to wait for the other federates to publish more data to continue running, but my error persisted image
  • Then looking at my helics broker and gridlabd federate log files, I realized it would be more useful to have the log level set to debug for all my federates so that I can better understand where my time request issue is coming from: image image
  • With the log level set to debug, I saw that the ROS2 federate was being initialized but granted time looked a bit odd: image
  • I decided to dig into the log files for my other federates to understand what the time granted should look like: image I realized that the standard time request is small positive integer (logically makes sense - as simulation continues, time step increases linearly), whereas my ROS2 federate is receiving some large negative floating point value, which is very odd considering my time requesting is identical to what I have in my Relay federate: image
  • Using the helics documentation as a reference, I decided to play around with my offset, period, and time delta defined in the config json file: image
  • It appears that did not affect the simulation because I received the same error. I will bring this up in class next Thursday to see if Will or Sam have any ideas.

Week 7

9/30/24 - Team Meeting

  • Discussed outline of midterm paper
  • Agreed to use last semester's final paper and modify section III to this semester's progress and goals
  • Agreed to finish up as much as possible tomorrow night because a lot of people have an exam on Wednesday night
  • Modified section IIIc to include my work on fault detection

10/1/24 - Individual

  • Checked in with team via Discord to see what progress everyone's made
  • Agreed that Safiy will turn in the paper tomorrow now
  • Continued looking around the web for more resources on my timing issue, but having found anything else useful
  • To-Do: contact Phillip Top from LLNL (same contact from last semester) about setting up time in HELICS office hours to troubleshoot issue

10/3/24 - Class Meeting

  • Sat down with Will to look at the helics source code in order to find why the "cannot call time" exception is being thrown
  • Realized that I was not putting my ros2 federate into execution mode after initializing it, which meant it was illegally requesting time
  • Simulation from end of last semester now runs! image image

10/4/24 - Individual

  • I am now modifying my code such that the ros2 federate subscribes to the CC federate, which for now is just printing "fault not detected" --> the idea is the CC federate will monitor current and total load and determine whether there is a fault in the distribution (GLD federate) system
  • I sometimes receive the following error when I try to rerun my cosimulation, and ./kill_all.sh doesn't help image
  • Will continue debugging to see where the issue with coming from

Week 8

10/7/24 - Team Meeting

  • Met with team to discuss updates to presentation
  • Added a new slide for fault detection progress

10/10/24 - Class Meeting

  • Had midterm presentation - spoke about past semester's accomplishments and this semester's fault detection accomplishments

Week 9

10/17/24 - Class Meeting

  • Met virtually as a class
  • Discussed our first proof-of-concept mission: Mission Planning We (ROS / HELICS) insert a fault Command and control processes GLD data from HELICS Detects fault Sends command to ROS subscriber, ROS will move in Gazebo

Questions

Where do we inject a fault? Artificially send a value above nominal voltage. In what component? Distribution federate, Transmission federate, Relay Pick one and inject a fault Send out erroneous data How do we detect it? CC gets it IF ELSE Where do we send the robot? Trigger a movement to a point X in substation

Inject a high voltage

IF voltage > threshold THEN command robot

Robot moves to point X (arbitrary)

Modularization

CC Python interacts with HELICS (ros/helics subteam) Fault injection in GLD (ros/helics subteam) Robot logic Figure out navigation in the substation (Sensors subteam) ROS node that moves the robot based on external commands (gazebo subteam) CC acts as both HELICS federate and ROS node Mission and Trajectory

Prepare questionnaire for Device Modeling What is the device? Outputs of the device (voltage, current) Data type (complex, value, string, floating) Simulation configuration Potential faults and how we can produce them Communication protocols Physical structure and location ( a rough idea) Send out to discord channel, communicate with instructors if no response from DM within one week Target to prepare this questionnaire - Monday 21st Oct

Week 10

10/21/24 - Team Meeting

  • Reviewed questions Hussein compiled for device modeling team
  • Hussein sent out Google Doc

10/22/24 - Individual

  • Researched into correct data type handling in C++ for the publications and subscriptions I am using for the Control Center <--> ROS2 federate communication
  • Reviewed previous code from last semester because I haven't been able to resolve my issue

10/24/24 - Class Meeting

  • Briefly introduced ourselves and our questionnaire to device modeling team
  • Confirmed that they would put some people on finishing it and sending it back to us with a device model (glm files, etc.)
  • Discussed everyone's technical progress and future plans to have robot design team
  • Not a priority right now, that's a task for 6 people alone with our current work on communications and navigation

Week 11

10/28/24 - Team Meeting

  • Was not able to fully attend because of my interview later that day, but updated my team on my continued struggles with getting the Control Center federate to run
  • Joseph said he should have a demo of the ROS2/GAZEBO ready for the class meeting

10/31/24 - Class Meeting

  • Debriefed Will on current progress
  • Issues with importing/building GridLAB-D reliability module
  • Continued debugging control center federate

  • Experiencing new error with CC publishing the right message but erroring out immediately after because it's somehow publishing after exiting executing state image image image

  • Looking at the CCFederate.log, I realize it was trying to register a publication of the name "CC/CC/faultDetection" instead of "CC/faultDetection" because I was defining the publication in my CC_config.json file. image

  • After fixing that, I got the right message exchange! image

  • My next step is to define the actual parameters I should be checking based on Safiy's reliability module work.

11/1/24 - Individual

Week 12

11/4/24 - Team Meeting

  • A few people had time conflicts, so we agreed to share updates in the discord channel
  • We agreed we would review the google document returned by the device modeling team on Thursday
  • To-Do: check in with Safiy on his status with the reliability module in GridLAB-D

11/7/24 - Class Meeting

  • Followed up with Safiy and clarified that he is injecting a fault in an overhead line in the Distribution system
  • Nominal voltage: 138000 V
  • Nodes are taking: 2400 V
  • Transmission publishes voltage -> subscribe with CC federate
  • Distribution can publish voltage values if necessary
  • Helped Safiy troubleshoot pyhelics installation in Nix environment
  • Refer to GLD documentation for units of values in the future: https://gridlab-d.shoutwiki.com/wiki/Power_Flow_User_Guide

Week 13

11/11/24 - Team Meeting

  • Agreed to finish integration by next week's final presentation
  • Things to integrate: Joseph's GAZEBO/ROS plugin, my Control Center federate, Safiy's fault injection

11/14/24 - Class Meeting

11/15/24 - Individual

  • Safiy wasn't able to access my image on the registry because the organization permissions automatically set it to private, so I had to go into the registry settings and deselect organizational permission inheritance to make it accessible internally
  • My image is still arm64 instead of amd64, so Safiy couldn't build it on his Windows machine, so he decided to write his own dockerfile

Week 14

11/18/24 - Team Meeting & Individual

  • Joseph made a copy of our previous presentation to start working on our final presentation
  • Recorded a demo video of the integration with the CC server sending a "fault detected" signal to the ROS federate
  • Updated and rearranged my slides to include new demo video and update on progress towards original fault detection goals image

11/20/24 - Individual

  • Checked in with group to make sure everyone has updated their slides before the final presentation deadline
  • Used docker cp to copy the minimal_publisher and simple_gridlabd_example directories to my ros-helics github so that Safiy can pull them down and set them up on his machine to try and run my example https://github.com/fizzyforever101/ros2-helics

11/21/24 - Class Meeting

  • Did our final presentation
  • Got a note to make a high level diagram that demonstrates how everything works together and what is already integrated/working image

Week 15

11/25/24 - Team Meeting

  • Discussed goals for next semester and completed diagram of moving pieces
  • Next semester will be focused on integrating robot movement in gazebo with current simulation of fault via reliability in gridlabd
Screenshot 2024-12-02 at 12 53 47 PM

Week 16

11/2/24 - Team Meeting

  • Dicussed division of work for final paper
  • Need to revise introduction and background research
  • Remove excess detail of previous semester's work to narrow the scope of the paper and focus on current semester's progress
  • Agreed to have initial edits done by tomorrow night 11:59 pm so we have a full day to revise

11/3/24 - Individual

  • Modified ROS section to highlight current progress and new goals of integration
  • Updated fault detection section with progress and future plans
  • Reviewed structure of paper to ensure it flows well

11/4/24 - Individual

  • Looked over everything one more time before Safiy submitted

Spring-2025

Week 1

1/9/25 - Individual

  • Sent the new members in the ROS/HELICS team the previous papers and slides we have
  • Note: I am doing this on the PURA award, so not for credit. I am also remote this semester because I have a class conflict with my Computer Networking class.

Week 2

1/15/25 - Individual

  • Spoke with Will about robot requirements:
  • LIDAR, IR camera, mount for some sort of mechanical arm
  • should make mount with general mechanical and electrical specifications so that we don't have to worry about designing something specific while we're still figuring out the basic structure
  • Need bridge node to connect serial communication between the motor controllers and ROS
  • can use onshape/solidworks/fushion360 for CAD design
  • need to design drive train
  • servo vs stepper vs dc motors

Week 3

1/20/25 - Subteam Meeting

  • Worked with Elliot to create slides in Kickoff presentation about robot design and hardware requirements image image image image image

1/23/25 - Class Meeting & Subteam Meeting

  • Presented introduction slides during Kickoff Presention
  • Feedback from Will and Sam:
  • Tie in tasking to end goal more explicitly
  • Overall best presentation for team so far!
  • Elliot and I spoke with Will about timeline for robot design -> goal is to order parts by the end of the semester so they can all arrive over the summer
  • check who's funding the project and whether we can already order parts to test as we start CADing
  • design with encoders directly on wheels so we don't run into issues where motors seem to be working but there's no movement, etc.
  • design so that it is easier to machine (but trade offs with designing for machining vs 3d printing)
  • will need to schedule longer design reviews outside of VIP meeting time
  • Sketched out drive train with Elliot
  • Plan to learn CAD:
  • Elliot will send me a few tutorials/exercises for some simple designs and then we'll work on something more relevant to our actual task
  • Will meet tomorrow at 6 pm at PG1 to start CAD

1/24/25 - Team Meeting & Subteam Meeting

  • Reviewed each subteam's tasking:
  • Mission and Trajectory planning: research on LIDAR/NAV2 and look into new GAZEBO package
  • Physical Simulation: look into new GAZEBO package and bring new members up to speed
  • Fault Detection: pick up where we left off last semester with sending keyboard commands from Command Center to HELICS broker to ROS2 Federate to ROS2 node to ROSGZ bridge to GAZEBO to trigger movement in GAZEBO simulation
  • Robot design: already made Gantt chart and we're on track so far, starting CAD and finishing up calculations today
  • Met up with Elliot at 6:00 pm to sketch out the motor mount image
  • Started by following a few basic Youtube tutorials to refresh my memory on Onshape controls and capabilities:

image

  • Found a bunch of practice 2D -> 3D modeling exercises on Too Tall Toby's website (same guy I watched on Youtube to get reacquainted): https://tootalltoby.com/practice/
  • Elliot and I discussed different motor mount designs and agreed that I would try a few variations next week

Week 4

1/28/25 - Subteam Meeting & Individual

  • Did working CAD session with Elliot to start modeling motor mount
  • Elliot found a motor to use, and I used the dimensions on the specification sheet to constrain my model: Motor image
  • I ran into issues with "sketch could not be solved," which I resolved by looking at the constraints I set up and deleting them systematically until I found the one that was the problem (reference link to onshape forum)
  • I continued building my onshape skillset but researching fillets, circular pattern, etc. to create holes and shapes in the most efficient way possible (minimal number of actions)
  • I also added tolerances to the support scoop shape under the motor and the holes for the bolts image image image Next to do: chat with Elliot/research other potential issues with the design and add "wings" on the sides for extra support (this will attach to wood)

1/30/25 - Individual & Class Meeting

  • Got some feedback about my design from Elliot and made the T-shape structure thinner and added a chamfer
  • Added countersink M3 holes to drill part into board image image
  • Chatted with Will and Elliot about next steps
  • Set a very ambitious deadline for completing CAD by next Thursday
  • Sabina will figure out whether Senior Design provides funding for projects tomorrow
  • Reviewed Elliot's motor calculations
  • Sabina will start on building the electronics holder (research electronic standoffs) for a modular design

1/31/25 - Team Meeting & Individual

  • Briefly provided updates for each subteam
  • Nodes and sensors will continue troubleshooting with humble for now until we finish and demo mission 1 -> we need a working simulation to ensure the transition to jazzy or other distributions is as smooth as possible
  • Gazebo team is waiting on Safiy (fault detection) on next steps with finishing up mission 1 (sending keyboard commands from control center federate to ros2 node to move robot in Gazebo)
  • Robot design will continue CAD design, should finish up in the next week
  • Joseph was having issues with running my docker container off the registry, so I sent him a couple troubleshooting links in the discord so that he can get sudo on there and build Gazebo image
  • Spoke with Senior Design professor and he told me that there is funding for projects, but all purchases parts need to be returned after the project is over
  • Will said that I should order parts via Senior Design because it'll be faster and then we'll get the final parts later (over the summer)
  • I found the senior design order form and sent it to Elliot to fill out for motors, motor controllers, and a teensy because he did the parts research for those: https://instructionallabs.ece.gatech.edu/ece-senior-design-support/

Week 5

2/3/25 - Individual

  • Joseph asked about extracting the Dockerfile from the container I put on the registry, so I pointed him to Dedockify, which is a tool I've used to reverse engineer images: https://github.com/mrhavens/Dedockify

2/4/25 - Individual

  • Standoffs are threaded and are good for stability, spacers are not threaded and just provide separation
  • Aluminum or brass standoffs provide the most structural support
  • 30-50 mm is usually enough clearance between layers to allow wire plugging/unplugging access
  • our biggest component in terms of size on the electronic stack is the RPI 3B+, which is 85 x 56 mm, and we need some space around the boards so that the components aren't right the edge of the platform, so our stack should be around 150 x 100 mm
  • consideration: in the TurtleBot burger, the motor mounts and motors are also inclosed in the stack at the base, which is something we could also do

2/6/25 - Class Meeting

  • Notes from Will:
  • Can do PWM with non-basic timers, so consideration for choosing a microcontroller
  • How to turn robot on and off
  • Will send list of preliminary purchases for hardware and software testing because can't get senior design funding until proposal is submitted at the end of the semester
  • Will design electronics base plate with captive nut design

Week 6

2/11/25 - Individual

  • Looked into captive nuts:
  • Fixed in position, making it easier to fasten in hard-to-reach areas
  • Permanently attached, reducing the risk of losing the nut
  • Maintains proper alignment in precise assemblies
  • Allows fastening when only one side is accessible
  • Can insert during 3D printing (embedded), press fit (best with PLA) (pocket), heat-set with soldering iron
  • Hole with some tolerance should be the size of the nut so you can slide it in, but should not be too loose that it can fall out under pressure or spin
  • typical tolerance: a clearance of about 5 thousandths of an inch
  • thicker materials needs a little more tolerance
  • can use epoxy or hot glue to hold it in place
  • Make sure the length of screws is appropriate for the thickness of the material. If the screw is too long, it might bottom out before fully tightening, leading to a weak connection --> basically leave a little extra room in terms of length to make sure entire length of screw fits
  • My problem is that each platform is 5 mm in thickness but the male heads of my female/male standoffs is 3 mm. So, the male thread isn't long enough to fully engage with the captive nut if it's mounted flush with the top surface of the platform
  • My solution is to counterbore from the bottom side of the platform, which will create a recess so the captive nut can sit deeper into the platform, which basically reduces the thickness at the mounting points
  • After counterboring, the captive nut's threaded portion will be closer to the top surface of the platform, so when I insert the 3 mm male thread of the standoff, it can fully engage with the captive nut, even though the platform remains 5 mm thick.
  • Will use M3 x 6 mm as the flange diameter of the captive nuts: https://www.amazon.com/Foyoram-Captive-Assemblies-Stainless-Phillips/dp/B0D1JCTP26?th=1
  • Am getting an issue with my dimensions after adjusting depth of counterbore to 3 mm image
  • Looking at example of Captive Nut FS Ovyl, I just realized I needed to merge with all: https://cad.onshape.com/documents/d40f3bfc679b364ebb9f35df/v/2241be3321d5be8e1abd7a0b/e/368eb0fdce8f6d196267ac93 image

2/12/25 - Individual

  • Researched/planned for power system design of robot
  • considerations for voltage/current requirements:
  • teensy (3.3V, but can usually accept 5V)
  • raspberry pi (5V)
  • LIDAR (depends, can vary from 5V to 12V)
  • motor drivers (12V+ for motors but may need 5V for logic control)
  • current draws differ significantly, especially during startup (ie. raspberry pi needs 2.5A, LIDAR needs 500mA+)
  • considerations for batteries:
  • Lithium Polymer has high energy density (high energy storage) and is lightweight but charging and monitoring require some overhead
  • Lithium Ion is more stable and good for longer runtimes
  • Nickel Metal Hydride is safer but has lower energy density (low energy storage)
  • Lead Acid is heavier but robust for high current draw
  • battery voltage needs to match highest required voltage and then be stepped down (ie. if motors needs 12V, then need a 12V battery with 5V regulator for raspberry pi)
  • need to decide desired operational runtime per single charge
  • high milliamp-hours -> longer runtime but heavier
  • considerations for voltage regulation:
  • buck converters are used to step down higher to lower voltage
  • boost converters are used to step up lower to higher voltage
  • buck-boost converters work in both directions if voltage fluctuates
  • high power efficiency is critical here because the robot is battery powered, so a switching regulator will be more efficient than a linear regulator (more expensive though and might need inductors/capacitors to filter noise)
  • considerations for power distribution:
  • either buy or design our own power distribution board (PDB), need to check for input voltage compatibility, current capacity, built-in regulators (?), connector types, and built-in protections (against overcurrent, fuses, EMI)
  • can also use DC-DC converters for voltage regulation
  • considerations for interfacing components:
  • logic level shifters for 3.3V to 5V conversion
  • matching communicational protocol (UART, I2C, SPI) between devices?
  • need to build bridge between ROS and motor drivers to run on raspberry pi
  • considerations for wiring/connectors:
  • thicker gauge for high-current components (ie. motors)
  • shield sensitive cables for LIDAR/sensors to avoid data corruption
  • considerations for thermal management:
  • heat sinks on the raspberry pi, motor drivers, voltage regulators, etc.
  • considerations for power-on/startup sequence
  • power raspberry pi first, then peripherals
  • use relay-controlled power switch + capacitors (?) to prevent high inrush current that could crash the raspberry pi and allow for smoother shut off of teensy and raspberry pi
  • MOSFET-based switch might actually be a better option for fast switching speed and better efficiency
  • overall setup
  • power supply and distribution by battery and PDB
  • power management by voltage regulators and MOSFET-based switching (controls power to PDB and selectively powers motors, sensors, LIDAR, etc.)
  • wiring and signal isolation with logic level shifters and shielded cables
  • low level hardware control by teensy (sensor data collection from encoders and IMU + motor control via PWM signals to motor drivers)
  • high level processing by raspberry pi (SLAM, LIDAR data processing, ros2)
  • ros2/serial bridge to facilitate data transfer between sensors, microcontrollers, and ros2

2/13/25 - Subteam Meeting & Advisor Meeting Meeting Minutes - VIP Autonomous Robot Location: Remote (Zoom) Date: 2/13/25 Time: 6:30 pm Attendance Sabina Sokol, Professor Aaron Lanterman Agenda Items

  • Establish cadence for check-ins with ECE advisor
  • Debrief on project scope and goals
  • Update on current progress and next steps
  • Note any feedback from advisor Problems
  • Briefly discussed current progress on CAD and HBOM, Lanterman approved
  • Everything is on track as per out Gantt chart, so no problems Action Items
  • Will finish up CAD design and HBOM this week
  • Will set up preliminary design review with VIP advisor (Will) to review CAD
  • Will start on SBOM next week
  • Will start on ROS/serial communication bridge next week
  • Schedule next meeting with Lanterman after next milestone (probably after proposal is completed) Other Notes
  • Professor Lanterman said that his job is really to make sure that my project has an EE component and that as long as my VIP advisors are content with my work, then he’s content.
  • met with Elliot and he helped me fix my mate connectors/fasteners to put the electronics platform into the main assembly
  • create subassembly and insert all parts
  • use fasten mates (not mate connectors!)
  • import into main assembly image
  • discussed options for how to accommodate for different electronics in the stack
  • Elliot proposed just design custom platforms for each electronic (Raspberry Pi, LIDAR, etc.)
  • I advocated for a platform design like the TurtleBot has with the waffle plates that have lots of holes and then design custom adaptors to actually screw in each component (see example under LIDAR in image below) image
  • We agreed that my design is more modular

Week 7

2/17/25 - Individual

  • Sent HBOM to Will to order parts
  • Added system design overview, design requirements, hardware requirements, development timeline, and future work sections under "III. Research and Progress" for our robot in the interim paper image

2/18/25 - Individual

  • Working on refining electronics platform such that it can modularly fit components
  • The two components that we're planning to have right now are the turtlebot LIDAR and raspberry pi 4B image image
  • the RPI has M2.5 screw holes
  • The specification for the LIDAR was a little confusing, and I was researching what screw would best fit, I came across tapped vs clearance holes
  • A tapped hole is a hole that has been drilled and then threaded using a tap tool, allowing a screw or bolt to fasten directly into the material without the need for a nut
  • The hole diameter for a tapped hole is smaller than the screw’s nominal diameter to allow for proper thread formation. In contrast, a clearance hole is an unthreaded hole that allows a screw or bolt to pass through freely
  • Clearance holes are typically used when fastening components together with a nut or when the screw threads into another part.
  • According to the schematic, the φ2.4 mm hole is not a tapped hole, meaning it is intended for a fastener to pass through without threading into the material
  • In standard ISO metric fastener charts, a 2.4 mm diameter hole aligns with a normal clearance fit for an M2 screw: https://amesweb.info/Screws/Metric-Clearance-Hole-Chart.aspx?utm_source=chatgpt.com#google_vignette image
  • If the hole were meant for an M2.5 screw, it would typically be slightly larger (around 2.6 mm or more for a clearance fit), making 2.4 mm the correct size for an M2 clearance hole
  • So, we need a design that can support both M2.5 and M2 for the LIDAR and RPI. Based on my discussion with Elliot last week, my idea for having a standardized platform and then designing adaptors for each component seems to be the best approach here. We need to make some array of tapped holes that are evenly spaced and then design adaptors so that we can screw in RPI and LIDAR -> this is what Will had in mind when we were discussing having a platform that fits a general mechanical/electrical specification so that we can fit any number of components
  • I'm feeling pretty lazy though so I currently have a platform that supports both a RPI (2.7 mm clearance holes) and the LIDAR (2.4 mm clearance holes). This is just a prototype, and so we want to get an MVP as soon as possible. The turtlebot designers probably spent a lot more time and resources devising their waffle board, though we could do something like that in the future

image image

  • Theoretically, we could add more holes via linear pattern, but this would be kind of nonsensical if we don't verify that adding these holes actually enables more hardware to be attached. That would require a lot more research and time, which we don't have right now, so it can be stretch goal for the final product next semester image image

2/20/25 - Class Meeting

  • Elliot filled me in on the first half of class, which was a foundational lecture on the components required to navigate a robot (how LIDAR works, what is NAV2 actually doing, what sensors do we need and how the data they gather is useful)
  • Reviewed our more-or-less finished CAD design with Will
  • Will gave a few suggestions on where to buy material for robot casing
  • Because this is very much a prototype, there's not really a need for a formal design review
  • Things to keep in mind:
  • where are batteries going to go?
  • how sophisticated do we want to get with the wiring?
  • this is a prototype, so rats nest will do
  • Sabina will start working on an electrical schematic (use WiringPi: https://github.com/WiringPi/WiringPi-Python)
  • Elliot will continue working on ROS2/Serial bridge

Week 8

2/24/25 - Individual & Subteam Meeting

  • Worked on slides for interim presentation on Thursday image image image image image image image image
  • For the security posture/assessment, I looked at 3 different case studies of ROS-specific exploits that would realistically impact our inspection robot and cause harm to the power grid it is supposed to be supporting
  • The Man-in-the-Middle attack seemed pretty obvious because ROS topics and messages are not encrypted by default, so anyone could theoretically intercept and potentially modify the data being sent between the robot and the control center or between the robot and the raspberry pi
  • I thought the arbitrary code execution and unauthorized/remote control attacks were quite interesting. It seems like the solution is to isolate and secure the network, though I wonder what the performance drawbacks are, as cryptography requires some compute power that would drain our batteries faster. In the future, I might do some more concrete analysis of power and time requirements. The reality is that OT systems are just not secured for the most part because they can't be brought offline to update and it just requires more resources to secure
  • Chatted with Elliot about changes we need to make to our CAD after building our HBOM
  • Need space for batteries + are batteries on the list actually enough? need 3S
  • bearings are thicker than we anticipated, can do an embedded print for fun but more realistic approach is to design some sort of clasp so they don't slide out even though they are listed as snap fit
  • Overall, looking at our checklist in the presentation, we've made significant progress! I will continue working on the electrical schematic and verifying the voltage regulation and logic level shifting requirements and Elliot will continue working on the software bridge, which may take a little longer than expected and is a little out of comfort zone so I'll support when I'm done with my task

2/26/25 - Individual

  • Verified all of the components we ordered (batteries, encoder, motors, microcontrollers, logic level shifters, motor controller, LIDAR, and buck-boost converters) are compatible with each other electrically and logically
  • Made a crude mock-up of the system to visualize connectivity of components: image
  • LiPo Battery (22.2V)
  • Connected to: Buck-Boost Converter input
  • Buck-Boost Converter
  • Input: LiPo Battery
  • Outputs:
  • 12V to Motor Controller
  • 5V to Raspberry Pi, Teensy, LIDAR, Logic Level Shifter, and Encoders
  • Raspberry Pi
  • Power: 5V from Buck-Boost Converter
  • Connected to:
  • LIDAR (via UART)
  • Teensy (via UART or SPI for data exchange)
  • Teensy
  • Power: 5V from Buck-Boost Converter
  • Connected to:
  • Encoders (digital input pins)
  • Logic Level Shifter (3.3V side)
  • Raspberry Pi (for data exchange)
  • Encoders
  • Power: 5V from Buck-Boost Converter
  • Connected to: Teensy (digital input pins)
  • Mechanically coupled to: 12V Motors
  • LIDAR Sensor
  • Power: 5V from Buck-Boost Converter
  • Connected to: Raspberry Pi (via UART)
  • Logic Level Shifter
  • Low voltage side (3.3V): Connected to Teensy
  • High voltage side (5V): Connected to Motor Controller
  • Power:
  • 3.3V from Teensy
  • 5V from Buck-Boost Converter
  • Motor Controller (BTS7960)
  • Power: 12V from Buck-Boost Converter
  • Control inputs: Connected to Logic Level Shifter (5V side)
  • Outputs: Connected to 12V Motors
  • 12V Motors
  • Connected to: Motor Controller outputs
  • Mechanically coupled to: Encoders

System Operation:

  1. Raspberry Pi processes LIDAR data and determines movement needs
  2. Raspberry Pi communicates desired motion to Teensy
  3. Teensy generates appropriate PWM signals
  4. Logic level shifter converts Teensy's 3.3V signals to 5V
  5. Motor controller receives 5V signals and controls 12V motors
  6. Encoders provide feedback on motor movement to Teensy
  7. Teensy uses encoder data to adjust motor control for precise movement
  8. Teensy sends movement data back to Raspberry Pi
  • created slide for midterm presentation: image

2/27/25 - Class Meeting

  • Presented interim slides
  • Feedback from Will: put mission description at the beginning, good explanations of how everything works together, keep exploring sensors

2/28/25 - Team Meeting

  • No new updates from other teams
  • Elliot and I will troubleshoot the micro-ROS tutorial (Elliot was experiencing an issue with not being able to see the ping and pong topics when running ros2 topic list after launching an example with a microros agent, ros2 node, and microros node)

Week 9

3/4/25 - Individual & Subteam Meeting

  • I've finished the rough draft of my proposal for senior design, which encompasses mine and Elliot's robot design work in this VIP
  • This final proposal is due the week of April 14th I believe, so I have some time to polish it and get feedback from Will, Sam, and Dr. Lanterman
  • I will probably revise it later this week or early next week
  • Pair programmed with Elliot later in the day to troubleshoot his issue with not seeing the ping and pong ros topics when running this micro-ros tutorial: https://micro.ros.org/docs/tutorials/core/first_application_linux/
  • He successfully ran colcon build and launched the micro-ros agent and ros2 node and we saw debug messages saying ros2 topics were created and what seemed to be successful sending and receiving of "pings" and "pongs," so we decided this was not an issue with the configuration of the micro-ros agent because communication seemed to be working
  • After some googling, we found some posts indicating similar issues:
  • We realized that the issue was that Elliot had exported ROS_DOMAIN_ID via his .bashrc file when doing the TurtleBot tutorial earlier, and commenting that out allowed us to successfully observe the "pings" and "pongs" image
  • While this works right now, this may become an issue in the future if we need to run the microros agent at the same time as a robot which requires a ros domain id, but an alternative solution suggested in multiple forums was using docker to run the micro-ros agent with a command like this (note that this is for an example with a teensyduino, which is not quite our use case but similar enough): docker run -it --rm -v /dev:/dev --privileged --net=host microros/micro-ros-agent:foxy serial --dev /dev/serial/by-id/usb-Teensyduino_USB_Serial_6014540-if00 -v6
  • One nice thing though is that we ran the micro-ros example on the humble distribution used by our VIP team, which is a relief that we do not need to try and migrate over from foxy ourselves as we previously thought
  • Next steps: our use case is having an encoder sending data to the Teensy, which will publish that data to a ros2 topic that the Raspberry Pi can also see and process, so we now need to see if we can replicate the micro-ros tutorial between a Teensy and an RPi, with the micro-ros node on the Teensy and the ros2 node and micro-ros agent (acts as middle-man) on the RPi

3/6/25 - Class Meeting

  • I will continue revising my senior design proposal
  • Elliot will continue building the software bridge and I will help as needed

Week 10

3/10/25 - Individual

  • Began deep cleaning my senior design proposal and cut down the executive summary from 2.5 pages to 1 page and revised the rest of the sections to remove redundant wording image

3/11/25 - Class Meeting

  • Most people were gone because of spring break, and not much progress has been made because of midterms
  • Got added to the senior design parts order through Will, so I can manage and receive orders for me and Elliot

3/12/25 - Individual

  • Checked with senior design professor about including part order links in references section because there's no IEEE format for those image

Week 11 - Spring Break!

Week 12

3/25/25 - Individual

  • Reached out to Sam, Will, and Dr. Lanterman about revising my senior design proposal
  • I need to have 2 more meetings with Dr. Lanterman, so I'll schedule those once I get some feedback image
  • Checked in with Elliot and he's been swamped with midterms and big homework projects, so he hasn't made much progress on the software bridge
  • I'll coordinate with him to see if we can do another pair programming work session this week or next week
  • I also got accepted for the research poster at the Undergraduate Research Symposium, but I have my ECE 4156 professor just announced a midterm during my timeblock. I reached out and was putting on the waiting list for a research talk earlier in the day if a slot opens up

3/27/25 - Subteam Meeting

3/28/25 - Team Meeting

  • I was about to board a flight to nationals so I provided an update about my and Elliot's progress on the CAD and platformIO
  • Elliot and I set up a work session next Tuesday (4/1) to continue working on the software component of the project
  • I also need to reach out the person at GTRI managing my charge code for the VIP PURA because I think getting close to running out of hours

Week 13

4/1/25 - Individual & Subteam Meeting

  • Elliot and I agreed last week that I need to get Gazebo and NAV2 working to begin simulating the LIDAR and navigation of the robot based on feedback from our sensors
  • I pulled down the image with the ROS-Gazebo bridge with docker pull ghcr.io/cps-vip/helics-ros2-gz:latest and then ran it with docker run -p 6080:80 --security-opt seccomp=unconfined --shm-size=512m ghcr.io/cps-vip/helics-ros2-gz:latest (based on command for the tiyroh ros/humble image I initially worked with)
  • I read to Joseph's notebook to get a better understanding of what progress he's made on integrating ROS, HELICS, Gazebo, and NAV2
  • It seems like he's been communicating with Natalie and Nguyen about the NAV2 installation and Nguyen got NAV2 working on a ROS Jazzy VM, and Joseph replicated this installation by doing it in his own VM and ran a basic NAV2 example
  • I reached out to Joseph to ask if he could put an image of his container on the registry so I can work off of it, and also asked him whether he wanted to work together on getting LIDAR/SLAM via Gazebo/NAV2 because that's a major component of the final product
  • Elliot and I need to clarify later today what needs to go through ros/microros between the Teensy and the RPI and create a diagram of the communication and software requirements
  • Update: Joseph put his container on the register and I was able to run the example he ran with ros2 launch nav2_bringup tb3_simulation_launch.py headless:=False!

image

  • What runs on Teensy:
  • takes in encoder data and sends that through microros
  • takes in commands from rpi for motor speed via microros and spits out pwm signal to motor controller
  • rpi has microros agent and regular ros node, teensy has microros node
  • What runs on RPI:
  • ros installation (probably Jazzy) with ros, gazebo, nav2 via docker or natively
  • rpi just communicates with lidar over usb and has libraries for specific lidar
  • key is to have robot in space with lidar as it's "seeing" things via gazebo
  • using nav2 for pathfinding Next steps for Sabina:
  • go through NAV2/Gazebo tutorial to see sample pathfinding (how do we set waypoints etc.)
  • see how lidar is visualized
  • Joseph will make robot in gazebo and use nav2 and slam toolbox to use lidar to sense the world and reference a nominal map (basically explore space to generate world map before doing pathfinding), then pathfind to the destination
  • In the future, do lifelong mapping, which updates map if space drastically changes

image

image

4/3/25 - Class Meeting

  • Chatted with Will to update about parts ordering (I should pick everything up)
  • Elliot and I agreed to chat with the navigation team: they will get the jazzy container up and running with the container and then will create a simple 4 wheeled, rectangular robot that can sense its surroundings with a simulated lidar sensor + navigate around if possible
  • Challenges with SLAM and navigation: should be pretty plug and play when driving on flat surface (gets very confused when z-axis calcs are required)
  • Writing robot level controller for when you deviate from the path, depends on number of actuators linked

Week 14

4/7/25 - Subteam Meeting

  • Met up with Elliot to discuss reordering of Amazon parts
  • H-Bridge motor drivers were unavailable, so Elliot found an Adafruit part after adjusting specs for amperage - has screw terminals
  • Need to pick new battery with 1 hour of operation time but max voltage is 11.1V so will never get to motor max speed - XT-60 connector
  • Now need to connect the two together and split the current, checked if battery can handle current and it can based on capacitance and amp-hours so yay
  • Found XT60 pigtails but need splitter

Need 2x https://www.adafruit.com/product/3190

New battery (x1) https://hobbyking.com/en_us/turnigy-rapid-6000mah-3s-11-1v-100c-lipo-battery-pack-w-xt60-connector.html

Battery to controllers (x1) https://hobbyking.com/en_us/genuine-xt60-female-connector-w-10cm-12awg-silicone-wire-5pcs.html

Battery connector splitter (x1) https://hobbyking.com/en_us/xt60-harness-for-2-packs-in-parallel-1pc-2.html

Battery charger (x1) https://www.getfpv.com/isdt-pd60-60w-6a-1-4s-usb-c-input-battery-charger.html?gc_id=21805212384&g_special_campaign=true&gad_source=1&gclid=Cj0KCQjw782_BhDjARIsABTv_JA-i1qqLeX7uocrc-UoRKHOan0r7Agr7NAicR6BNmf42NvB08BQjIgaAo8EEALw_wcB

Equivalent amazon listing: https://www.amazon.com/dp/B08F7C1T2T/

4/10/25 - Class Meeting

  • Checked in with navigation team and they've made good progress with adding LIDAR/SLAM into GAZEBO and importing a robot + substation into the environment
  • The current substation model is really complex and is causing the VMs to lag, so ideally we'd like to pair it down to a lower poly model. We also will first run this in a classroom environment, so it's no necessary to have a substation and instead have some rough objects, etc.
  • Got feedback from Ayleen about our new links for parts and they don't have a relationship with Hobby King so I told her that we would like to order from Amazon even with the restrictions GTRI has
  • Will try to pick up parts tomorrow
  • Pinged Dr. Lanterman again about receiving feedback about my proposal

4/11/25 - Individual

  • Picked up the LIDAR, RPI, and something from Mouser. They said they had multiple parts from DigiKey so I'll need to ask where to they delivered those

  • Got feedback from Lanterman and Sam about my proposal: image

  • Sam said to adjust the section about goals and constraints to have goals first before my explanation of technical specifications

  • I still need to schedule two more meetings with Dr. Lanterman to fulfill the senior design requirements, so I reached out to him about that

  • Sam also reviewed my URS presentation and provided suggestions to stay under 10 minutes by glossing over some of the details if things are moving a little slow. There's always more technical detail to get into if there's time left over or via questions people have.

Week 15

4/14/25 - Individual

  • Finished revising Senior Design proposal based on Sam's and Dr. Lanterman's feedback and submitted it

4/17/25 - Class Meeting & Individual

  • Picked up parts from CRB 426A and hauled them over to Elliot's apartment
  • Elliot has started printing more parts
  • I need to bug him again to find the new 3S battery and the connectors we need on Amazon this week
  • Presented at the Undergraduate Research Symposium with Joseph and Safiy and it went really well! I'm excited for the feedback
  • Presented VIP final presentation, main feedback was just excitement about all the pieces coming together and now assembling everything into one cohesive simulation and system

Week 16

4/21/25 - Individual

  • Joseph made the Spring 2025 Final Paper document in Overleaf

  • Revised Robot Design section to include update on current progress and future work

  • Added screenshot of robot cad from interior and exterior view image

  • picked up motor drivers from CRB 426A

  • need to bug Elliot again about finalizing all parts orders before we leave for the summer

Fall-2025

Contact Information

  • Project Name: VIP Autonomous Robot/Autonomous Maintenance of Power Grid Using Robotic Systems
  • Team Lead: Sabina Sokol (Only Senior Design member)
  • Email: [email protected]
  • Advisors: Aaron Lanterman (ECE), Will Stuckey (GTRI)

Deadlines

[X] - September 25, 2025: Update HBOM & order parts [X] - October 15, 2025: Confirm CAD and finish 3D printing components [X] - November 3, 2025: Finish initial mechanical and electrical assembly [X] - November 17, 2025: Finish writing firmware [] - November 21, 2025: Finish testing PID controller [X] - December 1, 2025: Finish preparing Senior Design Expo materials

Week 1

8/21/25 - Class Meeting

  • Joined remote first meeting via Discord
  • Submitted Welcome Quiz and Subteam quizzes
  • Reached out to Sam and Will a few days ago on discussing the end goal for my Senior Design product

Week 2

8/26/25 - Meeting with Sam and Will

  • Discussed realistic timeline for building and debugging an autonomous robot as planned, and it would require 20 hours of work per week minimum, which is not something I have the bandwidth for this semester
  • Unfortunately because I do need to have something done for the senior design expo this semester, I will try to come up with a smaller scope project that is still relevant to the robot, preferably security/assurance related based on my research interests
  • Confirmed Elliot dropped off all delivered parts to Will's office at GTRI
  • Idea: bootloader on microcontroller (STM32) in Rust -> will talk to Will on Thursday

8/28/25 - Class Meeting

  • Reviewed basics of co-simulation, project goals, etc.
  • Broke up into teams
  • Set up team meeting time via when2meet: Wednesdays at 12:00 - 12:30 pm on Discord

Week 3

09/02/25 - Individual

  • Downloaded rust and setup up the rust-analyzer lsp in neovim
  • Bookmarked offline rust book and began going through tutorials
image image image image

09/03/25 - Team Meeting & Individual

  • Met on Discord with team to explain kickoff presentation guidelines to newcomers and explain tasking for this semester
  • Added secure bootloader slides
image image image image image
  • Will get boards from Will tomorrow and figure out what machine to develop on

09/04/25 - Class Meeting

  • Presented Kickoff Presentation
  • Overall, Will and Sam said this was the best kickoff presentation they've seen from our team because it clearly highlighted what the short term and long term goals were, what the milestones are, and how each subteam is working towards the milestones
  • Will meet with Lanterman tomorrow to discuss further logistics with the shift in my senior design proposal

09/05/25 - Individual & Advisor Meeting

  • Met with Lanterman @ 6:00 pm over Zoom
  • Basically Lanterman anticipated the downscope but is weary of shifting towards the bootloader idea because it's more software based and uses a predefined piece of hardware (STM32H7) instead of building/designing the hardware myself
  • New goal for this semester is to assemble robot and have it drive around in a pre-programmed pattern, so that eliminates the stress of getting the LIDAR to work and just focuses on getting the PID loop with the encoder signal and PWM for motor drivers working, which seems a lot more doable
  • Updated Will on new project plan over Slack

Week 4

09/09/25 - Team Meeting

  • Gave status update on new goal for robot design this semester
  • Asked Shrayes and Nguyen (subteam leads) to provide updates on their progress
  • Nguyen sent out links to the container registry where the latest Docker image with ROS, HELICS, GLD, and Gazebo + link to tutorial video series on ROS for new people onboarding

Team Meeting Recap:

New members: please review ROS2 documentation/tutorial videos + pull down Docker image from container registry (links provided by Nguyen above) before our team meeting next week

Security Subteam: working on latest Docker image Shrayes is reviewing previous work on MITM within ROS, will begin replicating attacks soon

Robot Design: Sabina is 3D printing and ordering missing components this week

Navigation and Fault Detection Integration: working on Docker image with ROS2 Jazzy, NAV2, and Gazebo only Nguyen is looking at setting waypoints via code instead of GUI

Everyone: fill out notebook self-evaluation (due at 3:00 pm tomorrow!)

09/10/25 - Individual & Class Meeting

  • Brought my TPU/PLA (stolen from Elliot) and previously delivered robot parts from Will's office to the hardware lab at GTRI
  • Verified CAD by using calibers to measure encoder holes (2.87 mm in diameter, so the original estimate of 3.4 mm holes in the encoder mount are fine)
  • Printed 2 encoder mounts and 4 shaft couplers
  • Verified that we have the right batteries we need (2500 mah, 12V, yellow connectors)
Screenshot 2025-09-15 at 1 58 40 PM Screenshot 2025-09-15 at 2 00 37 PM Screenshot 2025-09-15 at 2 01 34 PM

09/11/25 - Individual

  • Picked up encoder mounts and shaft couplers

Week 5

09/17/25 - Individual & Team Meeting

  • started looking into control theory and how to write/tune a PID loop with our teensy 4.1 and taiss e38s6 600 p/r 24g rotary encoder

basics of what will happen:

  • encoder produces two quadrature signals, A/B, which you can derive position or velocity from with counts or counts/sec respectively
  • our encoder is 600 P/R, so it generates 600 distinct electrical pulses for every single full 360-degree rotation of its shaft. this is a pretty high resolution, meaning that it allows for finer control and more accurate measurements of rotational speed, angle, and linear displacement, which is what we want
  • Teensy has hardware quadrature support and libraries to read channels
  • teensy will convert counts to speed in terms of counts per second or RPM, and this will be used as the feedback for the control loop that outputs a motor command
  • the controller output will be mapped to a PWM duty between 0 and the max PWM value and that will be sent to the motor driver

key notes:

  • absolutely need a logic level shifter because the encoder operates at minimum 5V and teensy is 3.3V
  • taiss e38s6 600 p/r 24g rotary encoder connection: white = A phase, Green = B phase, red = power +, black = V0 ; Note: AB two -phase outputs must not be connected directly to VCC, otherwise, they will burn the output transistor.
  • will use QuadEncoder lib for Teensy 4.x; https://github.com/mjs513/Teensy-4.x-Quad-Encoder-Library
  • mapping for encoder channels:
Screenshot 2025-09-17 at 11 40 31 AM

important things about PI controller:

  • Kp is proportional gain, which is how strongly the controller reacts to the current errors, which is the setpoint/desired speed - measured speed. So if Kp is too low, then the motor responds sluggishly and if it's too high, then the motor oscillates or vibrates. It's basically a gas pedal pressure proportional to how far off speed you are
  • Ki is integral gain, which fixes the steady-state error by accumulating past error over time. So if the motor always runs a little slower than requested due to friction or load, then Ki keeps adding correction until it eliminates that offset. If Ki is too high, then motors will oscillate or overshoot. Should implement "clamp" to prevent wind up
  • since encoder is 600 P/R, if we count both edges of A/B channels, that's 4x decoding, or 2400 C/R
  • basic equation u = Kp * error + Ki * integral -> if u is positive, then motor needs to spin forward, if u is negative, then motor needs to spin backward, |u| dictates PWM duty cycle
  • PWM pin will set how much voltage/duty cycle the motor gets (0 - 100%)
  • DIR pin will set which way motor spins, so you don't need to generate negative PWM values because you can just flip the DIR pin
  • Teensy has 8-bit resolution, so expects 0-255 (255 is MAX_PWM) analog values

basic u -> PWM + DIR conversion:

bool forward = (u >= 0);
float pwmVal = fabs(u);
if (pwmVal > MAX_PWM) pwmVal = MAX_PWM;

digitalWrite(DIR_PIN, forward ? HIGH : LOW); // tells driver forward/backward
analogWrite(PWM_PIN, (int)pwmVal); // sets duty cycle (speed/torque)
if (pwmVal > MAX_PWM) pwmVal = MAX_PWM;

if (u >= 0) {
  analogWrite(RPWM, (int)pwmVal); // forward
  analogWrite(LPWM, 0);
} else {
  analogWrite(RPWM, 0); // backward
  analogWrite(LPWM, (int)pwmVal);
}
  • have R_EN and L_EN pins that must be driven HIGH to let module accept PWM, can permanently tie HIGH to VCC or use code (probably saferyes in case I need to disable the driver)
  • to make this a PID control loop, p responds to how far you are from the target, i responds to how long you've been off target, and d (derviative) responds to how fast you're moving toward/away from target
  • derivative is useful to prevent overshooting and oscillations, so it's the rate of error change, u = Kp * error + Ki * integral + Kd * derivative now

Plan to tune:

  • start with Ki = 0, Kd = 0, and increase Kp until motor responds quickly but oscillates a little
  • add Kd to dampen the oscillation
  • add Ki to reduce residual error

Useful Links for Future:

Team Meeting

  • all newcomers have gone through at least some of the ROS videos, all have or will pull down and build Docker image from container registry
  • will debug any Docker issues tomorrow during in class meeting

09/18/25 - Individual & Class Meeting

  • I was flying out during class time so I pinged Will to remind him to order the bearings and encoder and also asked him to bring the router and switch for Shrayes

Week 6

09/24/25 - Individual & Team Meeting

  • Received confirmation from Will that parts were ordered and shipped
  • It's midterm season so not all of progress was made this past week
  • Met with Gwen at 4:00 pm in PG1 to help her troubleshoot her Docker issues on Windows
  • She was getting a "docker not found" error when attempting to run "docker --version" in the terminal
  • We confirmed her Docker and Docker Desktop installation with the official documentation: https://docs.docker.com/desktop/setup/install/windows-install/
  • We confirmed she had WSL2
  • We realized that she needed run her docker commands from "Command Prompt", not Terminal (wrapper for Powershell)
  • Confirmed she could open Docker Desktop
  • She created her personal access token for GHCR
  • Pulled down latest docker container (Joseph's from laster semester) from the registry: https://github.com/orgs/cps-vip/packages with docker pull ghcr.io/cps-vip/cps-vip-vm:latest
  • I later got a message on Discord from her with an error indicating an architecture issue, so I suggested trying to pull down one of the later images

09/25/25 - Class Meeting

  • Participated in the lab led by Will to discover what kind of network we were looking at in Wireshark
  • key takeaways:
  • Having a networking configuration where a bunch of devices/IP talk to a multicast device/IP who then directs traffic to other devices/IP is a common cyber physical system network structure
  • Communication was over UDP because in a CPS, real-time (or as close to it as possible) transmissions are critical and establishing TCP sessions between each device with the error checking, etc. hinder communication in a way that isn't desirable because it's more important to have the most up-to-date information most of the time rather than assurance that all data is received all of the time but not necessarily in the most timely manner as with TCP

09/27/25 - Individual

  • Completed Chapters 4, 5, and 6 of the Rust book
  • I now have a better grasp of the borrow checker as well as how awesome result types
  • I'm still at the stage where I believe Rust is magical and I feel superior to 99% of computer majors just for learning it and coding strictly in my nvim/zellij (tmux but rust-based so it's better) setup

Week 7

10/1/25 - Team Meeting & Individual

  • Everyone provided progress updates, not much progress because of midterm season
  • I sent a link to the midterm paper draft and explained what additions need to be made; Shrayes will create a new security section to discuss his work and Nguyen will tack on his results to the navigation section because we haven't tied in the fault detection work from Safiy yet
  • Gwen will continue troubleshooting her Docker issue (not sure why she's getting an architecture issue since Docker containers are supposed to be architecture agnostic)
  • I will go to GTRI tomorrow and print the bearing mounts + start working on programming the Teensy
  • Discussed a plan of action for me with Elliot: print bearing mounts -> test all electronics components individually in the invention studio/GTRI -> assemble electronic and mechanical components -> tune PID controller (first using Arduino IDE/C++ then Rust) -> write state machine to get robot to drive around in basic pattern (square)

10/2/25 - Individual & Class Meeting

  • Went to GTRI and began printing M and F bearing mounts with a pause print to insert the bearings (picked up from Will)
  • Installed Arduino IDE and added Teensy board package
  • Successfully programmed teensy with Blinky example
  • Wrote base PID control loop:
#include <Encoder.h>
#define ENCODER_A 2
#define ENCODER_B 3
#define RPWM 5
#define LPWM 6
#define R_EN 7
#define L_EN 8
 
const int counts_per_rev = 600 * 4;  // 600 CPR * 4x decode = 2400 counts/rev
const float dt = 0.01;               // control loop period [s]
 
float Kp = 0.6;    // proportional
float Ki = 0.02;   // integral
float Kd = 0.1;    // derivative
 
Encoder enc(ENCODER_A, ENCODER_B);
float integral = 0;
float last_error = 0;
 
long target_position = 3 * counts_per_rev;  // 3 revolutions forward
 
void setup() {
  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);
  pinMode(R_EN, OUTPUT);
  pinMode(L_EN, OUTPUT);
 
  digitalWrite(R_EN, HIGH);
  digitalWrite(L_EN, HIGH);
 
  Serial.begin(115200);
}
 
void loop() {
  static elapsedMillis timer;
 
  if (timer >= dt * 1000) {
    timer = 0;
 
    long current_position = enc.read(); // read current position
    long error = target_position - current_position; // compute error
    integral += error * dt; // integrate error for Ki
    float derivative = (error - last_error) / dt; // derivatie term (rate of error change)
    last_error = error;
 
    float control_signal = Kp * error + Ki * integral + Kd * derivative; // PID control law
 
    int duty = constrain(abs(control_signal), 0, 255); // map control signal to PWM duty (0-255)
 
    if (control_signal >= 0) {
      analogWrite(RPWM, duty);
      analogWrite(LPWM, 0);
    } else {
      analogWrite(RPWM, 0);
      analogWrite(LPWM, duty);
    }
 
    Serial.print("Target: "); Serial.print(target_position);
    Serial.print("  Current: "); Serial.print(current_position);
    Serial.print("  Error: "); Serial.print(error);
    Serial.print("  Control: "); Serial.println(control_signal);
  }
}
  • basic wiring diagram to hook up Teensy 4.1 to BTS7960 board (H-bridge module)
[Motor Supply +12–24 V]  ---> BTS7960 VCC
[Motor Supply GND]       ---> BTS7960 GND --- Teensy GND

[Motor +] ---> BTS7960 M+
[Motor -] ---> BTS7960 M-

Teensy pin 5 (PWM) ---> BTS7960 RPWM
Teensy pin 6 (PWM) ---> BTS7960 LPWM
Teensy pin 7       ---> BTS7960 R_EN
Teensy pin 8       ---> BTS7960 L_EN
Teensy GND         ---> BTS7960 GND

Encoder A ---> Teensy pin 2
Encoder B ---> Teensy pin 3
Encoder VCC ---> 5 V (encoder outputs are NPN open-collector, add external pull-up resistors from each output (A, B) to 3.3 V (Teensy logic))
Encoder GND ---> Teensy GND
  • I talked to Elliot for feedback and he said: "So I think you might want the angular velocity to be the control signal and output, that way you can just tell it to go to a certain speed and not have overflow issues. Later you can wrap it in another pid loop to control position if you want. And then you’ll damp the acceleration and velocity, so like limit the max speed and the motor power to not blow anything up"
  • so the new workflow is reads encoder → computes RPM → filters it → ramps the commanded RPM → runs a PI controller on RPM → limits/saturates/slew-limits a signed PWM value → writes PWM to BTS7960, which will ensure that the robot doesn't try to accelerate too quickly and prevents overflow issues when writing new PWM values
  • to this, I need to keep track of the last count and last speed
  • I also want a simple state machine so I can move forward and back and forth autonomously so I don't have to input commands serially, so that will determine the target speed depending on whether we want to go forward, backward, idle, or stop/done
  • then we'll have a ramped speed to slow go up to the target speed so that we don't accelerate too quickly
  • the PI loop with compare the ramped speed to the actual speed and adjust the PWM
  • the motor driver will get the PWM and direction
  • once the encoder delta equals the target counts it stops and goes to the DONE state which just keeps repeating
volatile long encoderCount = 0;   // global encoder count
int lastA = 0;

#define ENCODER_A 2   // encoder channel A
#define ENCODER_B 3   // encoder channel B

// 600 P/R * 4X decode = 2400 counts per revolution
const long COUNTS_PER_REV = 2400;

#define RPWM 5
#define LPWM 6

float Kp = 0.5;    // proportional gain
float Ki = 0.05;   // integral gain

float targetSpeed = 0;   // desired speed in counts/sec
float actualSpeed = 0;   // measured speed
float integral = 0;

unsigned long lastSpeedTime = 0;
long lastCount = 0;

enum State { IDLE, FORWARD, BACKWARD, WAIT };
State currentState = IDLE;

long startCounts = 0;
long targetCounts = 0;
int moveSpeed = 1500;   // counts/sec target speed
int accelLimit = 200;   // max accel (counts/sec per update)

float rampedSpeed = 0;

const int moveRevs = 5;   // number of revs each way
const long moveCounts = moveRevs * COUNTS_PER_REV;
const unsigned long waitTime = 2000; // wait at ends (ms)

unsigned long waitStartTime = 0;

void encoderISR() {
  int A = digitalReadFast(ENCODER_A);
  int B = digitalReadFast(ENCODER_B);

  if (A != lastA) {
    if (A == B) encoderCount++;
    else encoderCount--;
  }
  lastA = A;
}

void setMotorPWM(int pwm) {
  pwm = constrain(pwm, -255, 255);

  if (pwm >= 0) {
    analogWrite(RPWM, pwm);
    analogWrite(LPWM, 0);
  } else {
    analogWrite(RPWM, 0);
    analogWrite(LPWM, -pwm);
  }
}

void updateSpeedControl() {
  unsigned long now = millis();
  if (now - lastSpeedTime >= 20) { // 50 Hz update
    long count = encoderCount;
    long delta = count - lastCount;
    lastCount = count;

    actualSpeed = (float)delta * 1000.0 / (now - lastSpeedTime); // counts/sec
    lastSpeedTime = now;

    if (targetSpeed > rampedSpeed) {
      rampedSpeed += accelLimit;
      if (rampedSpeed > targetSpeed) rampedSpeed = targetSpeed;
    } else if (targetSpeed < rampedSpeed) {
      rampedSpeed -= accelLimit;
      if (rampedSpeed < targetSpeed) rampedSpeed = targetSpeed;
    }

    float error = rampedSpeed - actualSpeed;
    integral += error * (0.02);   // 20 ms loop
    float output = Kp * error + Ki * integral;

    int pwmOut = (int)constrain(output, -255, 255);
    setMotorPWM(pwmOut);
  }
}

void startMove(State dir, long counts) {
  startCounts = encoderCount;
  targetCounts = counts;
  currentState = dir;
}

void updateStateMachine() {
  switch (currentState) {
    case IDLE:
      targetSpeed = 0;
      startMove(FORWARD, moveCounts);
      break;

    case FORWARD:
      targetSpeed = moveSpeed;
      if (encoderCount - startCounts >= targetCounts) {
        targetSpeed = 0;
        currentState = WAIT;
        waitStartTime = millis();
      }
      break;

    case BACKWARD:
      targetSpeed = -moveSpeed;
      if (startCounts - encoderCount >= targetCounts) {
        targetSpeed = 0;
        currentState = WAIT;
        waitStartTime = millis();
      }
      break;

    case WAIT:
      targetSpeed = 0;
      if (millis() - waitStartTime >= waitTime) { // flip direction after waiting
        if (encoderCount >= startCounts) {
          startMove(BACKWARD, moveCounts); // finished forward -> go backward
        } else {
          startMove(FORWARD, moveCounts); // finished backward -> go forward
        }
      }
      break;
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(ENCODER_A, INPUT_PULLUP);
  pinMode(ENCODER_B, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCODER_A), encoderISR, CHANGE);

  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);

  lastSpeedTime = millis();

  startMove(FORWARD, moveCounts);
}

void loop() {
  updateStateMachine();
  updateSpeedControl();

  static unsigned long lastPrint = 0;
  if (millis() - lastPrint > 500) {
    Serial.print("State: "); Serial.print(currentState);
    Serial.print("  Encoder: "); Serial.print(encoderCount);
    Serial.print("  TargetSpeed: "); Serial.print(targetSpeed);
    Serial.print("  RampedSpeed: "); Serial.print(rampedSpeed);
    Serial.print("  ActualSpeed: "); Serial.println(actualSpeed);
    lastPrint = millis();
  }
}

Week 8

10/6/25 - Individual

  • Played around with print settings and learned the hard way that to print embedded prints you need to put components on their sides so that the embedded element doesn't interfere with the nozzle
  • Ran out of bearings because in our original design we only had one encoder and only the back wheels were driven but we redesign so that all wheels are now driven so it'll be easier to do the PID control for turns, ordered some more
  • finished printing all bearings mounts

10/8/25 - Team Meeting

  • Updated my bootloader and robot assembly slides to reflect my progress on both

10/9/25 - Class Meeting

  • Presented midterm presentation and received positive feedback about our structure and progress, we're right on the cusp of getting our first mission completed now that Nguyen successfully was able to set waypoints via code, so now he just needs to create a ROS topic and publish a set of coordinates from the Python Control Center federate to NAV2 to get the robot to drive there

Week 9

10/13/25 - Individual

  • Acquired MDF 2x4 ft and used a jigsaw in the wood room of the invention studio to cut into a 16 by 24 in piece
  • Invention studio doesn't have the greatest selection of screws, mostly have countersunk
  • The tolerance on the rotary shafts was too small and it was a really tight fit into the embedded bearings so I ordered 4 mm shafts instead; they were also way too long for our design so I ordered ones that were half as long (100 mm)
  • Found out that the bolt circle of the encoder mounts was 4mm off, so reprinted those and confirmed the encoders fit nicely now
  • I also ordered some longer belts because our current belts are too short and not everything will fit in our original model
  • Asked Will if GTRI has a bunch of metric screws and there are a bunch in 223
  • Going to try reassembling next week on Monday IMG_3223

10/15/25 - Team Meeting

  • Updated team on progress with assembly
  • Not really any other updates from anyone else

10/16/25 - Class Meeting

  • Confirmed orders were placed and shafts have arrived, just waiting on the longer belts

Week 10

10/20/25 - Individual

  • Ordered a bunch of superglue to start placing everything down into MDF board (could drill holes and use nuts and bolts but supergluing is fine for a prototype)
  • Adjusted and reprinted all couplers to better fit 4mm shafts
  • Iterated through a few small 4-to-5 mm adaptors to fit 5mm bearings and 5mm wheel core holes
  • In hindsight it would have been better to press fit through the bearings just because now the gears for the pulleys are a little too big and don't sit symmetrically but invention studio wasn't keen on doing that IMG_3245

10/22/25 - Team Meeting

  • Updated team on progress with assembly
  • Helped troubleshoot a few issues with the Docker container on Gwen's laptop
  • Walked through fault injection to detection flow with Esha to help her better understand how to parse Safiy's code and merge with mine within the simple_gridlabd_example

10/23/25 - Class Meeting

  • Continued troubleshooting Esha's issues with running the example integrated simulation
  • Chatted with Shrayes about best way to set up network/attack flow for future networking I need between robot/raspberry pi, etc.

Week 11

10/27/25 - Individual

  • Need to print one more TPU wheel -> asked a friend at the Hive

10/29/25 - Team Meeting

  • No new updates as I was traveling for interview in Boston this week

10/30/25 - Class Meeting

  • No new updates as I was traveling for interview in Boston this week

Week 12

11/3/25 - Individual

  • Finished supergluing all mounts to MDF board IMG_3273
  • Some of the belts aren't quite tensioned enough so I'll need to design and 3D print a few belt tensioners -> asked Elliot to prototype
  • Grabbed a bunch of hex nuts from the invention studio because GTRI doesn't have 3x0.5mm
  • Located a few boxes of flat screws of various sizes that will be handy for assembling belt tensioners
  • Made a list of all the electrical components I need with Will
  • Need 2 level shifters, one for 5v to 3.3 v from encoders to STM32 and one for 3.3v to 5v for STM32 to motor drivers
  • Need terminal blocks for 5v power because motor drivers, stm32, etc. are all 5v powered
  • Need fuse blocks between batteries and motor mounts to make sure nothing blows up

11/5/25 - Team Meeting & Individual

  • Nguyen is making progress on NAV2 side with of things with the waypointing setting via code so he's now exploring serial communication between raspberry pi and ros
  • Updated team with my assembly progress
  • Gwen still hasn't been able to run the Docker container due to architecture issues, which is odd because Docker containers should be architecture agnostic but Joseph and I have apple silicon macs and I'm sure there are some nuances with then running containers on certain windows laptops, though Rose and Galadriel and Esha were able to set things up on the first try
  • If I have time, I'll try installing Docker on my parallels setup and see if I can pull down the container that way
  • Printed belt tensioners
  • Realized I need more bearings because had to reprint one of my bearing mounts because I couldn't get the 5mm shaft out to replace with a 4mm shaft, so I ordered more of those IMG_3277

11/6/25 - Individual & Class Meeting

  • Everything except fuse blocks arrived, which is fine because I'll be testing off the benchtop power supply for a while anyways
  • Started planning and making custom cables for motor drivers to stm32, encoders to stm32
  • Used stm32 nucleo board datasheet to start planning which pins on the stm32 I want to use for all the timers (need 4 with 2 channels for each) IMG_3278

11/7/25 - Individual

  • Spent the entire day making the custom cables
  • Tested the motors with the benchtop power supply
  • Tested encoders by rotating them and seeing the quadrature signal on the oscilloscope
  • Tested motor drivers by sending a PWM pulse via function generator and using a multimeter to check the conversion from PWM to voltage that will go to the motor drivers
  • The first motor driver I tested ended up being broken despite initially working without a resistive load -> only figured this out after a few hours of testing the other motor drivers and checking the resistive values on the motor driver pinout, so it ended up being that out of the 4 motor drivers that we ordered, 3 of them worked properly
  • Was able to then test motor drivers with motors by generating PWM pulse with function generator, wiring that through motor driver, and then see the motor turn both forwards and backwards (+/- PWM) IMG_3281 IMG_3282

Week 12

11/10/25 - Individual

  • Finished wiring up STM32 to encoders and motor drivers and used oscilloscope to make sure I was seeing the quadrature signal from the encoder through the level shifter to the STM32 IMG_3290
  • Began looking at rust crates on Crates.io I need to build out my firmware/pid controller for robot
  • My code on Github repo: https://github.com/fizzyforever101/robot_pid_controller (I did all of this locally on my GTRI laptop so I don't have screenshots of specific errors I encountered, I know I should commit more than once a week, I will do better next semester)
  • I first tried to implement a polling type QEI struct because I wanted to keep things simple and do everything in the main executor instead of having separate tasks for each PID loop (right and left sets of wheels) and using interrupts, though that would probably be faster and more accurate so maybe next semester I'll consider switching over to that when I have more time
  • Based on the blog post I found earlier (https://leshow.github.io/post/rotary_encoder_hal/), my understanding is that you can derive direction from the QEI by recording current and previous state of the A and B signals
Screenshot 2025-12-01 at 12 39 15 PM

11/12/25 - Team Meeting & Individual

  • Updated team on progress with robot assembly (completed)
  • Helped Esha troubleshoot the simple_gridlabd_example code by brainstorming a few likely causes for the graph not showing up, namely that updates to gridlabd, pypower, etc. where several functions were deprecated or otherwise implemented differently now is causing errors but they aren't showing up due to the way HELICS pipes stderr from co-simulations (specific errors not showing up in HELICS generated logs)
  • Continued troubleshooting my robot firmware
  • For starters I'll just have a simple state machine for robot motion where it's going to go forward for a few seconds, stop for a few seconds, go backward for a few seconds, stop for a few seconds, and repeat

11/13/25 - Class Meeting

  • No new updates from anyone, lots of exams and also had a ballroom expo earlier today

Week 13

11/17/25 - Individual

  • Still not really sure what's going on with my encoders so I decided to rewire my rats nest and use a label maker to label all of my wires
  • I realized I fried a logic level shifter because A must always be lower than B voltage and I didn't realize it shifts both ways for I need 3.3v on A for both level shifters and 5v on B for both level shifters IMG_3328
  • One milestone at least is that I can now drive the robot via hardware!

11/20/25 - Class Meeting

  • Did final presentation with videos of my robot driving via hardware and pictures of my build process
  • Talked to Will about encoders and realized I need to just use the QEI embassy library instead of the simple sampling of edges from the blog post I found because I'm not sampling fast enough and am missing edges and also quadrature signals are not always perfect so I'd need to implement a filter of some sort to get rid of noisy spikes, etc.

11/21/25 - Individual

  • Spent most of this week and all day today debugging and the encoders aren't giving great values, meaning that I am getting readings of 0 to 4000 counts in encoder after 1 tick, which is 10 ms which should not happen and then even after handling overflow I'm still getting weird jumps from 6000 to 30000 counts after 1 tick
  • Also encoders are too sensitive to direction changes so for now I've hardcoded that it's always going forward so I need to take the absolute value of new count value to add to the difference/delta to keep track of position
  • I will be out all of next week for thanksgiving break and the senior design expo is the monday after break, so I will just call it here and using videos and pictures I have of the build process because the encoders still aren't giving good enough values for the pid loop to work, but the code is all there

Spring-2026

👑📜 Official Proclamation of Academic Sovereignty 📜👑

By the powers vested in me by absolutely no formal authority whatsoever — yet tremendous confidence —

I hereby pronounce Elliot Kantor to be my loyal steward, trusted intern, and occasional bringer-of-coffee for this glorious semester of the VIP.

May he debug with courage, document with diligence, and respond to Discord messages with reasonable haste.

Let it be known that his duties shall include (but not be limited to):

  • Nobly wrangling rogue commits and mismanaged software packages
  • Translating cryptic error messages from ancient machine dialects
  • Asking “have you tried turning it off and on again?” at least once per week
  • And standing bravely on the front lines of version control conflicts

In return, he shall receive:

  • Occasional wisdom
  • Sporadic praise
  • And the eternal honor of surviving this VIP semester

May his pull requests be approved, May his tests always pass, And may his bugs be few and easily reproducible.

So declared. So documented. So committed.


Spring 2026 Semester Summary: Robot Development & Mission Control

A comprehensive overview of work completed by Sabina and Elliot on the VIP robotics team, including hardware design, embedded firmware development, and fault-injection simulation infrastructure.


Timeline of Work

January 30, 2026 - ROS Subteam Meeting 1

Attendance: Sabina, Esha, Calvin, Elliot

Esha's Work

  • Encountered issues with gridlabd example not working
  • Debugging with Will and Sam: identifying dependencies and version conflicts
  • Key Issue: New version of HELICS has breaking changes requiring version downgrade
  • Action Item: [ ] On Tuesday, provide detailed report of what's not working and what was tried

Calvin's Work

  • Moving nix configuration to Docker (responding to Sabina's comments)
  • Action Items:
    • Try a baseline of nix inside of Docker and get that working
    • Start moving dependencies outside of nix and into pure Docker environment

Elliot's Tasks

  • Come up with components for Sabina to include in the PCB
  • Gain access to the lab and redesign the drive system
    • Moved to direct drive with caster wheels
  • Purchase larger, real wheels
  • Printed one TPU tire (needs iteration to be more compliant)
  • Getting schematics and firmware from Will's GitHub
  • Action Items:
    • Redesign TPU tire that wraps onto old cores (thinner, more compliant)
    • Copy and paste schematic pieces from Will's PCB and add sensors (IMU, headers, motor drivers) to schematic
    • Stretch: Create separate power delivery board with fuses and power buses for logic and battery management/safety

Sabina's Assignment

  • Get quadrature encoders working and reading values to the microcontroller
  • Print new embedded bearing mounts for updated robot CAD

February 20, 2026 - ROS Subteam Meeting 2

Attendance: Sabina, Elliot

Key Agenda Items:

  • Team standup on progress
  • Dockerfile updates discussion
  • Mission 1 overview
  • Getting Rick's example code to run with visuals
  • Updating example to subscribe to control_center (not direct relay)

Action Items for Team

  • Finish PCB design completely by presentation

Next Steps (Updated 2-17-26)

  • Relay detection: relay tripped when fault detected
  • Control center detects tripped relay and sends dummy coordinate to ROS2 federate to direct robot to location on fault

Steps for Gazebo Integration (2-20-26)

sudo apt install ros-jazzy-twist-mux
# clone NAV2 from Nguyen
# cd into it
colcon build
ros2 launch vipnav launch_sim.launch.py  # uses twist

April 3, 2026 - ROS Subteam Meeting 3

Attendance: Sabina, Elliot, Esha

Esha's Tasks

  • Expressed preference for CS concepts but not embedded firmware
  • Interested in how robots perceive the world (LIDAR, SLAM, NAV2)

Action Items for Esha:

  • Reach out to Calvin and Nguyen regarding work she can help on
  • Read notebooks of Calvin and Nguyen to catch up
  • Create PR into NAV2 repo with markdown documentation in the readme

Discord Summary - Distributed Action Items

For Esha:

  • Finished documentation and verified by starting from clean image to working mission 1
  • Merge documentation as markdown into the readme on the NAV2 repo
  • Read Calvin and Nguyen's recent notebook entries to get up to speed
  • Reach out to Calvin and Nguyen to offer help either documenting background on SLAM/Kalman filtering or help set up the actual parameters for SLAM with Calvin

For Calvin:

  • Make a checklist of what's needed to get nav2 and slam working on an actual robot
  • Explain how we should go about receiving cleaned velocity measurements from encoders
  • What other parameters need to change? (measurement covariances, process noise estimates?)
  • Find or sketch out how to convert a stream of data into a nice ROS topic for nav2 to use
  • Remember: we will be reading IMU/encoder data from the microcontroller with a ROS node

For Elliot:

  • Almost done with PCB schematic (just need to add DCDC converters from TI's power designer)
  • With new 3D prints, tear apart old robot, add caster wheels, glue/screw everything down
  • Add battery circuit and check that Pi and microcontroller get 5V

For Sabina:

  • Get quadrature encoders working and reading values to the microcontroller
  • Print new embedded bearing prints for updated robot CAD

For Nguyen:

  • Keep team updated as you debug the Pi issues
  • Try second Pi with same SD card to see if hardware is the problem
  • Verify serial is enabled in raspiconfig
  • Definitely use the official power supply instead of other USB charger
  • Test serial code with stm32

April 10, 2026 - ROS Subteam Meeting 4

Attendance: Esha, Calvin

Status was brief - Esha and Calvin attended without Elliot/Sabina present.


Goals for Semester

High Level Objectives

  • Working robust robot with lidar mounted on top
  • Lidar connected to computer/Pi and running Nav2 on ROS2
  • Get rotary encoder drivers made, contribute to Embassy

Hardware Updates (HBOM)

Prints Completed

  • 2 motor mounts (shorter)
  • 2 motor bearing mounts

Fabrication Needed

  • Shorten 6 mm shafts (miter saw)
  • Hole in robot base (water jet or jig saw)

Purchased

Verified Components

  • 1x XT60 female-to-pigtails
  • 1x XT60 female-to-double-pigtails

Robot Hardware & PCB Design

Overview

The team is designing a custom PCB for a differential-drive mobile robot with encoder feedback, motor control, and sensor integration.

Motor Drive PCB Layout

image image

Power Management

5V Buck Converter

5V Power Supply Rail Design

image image image

3.3V Buck Converter

3.3V Power Supply Rail Design

image image image

Motor & Control Components

Motor Drivers

Battery Management

DIY LiPo Charging/Balancing on PCB

COTS (Commercial Off-The-Shelf) Solution

Sensor Integration

Encoders

Rotary quadrature encoders for precise odometry feedback. Implementation details in embedded firmware section.

IMU (Inertial Measurement Unit)

Option 1: Adafruit 9DOF IMU (Recommended)

  • Specs: 9-degree-of-freedom motion sensor
  • Interface: Qwiic connector for easy integration, I2C protocol
  • Mounting: Can be screwed down and has solderable pins for permanent integration
  • Cost: $30
  • Link: https://www.adafruit.com/product/4646
  • Advantages: Pre-assembled, Qwiic-compatible, readily available libraries

Option 2: BNO055 Chip (Budget Option)

Microcontroller Selection

Family Embassy Compatibility Notes
NRF Excellent Preferred for Rust/Embassy
STM32 Good, tedious More setup required
Pico Good RP2040 support improving
Teensy Okay, needs community Community support variable

Connector Type: Components are soldered directly to board (no connectors for microcontroller pins)

Design References

Reference Motor Control Implementation (SSL-A-Team)

Will's reference robot controller implementation provides excellent context for our firmware architecture:

image

Embedded Firmware: PID Controller & Serial Interface

Repository: https://github.com/fizzyforever101/robot_pid_controller

Project Overview

Embassy-based STM32 motor speed controller featuring:

  • Quadrature encoders (timer QEI)
  • H-bridge PWM (two PWM channels per motor: forward/reverse)
  • PID speed loop (counts-per-second setpoint)
  • UART telemetry + simple command interface (newline-terminated ASCII)

Hardware Assumptions (Current Pin Map)

Encoders (QEI)

  • Left encoder: TIM3 with PA6 (CH1) and PC7 (CH2)
  • Right encoder: TIM1 with PE9 (CH1) and PE11 (CH2)

Motors (PWM H-bridge)

Each motor uses 2 PWM channels:

  • CH1 = forward, CH2 = reverse

Configuration:

  • Left motor: TIM4 with PD12 (CH1 forward) and PD13 (CH2 reverse)
  • Right motor: TIM23 with PF0 (CH1 forward) and PF1 (CH2 reverse)

Serial (UART)

  • USART1: PB7 = RX, PB6 = TX, 115200 baud

Code Structure

  • src/main.rs: Hardware init + control loop + UART command parsing + telemetry formatting
  • src/modules/encoder.rs: EncoderQei wrapper around Embassy Qei, plus delta_counts() sampling
  • src/modules/motor_control.rs:
    • HBridgePwm: applies MotorCommand to SimplePwm CH1/CH2 (forward/reverse)
    • MotorPid: PID speed controller that outputs MotorCommand from measured counts/s
  • src/modules/serial.rs: SerialInterface using blocking UART writes + nonblocking byte reads

How It Works (Control Loop)

The main loop runs at a fixed period (CONTROL_PERIOD_MS, currently 10ms).

Per tick:

  1. Read any available UART bytes and parse newline-terminated commands
  2. Sample encoder deltas via EncoderQei::delta_counts() and convert to counts per second
  3. Run PID for each motor to generate a signed output in [-1, 1]
  4. Map the PID output to:
    • drive direction (Forward/Reverse/Coast)
    • duty cycle between MIN_DUTY and the timer's max_duty
  5. Apply PWM to each H-bridge

Telemetry is emitted every TELEMETRY_PERIOD_MS (currently 100ms) over:

  • defmt logging (RTT)
  • UART as an ASCII line: L:<left_cps> R:<right_cps>\r\n

UART Command Interface

Commands are ASCII, newline-terminated (\n). \r is ignored.

Available Commands:

  • T <int>: set target CPS for both motors
  • TL <int>: set target CPS for left motor
  • TR <int>: set target CPS for right motor

Examples:

T 4000
TL 2500
TR -3000

Values are interpreted as counts-per-second setpoints. Negative values command reverse.

Building and Flashing

This project targets thumbv7em-none-eabihf and uses a runner from .cargo/config.toml:

[target.thumbv7em-none-eabihf]
runner = 'probe-rs run --chip STM32H723ZGTx'

Common commands:

cargo build
cargo run

DEFMT_LOG is set in .cargo/config.toml (currently trace).

Testing Components (On Hardware)

1) Serial TX/RX

Goal: confirm UART wiring, baud, and command parsing.

  1. Connect a USB-UART adapter to USART1:
    • Adapter TX → PB7 (MCU RX)
    • Adapter RX → PB6 (MCU TX)
    • Common GND
  2. Open a serial terminal at 115200 8N1
  3. Reset the board and observe periodic telemetry lines: L:<...> R:<...>
  4. Send a command, e.g.:
    • T 0\n to coast both motors
    • T 2000\n to command forward

Troubleshooting: If telemetry prints but commands do nothing:

  • Verify you are sending a newline (\n)
  • Verify RX/TX are not swapped

2) Encoders (QEI)

Goal: confirm encoder counts move and direction is correct.

  1. Run firmware with motors disabled or setpoint 0 (T 0\n)
  2. Spin the left wheel/encoder by hand
  3. Observe L: change; repeat for the right wheel/encoder and R:

Expected scaling (Taiss 600 P/R encoder):

  • With x4 quadrature decoding, counts/rev = 600 * 4 = 2400
  • Telemetry reports counts/s (CPS)
  • With 2400 counts/rev: RPM = CPS / 40

Notes:

  • EncoderQei::delta_counts() uses wrapping subtraction and assumes you do not exceed ~32k counts per sample
  • If you see wildly incorrect readings, reduce speed or reduce CONTROL_PERIOD_MS
  • If your encoder outputs are open-collector (common on NPN optical encoders), A/B require pull-ups. This firmware enables pull-ups on the QEI pins via a local patch to embassy-stm32 and uses Pull::Up when configuring QEI pins

3) PWM Outputs

Goal: confirm the MCU is generating PWM on the expected pins.

  1. With the motor driver enabled but wheels off the ground, send:
    • TL 1000\n and TR 1000\n
  2. Use a scope/logic analyzer on:
    • Left: PD12/PD13
    • Right: PF0/PF1
  3. Expect:
    • Forward: CH1 toggling with duty, CH2 low (0% duty)
    • Reverse: CH2 toggling with duty, CH1 low

4) PID Speed Loop

Goal: confirm closed-loop behavior and basic stability.

  1. Start with a small setpoint: T 500\n
  2. Increase gradually: T 1000\n, T 2000\n, ...
  3. Watch telemetry counts/s and check it tracks the setpoint

If the loop oscillates or saturates:

  • Tune PID gains in src/modules/motor_control.rs (MotorPid::new)
  • Adjust MIN_DUTY (static friction compensation) in src/main.rs
  • Consider increasing PWM frequency if your motor driver prefers it (currently khz(1))

Safety Notes

  • Test with wheels off the ground first
  • Be ready to stop the motors quickly (T 0\n)
  • If direction is inverted, swap encoder channels or swap the motor outputs (or invert the sign of the setpoint)

Mission 1: Fault Injection Simulation

PR: https://github.com/cps-vip/cosim-fault-injection/pull/1

Title: Rewrite environment and setup script, add docs, fix federate naming to complete mission 1

Participants: Elliot Kantor & Sabina Sokol

Overview

Mission 1 focuses on co-simulating a power distribution system with fault injection and autonomous robot response. The system uses HELICS to couple multiple federates (GridLAB-D, ROS 2, Python control logic) and validates that when a fault occurs (open-line conductor), the relay trips and the robot automatically navigates to a specified location.

Major Accomplishments

Environment Overhaul

  • Ditched nix environment in favor of new lightweight Docker image with only build dependencies
  • Created an install script to install larger dependencies without bloating the image
  • Used uv as Python package manager (for non-ROS Python) to fix numpy versioning errors
  • Fixed C++ dependency issues
  • Added comprehensive documentation for environment setup
  • Full mission 1 documentation added to the NAV2 repo

Federate Architecture Updates

  • Fixed federate publisher/subscriber nodes naming consistency
  • Added control center federate for relay detection and robot navigation
  • Added ROS2 publisher with HELICS integration
  • Merged NAV2 from previous work with example code
  • Brought up Nav2 action server in control center run example script

Environment & Infrastructure (w/ Elliot)

Affirmation of Sabina's Previous Integration Work image

Simulation Architecture

  • Relay Federate: Monitors current values from Distribution federate
    • Trips relay when sensing a current drop (indicating open-line fault)
  • Distribution Federate: Generates fault via Reliability module (open conductor)
  • Control Center Federate: Detects relay trip from Relay federate
    • Generates dummy waypoint coordinates
    • Sends to ROS2 federate for robot navigation
  • ROS2 + NAV2 + Gazebo: Robot autonomously navigates to waypoints using Nav2 navigation stack in simulated environment

Current Status & Troubleshooting

  • Waypoint setting via ROS2 topic (in progress - final piece)
  • Resolved Issues:
    • Stale ROS2 files/nodes from improper shutdown during testing
    • Debugging URDF file origin coordinates
    • Odometry frame alignment
  • Current Work: Modifying URDF file to have correct origin coordinates and proper odometry setup

Key Commits

  1. Add control center federate
  2. Add ros2 publisher with helics integration
  3. Switch poetry to uv (Python package management)
  4. Add updated Dockerfile and install script
  5. Remove nix files
  6. Use ~/software for all github and move files to patch ros on install
  7. Use uv in run scripts and add control center run script
  8. Update readme to reflect docker environment
  9. Update federates and ros example for fault injection
  10. Inject fault into distribution federate with reliability module
  11. Update ros2 config (copied from ros2_ws)
  12. Update gitignore, absolute ros path
  13. Merge Nguyen's waypoint publisher work with existing simple gld example
  14. Move gazebo launch into launch_sim

Technology Stack

  • Containerization: Docker (lightweight, dependency-focused)
  • Python Management: uv (faster, cleaner than poetry)
  • Simulation: HELICS (co-simulation framework)
  • Middleware: ROS 2 Jazzy
  • Navigation: Nav2 (with custom parameters)
  • Visualization: Gazebo

Testing & Validation

  • Starting from a clean Docker image → working mission 1 verified
  • Environment setup fully documented and reproducible
  • Federate communication verified end-to-end

Documentation

Full setup and execution documentation added to NAV2 repo as markdown in the readme, enabling quick onboarding for future team members.


Additional Resources & References

Robot Design & Previous Work

Component Datasheets & References

Key Repositories


Next Steps & Future Work

Immediate Priorities

  1. Sabina: Complete rotary encoder integration and testing with the STM32
  2. Elliot: Finish PCB schematic with DCDC converters (from TI power designer)
  3. Both: Assemble updated robot with caster wheels, test power delivery
  4. Esha: Merge documentation into NAV2 readme
  5. Calvin: Complete Nav2 & SLAM parameter checklist and sensor integration plan

Medium-term Goals

  • Get lidar mounted and integrated with Nav2
  • Achieve full autonomous navigation in simulation and on hardware
  • Debug and stabilize odometry using encoder feedback + IMU
  • Contribute quadrature encoder drivers upstream to Embassy

Hardware Fabrication Checklist

  • Shorten 6 mm shafts
  • Cut hole in robot base
  • Print motor bearing mounts
  • Assemble and test updated drive train
  • Validate power distribution to Pi and microcontroller

Back to Top

⚠️ **GitHub.com Fallback** ⚠️