---json
{"name": "Thermal camera in RViz"}
---
====== ROS 2: thermal camera in RViz ======
Connect one Axiom with an **AMG8833 8×8 thermal camera**, request its measurements and display a heatmap with a temperature label for every pixel. This uses ''axiom_driver'', ''axiom_thermal_viz'' and RViz. The dashboard is optional.
===== Expected display =====
{{ :axiom:ros2:ros2-thermal-rviz.jpg?nolink&760 |RViz thermal heatmap and pixel temperatures}}
//Illustrative 8×8 frame generated for this screenshot. The commands below use the measurements from your camera.//
===== Before starting =====
Complete [[:axiom:ros2:getting_started|Install and connect]]. For Wi-Fi, set the ''axiom'' entry in ''boards.yaml'' to ''transport: ws'' and ''device_uri: ws://YOUR_AXIOM_IP/ws''. Keep ''auto_connect'', ''auto_reconnect'' and ''autosub'' false. Attach the camera to Axiom.
Build the supplied RViz configuration from the repository root:
source scripts/setup_env.sh
rosdep install --from-paths src examples/scenarios-dashboard/src --ignore-src -r -y
colcon build --base-paths src examples/scenarios-dashboard/src --symlink-install
source scripts/setup_env.sh
Open **four terminals** and source ''~/Projects/axiom-ros2/scripts/setup_env.sh'' in each. If a driver is already running, use that session rather than starting a duplicate.
===== Terminal 1: start the driver =====
ros2 launch axiom_driver axiom_minimal_launch.py \
namespace:=/axiom boards_file:="$AXIOM_ROS_BOARDS_FILE"
Leave it running. It reads the selected board's connection settings.
===== Terminal 2: connect and request data =====
ros2 service call /axiom/connect axiom_interfaces/srv/Connect '{device_uri: ""}'
ros2 service call /axiom/publish_data_subscription \
axiom_interfaces/srv/PublishedDataSubscription '{rate_hz: 20.0}'
ros2 topic list -t --no-daemon
Both service calls should return ''success: true''. Find the topic ending in ''/thermal/grid'', with type ''axiom_interfaces/msg/ThermalGrid''. No thermal entry is required in the board file.
Set the exact discovered path; this is an **example address**:
THERMAL_TOPIC=/axiom/bus_1/device_169/thermal/grid
ros2 topic echo "$THERMAL_TOPIC" axiom_interfaces/msg/ThermalGrid \
--qos-reliability best_effort --once
Expect ''width: 8'', ''height: 8'', 64 values in ''temperature_c'' and a nonempty ''header.frame_id''. The prompt returns after one frame. Do not continue if no frame arrives.
===== Terminal 3: convert the grid to RViz markers =====
Variables belong to the terminal where you set them. Set the same camera topic here, replacing the example path with yours:
THERMAL_TOPIC=/axiom/bus_1/device_169/thermal/grid
ros2 run axiom_thermal_viz thermal_heatmap --ros-args \
-r __ns:=/sensing \
-p input_topic:="$THERMAL_TOPIC" \
-p output_topic:=thermal_heatmap \
-p use_dynamic_range:=false \
-p min_temperature:=15.0 \
-p max_temperature:=40.0
Keep it running. It subscribes to the grid and publishes ''/sensing/thermal_heatmap'' markers and ''/sensing/thermal_heatmap_labels'' temperature labels. The colour scale stays fixed at **15–40 °C**.
===== Terminal 4: select the frame and open RViz =====
Use the actual camera topic in this terminal too:
THERMAL_TOPIC=/axiom/bus_1/device_169/thermal/grid
THERMAL_FRAME="$(ros2 topic echo "$THERMAL_TOPIC" \
axiom_interfaces/msg/ThermalGrid --field header.frame_id \
--qos-reliability best_effort --once | sed -n '1p')"
printf '%s\n' "$THERMAL_FRAME"
Once a frame name is printed, run RViz **in this same terminal**:
ros2 run rviz2 rviz2 \
-d "$(ros2 pkg prefix --share axiom_marty_demo)/config/thermal.rviz" \
-f "${THERMAL_FRAME:?No camera frame received}"
You should see an 8×8 heatmap with small temperatures in °C. Move your hand near the camera and watch the cells change. Marker size is a display layout; it is not a measurement of the object's physical size or position.
===== If RViz is empty =====
^ Check ^ What to look for ^
| Raw grid | The Terminal 2 echo returns a frame. If not, check acquisition and whether the camera is online in ''/axiom/devices''. |
| Adapter input | ''input_topic'' exactly matches the discovered thermal topic. |
| Marker publisher | ''%%ros2 topic info /sensing/thermal_heatmap --verbose%%'' reports a publisher. |
| Fixed Frame | It matches ''header.frame_id'' from the camera message. |
| Displays | Heatmap uses a **Marker** display on ''/sensing/thermal_heatmap''; labels use **MarkerArray** on ''/sensing/thermal_heatmap_labels''. |
| Colour saturation | Temperatures outside 15–40 °C clip to the end colours. Adjust the limits or enable ''use_dynamic_range''. |
The heatmap can render in its own sensor frame without another TF node. RViz may still report a global warning that no TF data has been received. To place the camera in a robot's coordinate system, supply its actual mounting transform separately.
===== Clean up =====
Press Ctrl+C in Terminal 4, then Terminal 3. In Terminal 2:
ros2 service call /axiom/publish_data_subscription \
axiom_interfaces/srv/PublishedDataSubscription '{rate_hz: 0.0}'
ros2 service call /axiom/disconnect axiom_interfaces/srv/Disconnect '{}'
Finally, press Ctrl+C in Terminal 1. Back to [[:axiom:ros2:start|Axiom with ROS 2]].