Stretch Python Bridge
The stretch_python_bridge package provides Python generators that allow simple, synchronous access to asynchronous ROS 2 topics like images, pointclouds, and TF transforms. This is particularly useful for quickly writing scripts or for integration into standard python loop structures without the need for explicitly setting up ROS2 subscriptions and callbacks for topics.
Prerequisites
For the streams to work properly, ensure the primary robot nodes and Zenoh router are running in the background:
ros2 run rmw_zenoh_cpp rmw_zenohd
ros2 launch stretch_core stretch_driver.launch.py
ros2 launch stretch_core dual_hesai.launch.py
ros2 launch stretch_core luxonis.launch.py
ros2 launch stretch_core gripper_camera.launch.pyFeatures
Generators for ROS 2 Topics: Access the latest message from a topic directly without defining subscriptions or explicit callbacks.
Image Bridge: Convert ROS 2
sensor_msgs/Imagetopis to NumPy arrays seamlessly. Yields a numpy array.PointCloud2 Bridge: Convert ROS 2
sensor_msgs/PointCloud2streams to structured NumPy arrays, making it easy to access fields like x, y, z, and intensity. Yields a numpy array.Transforms Bridge: Query TF2 transforms asynchronously and yield the 4x4 homogenous transformation matrix from a base frame to a target frame. Yields a 4x4 tracking numpy ndarray.
CameraInfo Bridge: Convert
sensor_msgs/CameraInfostreams to fetch identical timestamped intrinsic parameter arrays cleanly.IMU Bridge: Convert
sensor_msgs/Imustreams to fetch identical timestamped IMU data arrays cleanly.
Installation
This package is a standard ament_python package. Compile the ROS workspace with colcon build:
Typical usage
Prepared Methods for Known Topics
To make scripts exceptionally concise, all primary robot cameras and lidars have prepared wrapper methods inside the module export that stream the payloads locally. They natively support (timeout: float | None = 10.0, blocking: bool = True).
stream_camera_center()→/cameras_head/center/image_rawstream_camera_center_rotated()→/cameras_head/center/rotated_imagestream_camera_center_info()→/cameras_head/center/camera_infostream_camera_left()→/cameras_head/left/image_rawstream_camera_left_rotated()→/cameras_head/left/rotated_imagestream_camera_left_info()→/cameras_head/left/camera_infostream_camera_right()→/cameras_head/right/image_rawstream_camera_right_rotated()→/cameras_head/right/rotated_imagestream_camera_right_info()→/cameras_head/right/camera_infostream_lidar_points_left()→/lidar_points_leftstream_lidar_points_right()→/lidar_points_rightstream_gripper_imu()→/cameras_gripper/imu/datastream_gripper_right_info()→/cameras_gripper/right/camera_infostream_gripper_right()→/cameras_gripper/right/image_rawstream_gripper_stereo_info()→/cameras_gripper/stereo/camera_infostream_gripper_stereo()→/cameras_gripper/stereo/image_rawstream_gripper_stereo_points()→/cameras_gripper/stereo_left_rgbd/points
Examples:
1. Typical usage using Stream Manager
If your script requires monitoring multiple ROS topics simultaneously (e.g., streaming images from 3 cameras and a TF listener at the same time), using the individual generator methods will spawn heavy background threads for each topic.
Instead, use StreamManager to monitor an unlimited number of topics using only a single internal execution thread.
For custom topics, you can use your own stream generators
Blocking vs Non-blocking Generators
The bridging functions are split into two variants for each data type:
Blocking Generators (e.g.
image_stream_blocking,tf_stream_blocking): Guarantee a non-Nonereturn. Callingnext()or using them in aforloop will block indefinitely until a new frame or message arrives.Non-blocking Generators (e.g.
image_stream): Can be configured to be completely non-blocking, or blocking with a specific timeout window. They yieldFrame | None.
1. Image Stream Example
Use the image_stream_blocking to effortlessly fetch frames from an active image topic.
2. Pointcloud Stream Example
Use the pointcloud_stream_blocking generator to get the most recent pointcloud as a structured Numpy array. Given the structured output, you can query specific fields using keys.
3. Transforms Stream Example
Use the tf_stream to track the geometric relationship and 6DoF pose of arbitrary frames. The matrix yielded is a 4x4 affine homogenous transformation containing rotation and translation data.
Frame Dataclasses
All generator wrappers from this bridge yield native Python dataclasses, providing clean and strongly-typed interfaces to underlying ROS 2 messages.
Here is the structure and available bindings for each underlying datum:
ImageFrame
ImageFrameReturned by image_stream, stream_camera_center, etc.
image: np.ndarray: A standard NumPy array representing the image data. Its dimensions and encoding match the original topic config.timestamp: float: The absolute floating-point timestamp acquired from the ROS 2 message header (sec + nanosec * 1e-9).
PointCloudFrame
PointCloudFrameReturned by pointcloud_stream, stream_lidar_points_left, etc.
points: np.ndarray: A structured NumPy array output fromros2_numpy. Common accessible channels include.points['x'],.points['y'],.points['z'], and.points['intensity'].timestamp: float: The absolute floating-point timestamp acquired from the ROS 2 message header.
TransformsFrame
TransformsFrameReturned by tf_stream.
transform_4x4: np.ndarray: A 4x4 homogenous affine transformation matrix containing the resolved translation and rotation from the queried base frame to target frame.timestamp: float: The absolute floating-point timestamp acquired from the ROS 2 TF buffer.
ImuFrame
ImuFrameReturned by imu_stream, stream_gripper_imu.
orientation: np.ndarray: 1D array natively ordered as[x, y, z, w].angular_velocity: np.ndarray: 1D array ordered as[x, y, z].linear_acceleration: np.ndarray: 1D array ordered as[x, y, z].timestamp: float: The absolute floating-point timestamp acquired from the ROS 2 message header.
CameraInfoFrame
CameraInfoFrameReturned by camera_info_stream, stream_camera_center_info, etc.
camera_matrix: np.ndarray: A 3x3 NumPy array of the intrinsicKparameters.distortion_coefficients: np.ndarray: A 1D NumPy array covering theDvector.distortion_model: str: The specific distortion model (e.g.plumb_bob) utilized by this camera logic.timestamp: float: The absolute floating-point timestamp acquired from the ROS 2 message header.
Last updated
Was this helpful?
