Skip to content

intermediate tutorial

David Moli edited this page Jan 30, 2026 · 3 revisions

🧒 I have some basic knowledge

Welcome to the Intermediate tutorial! 🎓

If you are here, you likely have your Raspberry Pi set up with Ubuntu and Pixi, and you are ready to understand how RustyRover is actually put together. You aren't just flashing SD cards anymore—you are ready to look under the hood. 🔧


🏗️ Project Architecture

Unlike a standard ROS 2 project where everything might live in one folder, RustyRover is split into three specific workspaces to handle the Rust dependencies and the remote control cleanly.

Here is the high-level map of the repository:

1. rclrs_install_ws 🦀 (The Foundation)

"The Client Library Workspace"

  • Purpose: Since rclrs (the Rust client for ROS 2) is not yet included in standard ROS 2 distributions (like Humble or Jazzy) via apt install, we must build it from source.
  • What's inside: The source code for the rclrs library itself.
  • Why it matters: This workspace provides the core Rust libraries that the robot code needs. You typically build this once and then source it so other workspaces can find rclrs.

2. rusty_rover_ws 🤖 (The Robot Brain)

"The Main Robot Workspace"

  • Purpose: This is where the actual code for the RustyRover lives.
  • Location: Runs on the Raspberry Pi.
  • What's inside:
    • Drivers for the motors.
    • The spinner action server.
    • Camera service nodes.
    • Launch files.
  • Dependency: This workspace depends onrclrs_install_ws. You cannot build this if the foundation isn't sourced!

3. ratatui_teleoperator 🐀 (The Remote)

"The Control Center"

  • Purpose: A standalone Rust application that runs on your Laptop, not the robot.
  • Technology: Uses Ratatui for the TUI (Terminal User Interface) and BlueR for Bluetooth communication.
  • Dependency: This is largely independent of ROS 2, as it communicates via Bluetooth to the Pi (which then translates commands to ROS 2).

🧚 Understanding Pixi

You might have noticed the pixi.toml files. We use Pixi to manage our development environment.

In a traditional ROS setup, you rely on global installations (/opt/ros/...). In RustyRover, Pixi creates a contained environment with all the necessary dependencies (compilers, tools, libraries) installed locally.

The Workflow: Whenever you work on this project, you must ensure you are inside the Pixi environment:

cd RustyRover
pixi shell

This ensures that cargo, colcon, and ros2 commands are available and are the correct versions.


🚀 How to Extend the Project

So, you want to add a new feature? Maybe a LIDAR node or a new sensor driver? Here is how to add a new package to the RustyRover ecosystem.

Step 1: Enter the Main Workspace

Move to the source folder of the robot's workspace:

cd rusty_rover_ws/src

Step 2: Create a New Package

Since we are doing Rust, we use cargo to initialize the package, but we structure it so colcon can find it.

# Replace 'my_new_feature' with your package name
cargo new my_new_feature

Step 3: Configure Dependencies

This is the tricky part! To make your new Rust crate a "ROS 2 Node," you need to tell it where to find rclrs.

Open rusty_rover_ws/src/my_new_feature/Cargo.toml and add:

[dependencies]
rclrs = "*"serde = { version = "1.0", features = ["derive"] } # Often needed for messages

Note

We use rclrs = "*" because we rely on the rclrs_install_ws being sourced in the background. The build system will find the library in the underlay workspace.

Step 4: The Build Cycle

To test your new package, you need to go back to the workspace root and build using colcon.

⚠️ Crucial Sourcing Order:

  1. Source the Foundation: You must source the rclrs setup file first.
  2. Build your Workspace:
# Inside rusty_rover_ws/
colcon build --packages-select my_new_feature
  1. Source your Workspace:
source install/setup.bash

🔄 The Development Lifecycle

When extending RustyRover, your loop will look like this:

  1. Code inside rusty_rover_ws/src/my_node.
  2. Build using colcon build in the rusty_rover_ws root.
  3. Source the install/setup.bash.
  4. Run using ros2 run my_new_feature my_executable.

⏭️ Next Steps

Now that you understand where the folders are and how to add a new package, you probably want to know what code to actually write inside that main.rs file.

👉 Ready to write code? Go to the Pro Tutorial 👑 to learn how to write Publishers, Subscribers, and Services in Rust!