Using Pitwall Telemetry
Use this when you want to watch values inside the code — speed, PID error, and so on — in real time while driving. Normally in ROS, checking such values means creating a new topic (declaring a publisher, picking a message type, writing the publishing code), and internal variables that are not topics are even harder.
With Pitwall telemetry, dropping pitwall.log("name", value) anywhere in the code automatically turns that value into a channel you can watch and record in real time.
Why It Is Nice
- No topic creation — a single
pitwall.log(...)line, no publisher or message-type declarations - Watch internal variables that are not topics — PID errors, intermediate computations, values you normally cannot see
- Faster tuning loops — change gains and watch the values respond immediately on a live graph
In the default Sim, only events (event notifications) show up out of the box. Value logging (log) is switched on per value by adding one line, as in “Logging and Viewing Values” below.
Pitwall Telemetry Basics
| Feature | Description | Mechanism / example |
|---|---|---|
Event notification (event) | Logs one line to the list when a specific event happens | Car hits a wall → ego: WALL collision appears |
Value logging → viewing (log) | Turns an in-code value into a channel with one line | Watch the speed on a live graph |
Caution — Unlike
pitwall.event(...), viewingpitwall.log(...)values as a graph requires rqt (ROS’s GUI tool collection). If you just want the numbers,ros2 topic echo /pitwall/…is enough.
Event Notifications (event)
This feature prints one line to the Pitwall Telemetry box when a specific event happens in the code. In the current stack, a notification fires when the Ego collides with a wall or an opponent, appearing in real time in the Telemetry box of the RViz Pitwall panel.
Visible right away in the Sim.
1
2
3
4
5
6
7
import pitwall # once at the top of the file
pitwall.init(self) # once in the node __init__
# where the collision is detected
pitwall.event('ego: WALL collision')
pitwall.event('ego: OPPONENT collision')
Try It Yourself — Raising an Event on Avoidance
① Open the file where the situation you want to announce is handled. Here we want an event the moment the Ego overtakes an obstacle (OVERTAKE), so open state_machine_node.py.
(Path: /home/hmcl/unicorn_ws/src/unicorn-racing-stack/state_machine/state_machine/state_machine_node.py)
This file does not have pitwall yet, so first add import pitwall at the top, and pitwall.init(self) plus a variable to remember the previous state in the node __init__. (Skip if already present.)
1
import pitwall # top of the file (line 19)
1
2
3
# mind the indentation
pitwall.init(self) # ← add (once), line 348
self._prev_state = None # ← add (remembers the previous state), line 349
Then, where the state is published (line 1408), add code that catches only the moment the state flips to OVERTAKE and raises the event.
1
2
3
4
# ↓ add: only once, at the moment of entering OVERTAKE (line 1408)
if self.cur_state == StateType.OVERTAKE and self._prev_state != StateType.OVERTAKE:
pitwall.event('obstacle avoid')
self._prev_state = self.cur_state
Why compare with
_prev_state: this line runs every loop (tens of Hz), so raising the event unconditionally would spamobstacle avoidfor the entire overtake. Comparing against the previous state raises it exactly once at the moment of entry. To change the message, just edit the string insidepitwall.event('...').
② Save and build.
1
colcon build --packages-select state_machine # build only the modified package
③ Run the Sim.
1
ros2 launch stack_master race.launch.xml sim:=true map:=f
Actual run
Logging and Viewing Values (log)
Use this to watch numeric values inside the code in real time. It looks similar to ros2 topic echo, but the difference is that it can also show internal variables that were never made into topics (e.g. PID error).
Try It Yourself — Watching the Speed on a Graph
① Open the file where the value you want is computed. Here we want the Ego’s speed, so open gym_bridge.py. (This file already contains import pitwall and pitwall.init(self), so only the one value line needs adding.)
(Path: /home/hmcl/unicorn_ws/src/unicorn-racing-stack/race_utils/unicorn_gym/f1tenth_gym_ros/f1tenth_gym_ros/gym_bridge.py)
1
pitwall.log("speed", self.ego_speed[0]) # ← add just this line (logs the car's actual speed)
If import and init are not there yet, fill them in.
1
2
3
4
import pitwall # one-line telemetry: pitwall.event(...) -> /pitwall/events (line 50)
# Bind pitwall telemetry to this node (reuses its DDS participant). line 77
pitwall.init(self)
② Save and build.
1
colcon build --packages-select f1tenth_gym_ros # build only the modified package
③ Run the Sim.
1
ros2 launch stack_master race.launch.xml sim:=true map:=f
④ View the value.
Quick numeric check in the terminal:
1
ros2 topic echo /pitwall/speed
As a graph (rqt):
1
ros2 run rqt_plot rqt_plot /pitwall/speed/data
When no values appear —
pitwall.logonly emits values while a viewer is open. One ofrqt_plotorros2 topic echomust be running (seeing nothing with neither open is normal). Also, numeric values do not appear in the RViz Pitwall panel — view them inrqt_plotorecho(the panel shows events only).
Recording → Replaying a Run
Recording (same role as ros2 bag, saved as MCAP):
1
2
3
4
ros2 bag record -a # all topics → includes /pitwall/*
ros2 launch pitwall record.launch.py # default regex '/pitwall/.*' → saves only pitwall
ros2 launch pitwall record.launch.py topic_regex:='/pitwall/.*|/scan|/imu'
# pitwall + the specified sensor topics
Replaying:
1
2
3
4
5
6
# terminal 1 — replay
ros2 bag play ~/runs/lap03 # example
# terminal 2 — view (same as while recording)
ros2 run rqt_plot rqt_plot /pitwall/speed/data
# or ros2 topic echo /pitwall/speed
Wrap-up
This post covered the two ways Pitwall telemetry exposes in-code values — event notifications (pitwall.event) and value logging (pitwall.log) — with hands-on examples. Being able to observe even internal variables with a single line and no publisher declarations makes tuning and debugging loops much faster. For the Pitwall panel itself, see Using the Pitwall Panel.