Docs menu
Docs
How the Racerbot cars' ROS 2 workspace is organized, how to run each driving algorithm, the mathematics each algorithm is built on, and beginner guides for new members.
The two Racerbot cars run one ROS 2 Jazzy workspace, Racerbot-Car-Workspace, on an NVIDIA Jetson Orin Nano Super. Both cars run the same code. Each car’s own hardware values live in its car profile, so a change to the driving code reaches both cars with one commit. These pages document that workspace, from how the nodes connect to the commands for every driving mode and the mathematics behind each algorithm. New members start with Beginners, which covers the terminal, a Docker development environment, ROS 2 and the simulator.
The two cars
Both cars use the same chassis (a Traxxas Ford Fiesta ST Rally VXL), the same Jetson, a Hokuyo LiDAR, a VESC motor controller with a built-in IMU and a BNO085 IMU. They differ in the sensors’ connections and in their calibration. A machine finds its car from its Jetson serial number in machines.yamlGitHub: car 1 is rb1 and car 2 is rb2. On a development computer or in the simulator, RACERBOT_CAR=rb1 or RACERBOT_CAR=rb2 chooses the car. Each car’s values are in its profile, cars/rb1/Car 1 or cars/rb2/Car 2, and The cars explains the profile. Where a page depends on one of these values, it shows a table like this one. The full list of differences, with the file that holds each, is docs/car1-vs-car2.mdGitHub.
| Car 1 | Car 2 | |
|---|---|---|
| LiDAR | Hokuyo UST-30LX over USB, at /dev/sensors/hokuyo | Hokuyo UST-10LX over Ethernet, at 192.168.0.10 |
| Camera | UVC USB webcam at /dev/video0 | Intel RealSense D435i |
| BNO085 IMU | Jetson I2C bus 7, address 0x4A | Jetson I2C bus 7, address 0x4A; mount yaw and position not yet measured |
| Full-stick steering | 0.38 rad | 0.436 rad |
| Autonomy steering limit | 0.33 rad | 0.349 rad |
| Servo map | ||
| Speed to ERPM gain | 3650 | 4614 |
| Dashboard site ID | rb1 | rb2 |
Both cars model the same geometry: a 0.36 m wheelbase, a 0.31 m padded body width, and the LiDAR 0.26 m ahead of the rear axle. These were measured on car 2 on August 24, 2026. Car 1 uses the same values and has not been measured separately.
How the software is organized
Every piece of the stack communicates over ROS 2 topics. A launch is always two layers, each in its own terminal:
- Bringup (
bringup_launch.py) starts the drivers for the gamepad, LiDAR and VESC, andackermann_mux. Bringup never moves the car by itself. - A control layer runs on top. It is
teleop_launch.pyfor manual driving, or one autonomy node such asgap_followorpure_pursuit.
ackermann_mux gives manual commands on /teleop (priority 100) precedence over autonomy commands on /drive (priority 10). Because joy_teleop keeps publishing while LB is released, no autonomy command reaches the motor for as long as teleop_launch.py is running, even though the autonomy node itself runs normally. Stop teleop before starting an autonomy node.
joy_teleop, gap_follow or pure_pursuit runs at a time. ackermann_mux passes the winning command on as /ackermann_cmd.Safety rules
At full stick, manual driving commands 5 m/s, gap_follow is configured for up to 5.0 m/s and pure_pursuit for up to 4.0 m/s. Every mode on these pages follows the same rules.
/joy for 0.5 s, commands zero speed. Autonomy nodes enforce this check themselves, in addition to ackermann_mux. Never set enable_deadman to false on the car.- Run any new or changed driving code with the wheels off the ground first.
- Never run
teleop_launch.pyalongside an autonomy node. - Keep one person beside the battery switch whenever the car drives itself.
- Run
ros2 run racerbot_doctor doctorbefore a session. It checks every device from USB up to the ROS topic and never publishes anything. See the pre-run checklist.
Relation to the course
The workspace implements the methods taught in the club’s RoboRacer course, which is adapted from the F1TENTH course. The labs build each method from scratch in the simulator, and the workspace runs the same methods on the car with what a physical car adds: a body-sized collision model, speed limits from braking distance and grip, and the LB check.
| Course material | Topic | In the workspace |
|---|---|---|
| Lecture 1 (notes), Lab 1 | ROS 2, packages, nodes, launch files | ROS 2 in this workspace |
| Lecture 2 (notes), Lab 2 | Time to collision and automatic emergency braking | The TTC brake in Follow the gap |
| Lecture 3 (notes), Tutorial 3 (notes) | Coordinate frames and TF2 | Coordinate frames |
| Lecture 5 (notes), Lab 4 | Follow the gap, safety bubble, disparity extender | Follow the gap |
| Lecture 6 (notes) | Vehicle states and the kinematic bicycle model | Wheel odometry, Pure pursuit |
| Lecture 7 (notes) | Bayes filters, Kalman filters, particle filters | IMU fusion, SLAM and localization |
| Lecture 8 (notes), Lecture 9 (notes), Tutorial 5 (notes) | SLAM, occupancy grids, pose graphs, slam_toolbox and the particle filter |
SLAM and localization, Map a course and race |
| Lecture 10 (notes) | Pure pursuit | Pure pursuit |
Beginners
- Terminal FoundationsThe concise Racerbot terminal cheat sheet: exactly the shell skills the team's Linux terminal skills assessment tests, plus a short list of external lessons worth your time.
- Dev Environment SetupSet up the Racerbot ROS 2 development environment on macOS, Linux or Windows: Docker Desktop, the racerbot_ws workspace container, verification checkpoints and troubleshooting.
- ROS 2 PrimerA hands-on ROS 2 primer for Racerbot members: your first package, node, topic, launch file and rosbag, each with a working checkpoint, ending where the first autonomous lab begins.
- Sim QuickstartGet a simulated Racerbot race running in under an hour with f1tenth_gym_ros, then step up to AutoDRIVE for higher-fidelity testing.
- Rigid Body TransformsA visual guide to rotation matrices, homogeneous coordinates and changing reference frames — the maths behind how the car's sensors, chassis and map relate in ROS 2.
Get started
- The carsThe hardware on each car, how the two differ, and the measured geometry and calibration every controller relies on.
- Set up the workspaceClone the car workspace onto a Jetson, install its dependencies, build it, and confirm the car and its hardware are found.
- ROS 2 in this workspaceNodes, topics, parameters, launch files and sourcing, as this workspace uses them, with the commands for inspecting a running car.
Safety
- Safety modelHow the LB deadman and ackermann_mux each stop the car, which one protects you in each mode, and the rule every driving node must follow.
- Pre-run checklistThe physical checks and the racerbot_doctor self-check to run before the car moves, and how to read the doctor's report.
Run the car
- QuickstartEvery command for running the car on one page, each with a single line saying what it does.
- Command referenceOne copy-paste block for every mode of the car, with the output that shows it is working.
- Drive manuallyDrive the car with the F710 gamepad or a Wiimote, and confirm the commands reach the motor and servo.
- Map a course and raceThe whole path from a course nobody has mapped to a race on its saved line: the three routes, what each step produces, and the run folder that ties them together.
- Map a courseDrive laps of a new course with gap_follow while SLAM builds the map, then save the map, a racing line and the start pose, automatically with map_course or by hand.
- Race a saved mapLocalize the car on a mapped course from its saved start pose, then race the saved line with pure pursuit or another steering law.
Architecture
- System architectureEvery node in the workspace and how they connect, from the sensors through odometry, IMU fusion, SLAM and the control layer to the motor and servo, with the launch layers, topics and packages.
- Coordinate framesThe map, odom, base_link and laser frames, which node publishes each transform, and which point on the car a pose refers to.
- QoS and timingThe delivery settings each topic is published with, which subscriber settings can receive it, and the rates, timeouts and delays the driving code is built around.
- Drive intentThe /drive_intent topic: what a driving node plans to do and which limit is in charge, published as JSON for the dashboard without risk to the control path.
Autonomy
- Follow the gapReactive driving with no map: gap_follow aims into the best-scoring opening in each LiDAR scan and caps its speed so the car can always stop within the free distance ahead.
- Racing line and speed profileHow the racing line is recorded, how every point gets a target speed from the car's grip and braking limits, and how the line can be reshaped to the least-curved path the track allows.
- Pure pursuitThe default race controller: each tick it picks a point a speed-dependent distance ahead on the racing line and steers along the circle that reaches it.
- StanleySteering from the front axle's errors: turn the wheels parallel to the racing line, then toward it by an angle that grows with the sideways error.
- LQRFeedforward for the bend plus feedback on the sideways and heading errors, with gains computed from a model of the car rather than tuned by hand.
- MPCEvery tick, MPC plans 20 steering moves over the next second within the servo's angle and rate limits, applies the first, and plans again.
- Safety net and overtakingThe independent checks that can stop or steer pure_pursuit, and how it detects another car with the LiDAR, tracks it along the track and passes it.
- Neural racerAn experimental learned racing policy: a small network trained in simulation, run in shadow mode beside gap_follow, inside a deterministic safety wrapper that can only make its commands safer.
State estimation
- Wheel odometryHow vesc_to_odom_node turns the VESC's motor speed and the servo command into speed, yaw rate and a dead-reckoned pose on /odom, and why its heading drifts.
- IMU fusionimu_bridge: calibrated IMU topics in car axes, a health verdict, a Kalman-filtered speed that rejects wheelspin, the measured steering angle, and gyro odometry for SLAM.
- SLAM and localizationHow slam_toolbox builds the map and corrects odometry drift, and how the particle filter localizes the car on a saved map with GPU ray casting.
- Odometry calibrationCalibrate the speed gain, the servo centre, the steering gain and the steering limits with a tape measure and a browser wizard.
Tools
- Web dashboardWatch the car's map, scan, pose, camera and decisions from a browser at dashboard.sfuracerbot.ca, tune the driving nodes live, and open the car in Lichtblick.
- Record and analyze runsCapture everything a run did, then explain every stop and measure how the car responded to its commands.
- SimulatorsTwo simulators built on F1TENTH Gym: one that tests controller mathematics with no ROS, and one that runs the real launch files above a simulated car.
Develop
- Add your own codeDecide whether new code is driving code or support code, where its package goes, and what every package must contain.
- Write a driving nodeThe contract for a node that can move the car: its topics, the LB deadman check copied from gap_follow, the tests it needs, and the order to bring it up.
- TestingWhat kinds of tests the workspaces have, what each package's tests check, how to run them safely and read their output, and the standard every test is held to.
- Git and car profilesWhich packages are submodules and which are vendored, how to update each safely, and where to change a value for one car without touching the other.
Reference
- TroubleshootingProblems seen on the cars, by symptom, with the cause and the fix, and the method that finds most faults quickly.
- Configuration filesEvery YAML file that sets the car's behaviour, which node reads it, and what to change in it.
- GlossaryShort definitions of the terms these pages use, from ROS 2 basics to racing-line vocabulary.
Checked against workspace commit 556284c.