Skip to main content

Static Transforms

Static transforms (TFs) define the position and orientation of each sensor relative to the UAV's body frame. These are essential for the MRS system to correctly interpret sensor data.

When TFs Are Needed

Custom static transforms are needed if the UAV has sensors whose transforms are not already provided by the MRS system. Common sensors requiring custom transforms include:

  • External cameras
  • LiDARs
  • Additional IMUs

Getting Sensor Offsets

Request the sensor offset data (position and orientation relative to the UAV frame) from the hardware team. These measurements typically come from the CAD model and include:

  • Translation: X, Y, Z offsets in meters
  • Rotation: Roll, pitch, yaw in radians (or quaternion)

Setting Up Transforms

All custom static transforms for a UAV are grouped into a single ROS2 launch file inside the session's launch/ folder:

example_session/
└── launch/
└── static_tfs.launch.xml

This file publishes one static_transform_publisher node per sensor. Keeping every TF in one place makes the setup easier to review, version, and hand off between sessions.

Creating static_tfs.launch.xml

Create launch/static_tfs.launch.xml and add a <node> block per sensor:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="uav_name" default="$(env UAV_NAME)" />
<group>
<push-ros-namespace namespace="$(var uav_name)"/>
<!-- LiDAR -->
<node pkg="tf2_ros" exec="static_transform_publisher" name="tf_fcu_to_livox"
args="--x 0.0 --y 0.0 --z 0.05 --roll 0.0 --pitch 0.0 --yaw 0.0
--frame-id $(var uav_name)/fcu --child-frame-id $(var uav_name)/livox" />

<!-- Front camera -->
<node pkg="tf2_ros" exec="static_transform_publisher" name="tf_fcu_to_front_camera"
args="--x 0.10 --y 0.0 --z 0.02 --roll 0.0 --pitch 0.0 --yaw 0.0
--frame-id $(var uav_name)/fcu --child-frame-id $(var uav_name)/front_camera" />

<!-- Add more <node> blocks for additional sensors -->
</group>
</launch>

A few things to note:

  • $(env UAV_NAME) pulls the UAV name from the environment, so frame IDs are automatically namespaced (e.g. uav1/fcu, uav1/livox).
  • --frame-id is the parent frame (usually $(var uav_name)/fcu), --child-frame-id is the sensor frame.
  • Arguments use the named flag syntax (--x, --roll, --frame-id, …) passed through args="...", not positional arguments.
  • Node names (name="tf_fcu_to_...") must be unique within the launch file.

Adding to the Tmux Session

Launch the file from a single pane in the tmux session's input array:

input=(
# ... other panes ...
'StaticTFs' 'waitForTime; ros2 launch ./launch/static_tfs.launch.xml
'
# ... other panes ...
)

waitForTime ensures the system clock is synchronized before the transforms start publishing.

Using tf_reconfigure

The tf_reconfigure tool provides an interactive way to fine-tune static transforms at runtime. Once the values are confirmed, copy them into static_tfs.launch.xml so they persist across sessions. See the tf reconfigure guide for usage instructions.

Verification

After setting up all transforms, run the tmux session and visualize them in RViz:

  1. Start the tmux session
  2. Open RViz on a connected computer
  3. Add the TF display
  4. Verify that all sensor frames appear in the correct positions relative to the UAV body frame

Check that:

  • Sensor frames are oriented correctly (X forward, Y left, Z up by convention)
  • Distances between frames match the physical measurements
  • No transforms are missing or duplicated