yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
RDK S600 Developer Kit📖
1.RDK S600 board introduction
  • 1.1 RDK S600 board introduction
  • 1.2 System Flashing
  • 1.3 Hardware Interface Description
  • 1.4 Accessory Installation
  • 1.5 Camera Expansion Board
  • 1.6 MCU Interface Expansion Board
  • 1.7 Precautions for Using the 15.6-inch Screen
  • 1.8 System Boot Modes
2.RDK S600 basic course
  • 2.1 Network Configuration
  • 2.2 Remote Login
  • 2.3 System Update
  • 2.4 Boot Auto-Start Configuration
  • 2.5 RDK Exclusive Command Usage
  • 2.6 Linux Command Usage
  • 2.7 Examples of GPIO Read and Write Operations
  • 2.8 Using the USB Camera
  • 2.9 Solid-state mounting
  • 2.10 SSD expansionnew
3.TogetheROS.Bot Vision Applications
  • 1. About TogetheROS. Bot
  • 2. System Installation
  • 3. Object Detection(YOLO)
  • 4. Image Classification(mobilenetv2)
  • 5. Image Segmentation(mobilenet_unet)
  • 6. Perception Algorithm(BEV)
  • 7. Human Detection and Tracking (Ultralytics YOLO Pose)
4. Offline AI Large Model Development
Offline large model (Text Interaction)
  • 1. AI large model environment deployment
  • 2. Install large model dialogue platform
  • 3. Meta AI Llama 3.2 model
  • 4. Alibaba Cloud Qwen3 model
  • 5. Microsoft Phi-4 mini model
  • 6. DeepSeek - DeepSeek-R1 model
  • 7. Alibaba Cloud Qwen2.5vl Visual Multimodal Large Model
  • 8. Google Gemma3 Visual Multimodal Large Model
  • 9. Lava Visual Multimodal Large Model
  • 10. MiniCPM-V Visual Multimodal Large Model
  • 11. Multimodal visual understand application
  • 12. Multimodal text image application
  • 13. Multimodal visual localization application
  • 14. Multimodal table scanning application
  • 15. Multimodal Autonomous Agent Applications
Offline large model (Voice Interaction)
  • 0. Voice Interaction Hardware Connection (Must Read)
  • 1. Offline speech-to-text (ASR)
  • 2. Offline Text-to-Speech (TTS)
  • 3. AI large model voice interaction
  • 4. Multimodal visual understanding voice interaction
  • 5. Multimodal Text-to-Image application
  • 6. Multimodal video analytics application
  • 7. Multimodal visual localization application
  • 8. Multimodal table scanning application
  • 9. Multimodal autonomous agent application
  • 10. AI Large Model Offline Voice Assistant
5. Online AI Large Model Development
Online large model (Text Interaction)
  • 1.OpenRouter large model API aggregation platform
  • 2.Multimodal visual understand application
  • 3.Multimodal visual localization application
  • 4.Multimodal table scanning application
  • 5.Multimodal autonomous proxy application
Online large model (Voice Interaction)
  • 0.Voice interaction hardware connection (ReadMe)
  • 1.Online speech to text (ASR)
  • 2.Online text to speech (TTS)
  • 3.AI large model voice interaction
  • 4.Multimodal visual understand speech interaction
  • 5.Multimodal visual localization application
  • 6.Multimodal table scanning application
  • 7.Multimodal autonomous proxy application
  • 8.AI large model online voice assistant
6.YOLO26 tutorials
  • 01.YOLO26 environment
  • 02.CLI use
  • 03.Object detection
  • 04.Instance segmentation
  • 05.Pose estimation
  • 06.Image classification
  • 07.Oriented object detection
  • 08.Model conversion
  • 09.Dataset annotation
  • 10.Model training - conversion
  • 11.Model prediction
7.OpenClaw Advanced Development
  • 1. OpenClaw Deployment
  • 2. OpenClaw and WhatsApp Plugin Application
  • 3. OpenClaw TUI Interaction
  • 4. OpenClaw WebChat Interaction
  • 5. OpenClaw Gate Gateway Operation Manual
  • 6. OpenClaw Plugin Function Introduction
  • 7. OpenClaw Tools Introduction
  • 8. OpenClaw ClawHub Introduction (skill Installation)
  • 9.OpenClaw Application - File Management
  • 10.OpenClaw Application - Browser Control
  • 11.OpenClaw Application - Camera
  • 12.OpenClaw Application - Script Execution
  • 13.OpenClaw Application - AI Programming (Peripheral & GPIO Control)
  • 14. OpenClaw Application - Dedicated AI Assistant
  • 15. OpenClaw Configure Web Search Capability
8.ROS2 basic course
  • 1.Introduction to ROS2
  • 2.ROS2 install Jazzy
  • 3.ROS2 development environment
  • 4.ROS2 workspace
  • 5.ROS2 function package
  • 6.ROS2 node
  • 7.ROS2 topic communication
  • 8.ROS2 service communication
  • 9.ROS2 action communication
  • 10.ROS2 custom interface message
  • 11.ROS2 parameter service case
  • 12.ROS2 meta-function package
  • 13.ROS2 distributed communication
  • 14.ROS2 DDS
  • 15.ROS2 time related API
  • 16.ROS2 common command tools
  • 17.ROS2 rviz2 use
  • 18.ROS2 rqt toolbox
  • 19.ROS2 Launch startup file configuration
  • 20.ROS2 recording and playback tool
  • 21.ROS2 URDF model
  • 22.ROS2 Gazebo simulation platform
  • 23.ROS2 TF2 coordinate transformation
Download
  • System_File
  • Code
  • 3D_Model_File
  • Tools_Software
Download ZIP

Welcome to RDK S600 Developer Kit repository

23.ROS2 TF2 coordinate transformation

23. ROS2 TF2 Coordinate Transformation

Note: The accompanying reference video uses the ROS Humble version, for reference only

1. TF2 Overview

The coordinate system is a very familiar concept and an important foundation in robotics. In a complete robot system, there are many coordinate frames. How should we manage the positional relationships between these coordinate frames? ROS provides us with a powerful tool for managing coordinate frames: TF2.

TF system reference: tf: The transform library | IEEE Conference Publication | IEEE Xplore

2. Coordinate Frames in Robots

In mobile robot systems, coordinate frames are equally crucial. For example, a mobile robot's center point is the base coordinate frame (Base Link). The position where the LiDAR is located is called the LiDAR coordinate frame (laser link). When the robot moves, the odometer accumulates position. This position's reference frame is called the odometer coordinate frame (odom). The odometer also has accumulated errors and drift. The reference frame for absolute position is called the map coordinate frame (map).

The relationships between coordinate frames at each level are complex. Some are relatively fixed, while others are constantly changing. Simple coordinate frames become complex within a spatial range, making a good coordinate frame management system particularly important.

image-20220528142112163

The basic theory of coordinate frame transformation relationships is explained in every robotics textbook. It can be decomposed into two parts: translation and rotation, described by a 4x4 matrix. Draw coordinate frames in space, and the transformation relationship between them is actually a vector's mathematical description.

The underlying principle of TF functionality in ROS is the encapsulation of these mathematical transformations. For detailed theoretical knowledge, you can refer to robotics textbooks. We will mainly explain how to use the TF coordinate management system.

3. TF Command Line Operations

First, through the example of two turtles, let's understand a robot following algorithm based on coordinate frames. For easier demonstration, it's best to operate this section's course in a virtual machine.

3.1. Install Related Tools

This example requires installing the corresponding packages, tf turtle simulator example, and tf tree visualization tool:

sudo apt install ros-${ROS_DISTRO}-turtle-tf2-py ros-jazzy-tf2-tools
sudo pip3 install transforms3d --break-system-packages
sudo apt install ros-${ROS_DISTRO}-rqt-tf-tree

image-20250905190746493

 

3.2. Start

Then you can start through a launch file. After that, we can control one turtle, and the other turtle will automatically follow.

xxxxxxxxxx
ros2 launch turtle_tf2_py turtle_tf2_demo.launch.py
ros2 run turtlesim turtle_teleop_key

When we control one turtle to move, the other turtle will also follow.

image-20231031174611320

3.3. View TF Tree

xxxxxxxxxx
ros2 run rqt_tf_tree rqt_tf_tree

You can see the TF transform tree in the rqt window.

image-20231031174844745

3.4. Query Coordinate Transform Information

Just seeing the structure of coordinate frames is not enough. If we want to know the specific relationship between two coordinate frames, we can use the tf2_echo tool:

xxxxxxxxxx
ros2 run tf2_ros tf2_echo turtle2 turtle1

After successful execution, the terminal will continuously print the coordinate frame transformation values.

image-20231031174933242

3.5. Coordinate Frame Visualization

  • Run rviz2, then add TF display plugin:

xxxxxxxxxx
rviz2

In rviz2, set the reference coordinate frame to: world, add TF display, and then let the turtle move. The coordinate axes in Rviz will start moving. Isn't this more intuitive?

image-20231031175440027

 

4. Static Coordinate Transformation

Static coordinate transformation refers to the relative position between two coordinate frames being fixed. For example, the position between the LiDAR and base_link is fixed.

Example: For easier demonstration, it's best to operate this section's course in a virtual machine.

 

4.1. Publish Pose from A to B

xxxxxxxxxx
ros2 run tf2_ros static_transform_publisher 0 0 3 0 0 3.14 A B

image-20250905190855196

4.2. Listen/Get TF Relationship

xxxxxxxxxx
ros2 run tf2_ros tf2_echo A B

4.3. Rviz Visualization

  • Run rviz2, then add TF display plugin:

xxxxxxxxxx
rviz2

image-20231031180746331

5. Example Introduction

The previous section explained the TF relationships in the turtle following example provided by the system. This section we implement this functionality ourselves.

Course content:

  • Implement the turtle following example through programming

  • Master implementing dynamic broadcasters through programming

  • Master listening to coordinate transformations between coordinate frames through programming

  • Master PID control to convert physical quantities (distance, angle) into velocity control values

Advanced content:

  • Understand TF system's cross-time-dimension coordinate frame transformation functionality

6. Turtle Following Example Implementation Principle Analysis

image-20220528143750881

In the two-turtle simulator, we can define three coordinate frames. For example, the simulator's global reference frame is called world. The turtle1 and turtle2 coordinate frames are at the center points of the two turtles. This way, the relative position of turtle1 and the world coordinate frame can represent turtle 1's position. The same applies to turtle 2.

To make turtle 2 move toward turtle 1, we draw a line between them and add an arrow. Does this remind you of vector calculations from high school? We said the description method for coordinate transformations is vectors. So in this following example, TF can solve this well.

The vector's length represents distance, and the direction represents angle. With distance and angle, we can set a time arbitrarily and calculate velocity. Then it's just the encapsulation and publishing of velocity topics, and turtle 2 can start moving.

Therefore, the core of this example is implementing vector calculations through coordinate frames. The two turtles keep moving, so this vector also needs to be calculated periodically. This requires TF's dynamic broadcasting and listening.

7. Create Package

  1. Create a new package in the workspace src directory to store our files:

xxxxxxxxxx
ros2 pkg create pkg_tf --build-type ament_python --dependencies rclpy --node-name turtle_tf_broadcaster

After executing the above command, the pkg_tf package will be created, along with a turtle_tf_broadcaster node, and the related configuration files will already be set up. Add the following code to the [turtle_tf_broadcaster.py] file:

 

​x
import rclpy                                       # ROS2 Python interface library
from rclpy.node import Node                        # ROS2 Node class
from geometry_msgs.msg import TransformStamped     # Transform message
import tf_transformations                          # TF coordinate transformation library
from tf2_ros import TransformBroadcaster           # TF coordinate transformation broadcaster
from turtlesim.msg import Pose                     # turtlesim turtle position message

class TurtleTFBroadcaster(Node):

    def __init__(self, name):
        super().__init__(name)                                # ROS2 node parent class initialization

        self.declare_parameter('turtlename', 'turtle')        # Create a turtle name parameter
        self.turtlename = self.get_parameter(                 # Prefer external parameter value, otherwise use default
            'turtlename').get_parameter_value().string_value

        self.tf_broadcaster = TransformBroadcaster(self)      # Create and initialize TF broadcast object

        self.subscription = self.create_subscription(         # Create subscriber for turtle position messages
            Pose,
            f'/{self.turtlename}/pose',                       # Use turtle name obtained from parameter
            self.turtle_pose_callback, 1)

    def turtle_pose_callback(self, msg):                              # Callback to transform position messages to coordinate transforms
        transform = TransformStamped()                                # Create transform message object

        transform.header.stamp = self.get_clock().now().to_msg()      # Set timestamp for transform message
        transform.header.frame_id = 'world'                           # Set source coordinate frame for transform
        transform.child_frame_id = self.turtlename                    # Set target coordinate frame for transform
        transform.transform.translation.x = msg.x                     # Set X, Y, Z translation in transform
        transform.transform.translation.y = msg.y
        transform.transform.translation.z = 0.0
        q = tf_transformations.quaternion_from_euler(0, 0, msg.theta) # Convert Euler angles to quaternion (roll, pitch, yaw)
        transform.transform.rotation.x = q[0]                         # Set X, Y, Z rotation in transform (quaternion)
        transform.transform.rotation.y = q[1]
        transform.transform.rotation.z = q[2]
        transform.transform.rotation.w = q[3]

        # Send the transformation
        self.tf_broadcaster.sendTransform(transform)     # Broadcast transform, update transform info when turtle position changes

def main(args=None):
    rclpy.init(args=args)                                # ROS2 Python interface initialization
    node = TurtleTFBroadcaster("turtle_tf_broadcaster")  # Create and initialize ROS2 node object
    rclpy.spin(node)                                     # Loop waiting for ROS2 exit
    node.destroy_node()                                  # Destroy node object
    rclpy.shutdown()                                     # Shutdown ROS2 Python interface

 

  1. Next, create a [turtle_following.py] file in the same directory as turtle_tf_broadcaster.py and add the following code:

xxxxxxxxxx
import math
import rclpy                                              # ROS2 Python interface library
from rclpy.node import Node                               # ROS2 Node class
import tf_transformations                                 # TF coordinate transformation library
from tf2_ros import TransformException                    # TF transform exception class
from tf2_ros.buffer import Buffer                         # Buffer class for storing transform information
from tf2_ros.transform_listener import TransformListener  # Transform listener class
from geometry_msgs.msg import Twist                       # ROS2 velocity control message
from turtlesim.srv import Spawn                           # Turtle spawn service interface
class TurtleFollowing(Node):

    def __init__(self, name):
        super().__init__(name)                                      # ROS2 node parent class initialization

        self.declare_parameter('source_frame', 'turtle1')           # Create source frame name parameter
        self.source_frame = self.get_parameter(                     # Prefer external parameter value, otherwise use default
            'source_frame').get_parameter_value().string_value

        self.tf_buffer = Buffer()                                   # Create buffer for storing transform information
        self.tf_listener = TransformListener(self.tf_buffer, self)  # Create transform listener

        self.spawner = self.create_client(Spawn, 'spawn')           # Create client for requesting turtle spawning
        self.turtle_spawning_service_ready = False                  # Flag for whether turtle spawning service has been requested
        self.turtle_spawned = False                                 # Flag for whether turtle has been successfully spawned

        self.publisher = self.create_publisher(Twist, 'turtle2/cmd_vel', 1) # Create velocity topic for following turtle's motion

        self.timer = self.create_timer(1.0, self.on_timer)         # Create periodic timer to control following turtle's motion

    def on_timer(self):
        from_frame_rel = self.source_frame                         # Source coordinate frame
        to_frame_rel   = 'turtle2'                                 # Target coordinate frame

        if self.turtle_spawning_service_ready:                     # If turtle spawning service has been requested
            if self.turtle_spawned:                                # If following turtle has been spawned
                try:
                    now = rclpy.time.Time()                        # Get current ROS time
                    trans = self.tf_buffer.lookup_transform(       # Listen for transform from source to target at current time
                        to_frame_rel,
                        from_frame_rel,
                        now)
                except TransformException as ex:                   # If transform acquisition fails, enter exception report
                    self.get_logger().info(
                        f'Could not transform {to_frame_rel} to {from_frame_rel}: {ex}')
                    return

                msg = Twist()                                      # Create velocity control message
                scale_rotation_rate = 1.0                          # Calculate angular velocity based on turtle angle
                msg.angular.z = scale_rotation_rate * math.atan2(
                    trans.transform.translation.y,
                    trans.transform.translation.x)

                scale_forward_speed = 0.5                          # Calculate linear velocity based on turtle distance
                msg.linear.x = scale_forward_speed * math.sqrt(
                    trans.transform.translation.x ** 2 +
                    trans.transform.translation.y ** 2)

                self.publisher.publish(msg)                        # Publish velocity command, turtle follows motion
            else:                                                  # If following turtle has not been spawned
                if self.result.done():                             # Check if turtle has been spawned
                    self.get_logger().info(
                        f'Successfully spawned {self.result.result().name}')
                    self.turtle_spawned = True
                else:                                              # Following turtle still not spawned
                    self.get_logger().info('Spawn is not finished')
        else:                                                      # If turtle spawning service has not been requested
            if self.spawner.service_is_ready():                    # If turtle spawning server is ready
                request = Spawn.Request()                          # Create request data
                request.name = 'turtle2'                           # Set request data content, including turtle name, xy position, pose
                request.x = float(4)
                request.y = float(2)
                request.theta = float(0)

                self.result = self.spawner.call_async(request)     # Send service request
                self.turtle_spawning_service_ready = True          # Set flag indicating request has been sent
            else:
                self.get_logger().info('Service is not ready')     # Prompt that turtle spawning server is not ready


def main(args=None):
    rclpy.init(args=args)                       # ROS2 Python interface initialization
    node = TurtleFollowing("turtle_following")  # Create and initialize ROS2 node object
    rclpy.spin(node)                            # Loop waiting for ROS2 exit
    node.destroy_node()                         # Destroy node object
    rclpy.shutdown()                            # Shutdown ROS2 Python interface

 

  1. Create a launch folder under the pkg_tf package. Create a [turtle_following.launch.py] file in the launch folder and add the following content:

xxxxxxxxxx
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

def generate_launch_description():

    return LaunchDescription([
        DeclareLaunchArgument('source_frame', default_value='turtle1', description='Target frame name.'),
        Node(
            package='turtlesim',
            executable='turtlesim_node',
        ),
        Node(
            package='pkg_tf',
            executable='turtle_tf_broadcaster',
            name='broadcaster1',
            parameters=[
                {'turtlename': 'turtle1'}
            ]
        ),
        Node(
            package='pkg_tf',
            executable='turtle_tf_broadcaster',
            name='broadcaster2',
            parameters=[
                {'turtlename': 'turtle2'}
            ]
        ),
        Node(
            package='pkg_tf',
            executable='turtle_following',
            name='listener',
            parameters=[
                {'source_frame': LaunchConfiguration('source_frame')}
            ]
        ),
    ])

 

8. Edit Configuration File

8.1. Configure in setup.py

  • Import related libraries:

xxxxxxxxxx
import os
from glob import glob
  • Add turtle_following node information and add command to copy launch files to install's shared directory:

xxxxxxxxxx
(os.path.join('share',package_name,'launch'),glob('launch/*')),

image-20250905192526237

 

9. Build Package

xxxxxxxxxx
colcon build --packages-select pkg_tf

image-20250905192624459

 

10. Run Program

  • Refresh terminal environment variables, then run:

xxxxxxxxxx
ros2 launch pkg_tf turtle_following.launch.py

image-20250905192745346

 

  • Start turtle keyboard control node. Control the first turtle's motion, and the second turtle will automatically follow:

xxxxxxxxxx
ros2 run turtlesim turtle_teleop_key

image-20250905192830965

In this terminal, pressing the arrow keys can control one turtle to move, and then the other turtle will follow until they coincide.

 

11. Advanced Content

  • Understand TF's cross-time-dimension transformation capability

    Buffer can automatically cache all TF transformation relationships within the TF system for the past 10 seconds (the cache duration can be set arbitrarily through Buffer construction parameters). All transformations in the buffer are timestamped, and all transformations are continuously traceable. Even if two coordinate frames are at different time points, the transformation relationship between them can still be found. For this aspect, you can refer to the TF system design reference. There are detailed principles explained (the reference is in this section's course folder, or through the link at the beginning of this section).

image-20250905193230441

 

  • The following is a supplement to our turtle following example. The red arrows indicate the ability to query transformations between two coordinate frames at different time points across time.

image-20250905193837592

ROS2 Gazebo simulation platform

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文