Building Robots in Teams
In this tutorial you will work with your team to learn the basics of ROS2 and create a shared GitHub project. You'll make your first commits allowing you to share code via git. You will set up your editor, learn to use AI Coding tools responsibly, as well as best practices effective collaboration. With the ability to edit and share code, your team will implement several ROS2 nodes to solidify the core concepts of the Robot Operating System.
Learning Objectives
- Understand the basics of ROS2 architecture
- Understand basic Git commands and workflows
- Collaborate effectively using GitHub repositories
- Practice making commits, pushing, and pulling changes
- Set up your coding environment with your teammate
- Use an AI coding agent to assist with coding tasks
- Implement simple ROS2 nodes collaboratively
Deliverables
- A shared GitHub repository with contributions from both students
- Several simple ROS2 nodes implemented collaboratively
Prerequisites
- Have Git installed (
git --versionshould work in the terminal). - Both have GitHub accounts and are logged in.
- Have the VSCode editor installed.
git
git is a command-line tool for version control that allows multiple people to work on the same codebase simultaneously. It is closely related to github.com, which is one of the most popular platforms for hosting Git repositories. While git can be self-hosted or hosted on other platforms, such as gitlab.com, we will use github.com in this tutorial and for the class. In this portion of the tutorial, you will create a shared repository on GitHub and practice basic git commands such as clone, add, commit, push, and pull.
1. Student A creates the repository
- Go to https://github.com and click New repository.
- Check Add a README file.
- Click Create repository.
Now Student A has a GitHub repo!
2. Student A clones the repo to their computer
In a terminal:
git clone https://github.com/<studentA-username>/git-practice.git
cd git-practice
3. Student A makes their first change and pushes it
-
Create a new file, for example:
echo "Hello from Student A" > hello.txt -
Check what’s new:
git status -
Stage and commit the file:
git add hello.txt git commit -m "Add hello.txt from Student A" -
Push to GitHub:
git pushNow, ensure the file is visible on the GitHub website: https://github.com/
/git-practice
4. Student B joins the project
-
Student A should go to the repo on GitHub, open: Settings, Collaborators, Add collaborator, enter Student B’s GitHub username and invite them.
-
Student B accepts the invitation (check email or notifications).
5. Student B clones the repo and pulls the latest changes
git clone https://github.com/<studentA-username>/git-practice.git
cd git-practice
Now Student B has the same files locally.
6. Student B makes a new change and pushes it
-
Add another file:
echo "Hello from Student B" > hello_b.txt -
Stage and commit:
git add hello_b.txt git commit -m "Add hello_b.txt from Student B" -
Push the change:
git push
7. Student A pulls the new changes
Back on Student A’s computer:
git pull
Student A will now see both hello.txt and hello_b.txt locally.
Lab Notebook
Include two screenshots of your terminal. One screenshot should show the contents of the project (run the ls command). One screenshot should show the output of the git log command displaying the commit history with both students' commits.
git Summary
You just:
- Created a GitHub repo
- Made commits
- Pushed and pulled between collaborators
This is the foundation of real-world teamwork in software development.
Updating the Code in the Course Repositories
It's good practice to keep your local codebase up to date with the latest changes from the course repositories. This ensures you have access to the most recent tutorials, bug fixes, and features. Follow these steps regularly to sync your local repository with the remote course repository.
- Navigate to your local repository:
cd ~/roboracer_ws/
- Fetch the latest changes from the remote repository:
git pull
- Update the repositories in the workspace:
./scripts/checkout.sh
The Robot Operating System (ROS) 2
The robot operating system (ROS) is a flexible framework for writing robot software. It is a collection of tools, libraries, and conventions that aim to simplify the task of creating complex and robust robot behavior across a wide variety of robotic platforms. ROS2 is the second generation of ROS, which includes improvements in performance, security, and real-time capabilities.
ROS2
If you're not familiar with ROS2, read the ROS2 overview and optionally complete the ROS2 tutorials before starting this tutorial.
Creating A New ROS 2 Package
Building systems in teams is a critical skill for robotics researchers. A key challenge in this process is organizing code so that multiple people can work on different parts of the system without conflicts. ROS 2 packages provide a modular way to encapsulate functionality, making it easier to manage and share code among team members.
In this section, you will work in a team to create a new ROS2 package (or two, your choice) in your shared repository. Your implementation should contain two nodes: node A and node B. Node A will publish a simple message, and Node B will subscribe to that message and print it to the console.
Read through the instructions and then decide with your teammate how the work will be divided.
Lab Notebook
Note how you plan to divide the work between team members.
1. ssh into your car ssh orin07
2. Navigate to your workspace src directory
cd ~/roboracer_ws/src
3. Create a new ROS2 package named team_tutorial with dependencies on rclpy and std_msgs using the ros2 pkg create command
ros2 pkg create --build-type ament_python --dependencies rclpy std_msgs team_tutorial
4. Implement the two nodes in separate Python files within the team_tutorial package
cd team_tutorial/team_tutorial
touch node_a.py node_b.py
5. Edit node_a.py to publish a simple message
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class NodeA(Node):
def __init__(self):
super().__init__('node_a')
self.publisher_ = self.create_publisher(String, 'hello', 10)
self.timer = self.create_timer(1.0, self.timer_callback)
def timer_callback(self):
msg = String()
msg.data = 'Hello from Node A'
self.publisher_.publish(msg)
self.get_logger().info(f'Publishing: {msg.data}')
def main(args=None):
rclpy.init(args=args)
node_a = NodeA()
rclpy.spin(node_a)
rclpy.shutdown()
if __name__ == '__main__':
main()
6. Register the node in setup.py
To run the node using ros2 run, you need to register the entry point in setup.py. Open setup.py and add the following line to the entry_points console_scripts list:
entry_points={
'console_scripts': [
'node_a = team_tutorial.node_a:main',
],
},
7. Build the workspace to install the new node
cd ~/roboracer_ws
colcon build --packages-select team_tutorial
source install/setup.bash
8. Edit node_b.py to subscribe to the message and print it
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class NodeB(Node):
def __init__(self):
super().__init__('node_b')
self.subscription = self.create_subscription(
String,
'hello',
self.listener_callback,
10)
self.subscription # prevent unused variable warning
def listener_callback(self, msg):
self.get_logger().info(f'Received: {msg.data}')
def main(args=None):
rclpy.init(args=args)
node_b = NodeB()
rclpy.spin(node_b)
rclpy.shutdown()
if __name__ == '__main__':
main()
9. Register the node in setup.py
Add the entry point for node_b to setup.py:
entry_points={
'console_scripts': [
'node_a = team_tutorial.node_a:main',
'node_b = team_tutorial.node_b:main',
],
},
10. Rebuild the workspace
cd ~/roboracer_ws
colcon build --packages-select team_tutorial
source install/setup.bash
Running the Nodes
- Make the Python files executable:
chmod +x node_a.py node_b.py
-
Open 2 shell windows by using tmux panes on your car.
In the first pane, run Node A:
ros2 run team_tutorial node_a.pyIn the second pane, run Node B:
ros2 run team_tutorial node_b.pyYou should see Node A publishing messages and Node B receiving and printing them.
Lab Notebook
Include screenshots of both terminal panes showing Node A publishing messages and Node B receiving them.
Adding ROS2 Dependencies to the Docker container
If you're working on a new package or building a new package from source that requires other packages, they should be added to the scripts/ros2_deps.sh script.
Once you update the script, run the following command to rebuild the Docker container with the new dependencies:
./container build
Once it builds, you can start a new container shell with:
./container shell