Skip to main content
Version: QTrobot V3

Camera

The 3D camera (and its IMU) isn't part of the core service hub — it's served by a separate qtrobot-realsense-driver, bridged to ROS2 by its own gateway process. These examples additionally require that second gateway running, alongside the one from Connection.

Launching the RealSense gateway

python -m gateway.realsense_ros2 --ros-args -p realsense_ip:=<ROBOT_IP> -r __ns:=/qtrobot

This runs alongside the QTrobot gateway from Connection, adding camera-related services and topics under the same /qtrobot/ namespace.

Reading camera intrinsics

ros2 service call /qtrobot/camera/color/intrinsics qtrobot_interfaces/srv/CameraColorIntrinsics "{}"
ros2 service call /qtrobot/camera/depth/scale qtrobot_interfaces/srv/CameraDepthScale "{}"

The depth scale tells you how to convert a raw depth pixel value into meters — multiply the pixel value by the returned scale.

Subscribing to the color image

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from qtrobot_interfaces.msg import ImageFrameRaw


class CameraListener(Node):
def __init__(self):
super().__init__('camera_listener')
self.create_subscription(
ImageFrameRaw,
'/qtrobot/camera/color/image',
self.on_image,
10,
)

def on_image(self, msg: ImageFrameRaw):
self.get_logger().info(f'Got frame: {msg.width}x{msg.height}, encoding={msg.encoding}')


def main():
rclpy.init()
node = CameraListener()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()


if __name__ == '__main__':
main()

The same ImageFrameRaw message type is used for /qtrobot/camera/depth/image (raw depth), /qtrobot/camera/depth/aligned/image (depth aligned to the color frame) and /qtrobot/camera/depth/color/image (colorized depth), all published at 15 Hz.

Subscribing to the IMU

If the underlying driver is started with use-gyro/use-accel, the gateway also publishes IMU topics:

from qtrobot_interfaces.msg import ImuFrame

class ImuListener(Node):
def __init__(self):
super().__init__('imu_listener')
self.create_subscription(ImuFrame, '/qtrobot/camera/gyro', self.on_gyro, 10)
self.create_subscription(ImuFrame, '/qtrobot/camera/acceleration', self.on_accel, 10)

def on_gyro(self, msg: ImuFrame):
self.get_logger().info(f'gyro: x={msg.x:.3f} y={msg.y:.3f} z={msg.z:.3f} rad/s')

def on_accel(self, msg: ImuFrame):
self.get_logger().info(f'accel: x={msg.x:.3f} y={msg.y:.3f} z={msg.z:.3f} m/s^2')

Next steps

Continue with the Motor tutorial, or see the full camera namespace in the ROS2 API Reference.