Skip to content

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 --version should 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

  1. Create a new file, for example:

    echo "Hello from Student A" > hello.txt
    
  2. Check what’s new:

    git status
    
  3. Stage and commit the file:

    git add hello.txt
    git commit -m "Add hello.txt from Student A"
    
  4. Push to GitHub:

    git push
    

    Now, ensure the file is visible on the GitHub website: https://github.com//git-practice

4. Student B joins the project

  1. Student A should go to the repo on GitHub, open: Settings, Collaborators, Add collaborator, enter Student B’s GitHub username and invite them.

  2. 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

  1. Add another file:

    echo "Hello from Student B" > hello_b.txt
    
  2. Stage and commit:

    git add hello_b.txt
    git commit -m "Add hello_b.txt from Student B"
    
  3. 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.

  1. Navigate to your local repository:
cd ~/roboracer_ws/
  1. Fetch the latest changes from the remote repository:
git pull
  1. 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

  1. Make the Python files executable:
chmod +x node_a.py node_b.py
  1. Open 2 shell windows by using tmux panes on your car.

    In the first pane, run Node A:

    ros2 run team_tutorial node_a.py
    

    In the second pane, run Node B:

    ros2 run team_tutorial node_b.py
    

    You 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