AI 3D建模工具: Tripo 3D | Meshy AI
在机器人学中,传感器是感知的基础。它们通过将物理信号转换为可测量的数据,使机器人能够理解其环境。今天,我将简要介绍机器人学中使用的三种关键传感器——LiDAR、IMU和深度摄像头——以及它们如何与ROS 2集成以实现实际应用。
1、什么是LiDAR?
LiDAR = 光探测与测距(Light Detection And Ranging)。 它是一种主动传感器——发射自己的光(红外激光脉冲)并测量光子返回所需的时间。根据这个时间,它计算到周围物体的精确距离,构建一个称为点云的精确空间地图。
与摄像头(被动——仅捕获环境光)不同,LiDAR可以在完全黑暗中工作,穿透灰尘和雾气(范围会减小),并给出直接的度量距离,无需任何推理或估算。
1.1 飞行时间公式
d = (c × t) / 2
d = 距离(米),c = 光速(3×10⁸ m/s),t = 往返时间(秒)
t = 2d / c
重新排列:光传播到物体并返回所需的时间
示例:d=5m → t = (2×5) / (3×10⁸) = 33.3 ns
分辨率:1ps TDC → Δd = (3×10⁸ × 1×10⁻¹²) / 2 = 0.15 mm
这就是LiDAR能够实现毫米级精度的原因!

LiDAR硬件流程

1.2 LiDAR有分类吗?
是的,LiDAR的分类与RADAR一样根据维度区分,分为1D、2D和3D。"D"对应维度(Dimensions)。
- 1D LiDAR 由静止的激光束组成,在一个轴上计算障碍物与扫描器之间的距离,即一个维度。
- 2D LiDAR 由一束激光组成,带有旋转机制,收集到目标的水平距离数据,获取X和Y轴上的数据。
- 3D LiDAR 的原理相同,但多束激光垂直堆叠发射,获取X、Y和Z轴上的数据。每束激光与其它激光束之间有一个角度差。
1.3 架构

1.4 数据类型 — 原始硬件 → ROS 2消息


1.5 TF2变换树 — 坐标系
TF2是ROS 2的坐标变换系统。每个传感器和链接都有一个命名的坐标系(frame)。TF2知道每个坐标系的相对位置,可以自动将任何点从任何坐标系变换到任何其他坐标系——例如,摄像头坐标系中的检测结果 → 世界地图坐标系。

ROS 2 LiDAR命令
# ─── Essential ROS 2 LiDAR CLI commands ─────────────────────
# Start RPLIDAR driver
ros2 run rplidar_ros rplidar_composition \
--ros-args -p serial_port:=/dev/ttyUSB0 \
-p serial_baudrate:=256000
# See what's being published
ros2 topic list
# → /scan (sensor_msgs/LaserScan)
# See actual scan data (ctrl+c to stop)
ros2 topic echo /scan --once
# Check publish rate (should be ~10 Hz)
ros2 topic hz /scan
# Visualize in RViz2 (best tool for LiDAR!)
rviz2
# Add → LaserScan → topic: /scan → style: Points → size: 0.02
# Record a bag file (save data for offline work)
ros2 bag record /scan /tf /odom -o my_lidar_session
# Replay bag file (test SLAM without physical robot)
ros2 bag play my_lidar_session --loop
# Run SLAM Toolbox (easiest 2D SLAM in ROS 2)
sudo apt install ros-humble-slam-toolbox
ros2 launch slam_toolbox online_async_launch.py
# Save the map when done exploring
ros2 service call /slam_toolbox/save_map \
slam_toolbox/srv/SaveMap "{name: {data: 'my_map'}}"
# Load saved map for navigation (no re-mapping needed)
ros2 launch nav2_bringup bringup_launch.py \
map:=my_map.yaml use_sim_time:=false
2、深度摄像头传感器
深度摄像头,也称为RGB-D(红-绿-蓝-深度)传感器,同时捕获彩色图像和逐像素深度信息,实现对环境的三维感知。与仅捕获3D世界的2D投影的传统摄像头不同,深度摄像头添加了关键的第三维度,使机器人能够理解到物体的距离、安全导航并构建周围环境的3D地图。
2.1 深度测量技术

2.2 飞行时间(ToF)
飞行时间摄像头通过计算发射光传播到物体并反射回传感器所需的时间来测量深度。这可以使用脉冲光(测量实际传播时间)或连续波调制(测量相位差)来实现。ToF摄像头在户外和变化的光照条件下特别有用,因为它们主动控制照明源。
2.3 立体视觉
立体视觉使用两个或多个相隔已知基线距离的摄像头来模拟人类双眼视觉。通过在左右图像中找到对应点并测量它们的视差(水平偏移),可以通过三角测量计算深度。立体视觉是被动的(不需要红外发射器)并在户外效果良好,但需要有纹理的表面才能进行可靠的匹配。

深度处理流程

点云生成:
点云生成将2D深度图转换为空间中的一组3D点。深度图像中的每个像素使用摄像头内参转换为3D坐标(X, Y, Z)。当与RGB数据结合时,每个点还有颜色信息(R, G, B),创建场景的彩色3D表示。

深度摄像头的ROS 2集成
深度摄像头主题结构

深度摄像头驱动代码
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image, CameraInfo, PointCloud2, PointField
from std_msgs.msg import Header
import numpy as np
import struct
class DepthCameraPublisher(Node):
def __init__(self):
super().__init__('depth_camera_publisher')
self.declare_parameter('camera_name', 'camera')
self.declare_parameter('frame_id', 'camera_depth_optical_frame')
self.camera_name = self.get_parameter('camera_name').value
self.frame_id = self.get_parameter('frame_id').value
self.rgb_pub = self.create_publisher(Image, f'/{self.camera_name}/rgb/image_raw', 10)
self.depth_pub = self.create_publisher(Image, f'/{self.camera_name}/depth/image_raw', 10)
self.pc_pub = self.create_publisher(PointCloud2, f'/{self.camera_name}/depth/points', 10)
# Camera intrinsics
self.fx, self.fy = 614.5, 614.5
self.cx, self.cy = 319.5, 239.5
self.depth_scale = 0.001
self.timer = self.create_timer(0.033, self.publish_frames)
def publish_frames(self):
stamp = self.get_clock().now().to_msg()
header = Header(stamp=stamp, frame_id=self.frame_id)
# Capture from sensor (placeholder)
rgb_image = self.capture_rgb()
depth_image = self.capture_depth()
# Publish RGB
rgb_msg = self.create_image_msg(rgb_image, 'rgb8', header)
self.rgb_pub.publish(rgb_msg)
# Publish Depth
depth_msg = self.create_image_msg(depth_image, '16UC1', header)
self.depth_pub.publish(depth_msg)
# Publish Point Cloud
pc_msg = self.create_pointcloud(depth_image, rgb_image, header)
self.pc_pub.publish(pc_msg)
def create_image_msg(self, image, encoding, header):
msg = Image()
msg.header = header
msg.height, msg.width = image.shape[:2]
msg.encoding = encoding
msg.is_bigendian = False
msg.step = image.nbytes // msg.height
msg.data = image.tobytes()
return msg
def create_pointcloud(self, depth, rgb, header):
fields = [
PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1),
PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1),
PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1),
PointField(name='rgb', offset=12, datatype=PointField.FLOAT32, count=1)
]
points = []
for v in range(depth.shape[0]):
for u in range(depth.shape[1]):
z = depth[v, u] * self.depth_scale
if z <= 0 or z > 10.0:
continue
x = (u - self.cx) * z / self.fx
y = (v - self.cy) * z / self.fy
r, g, b = rgb[v, u, 2], rgb[v, u, 1], rgb[v, u, 0]
rgb_val = struct.unpack('f', struct.pack('I', (r<<16)|(g<<8)|b))[0]
points.append(struct.pack('ffff', x, y, z, rgb_val))
msg = PointCloud2()
msg.header = header
msg.height, msg.width = 1, len(points)
msg.fields = fields
msg.point_step = 16
msg.row_step = 16 * len(points)
msg.data = b''.join(points)
return msg
def capture_rgb(self):
return np.zeros((480, 640, 3), dtype=np.uint8)
def capture_depth(self):
return np.zeros((480, 640), dtype=np.uint16)
def main(args=None):
rclpy.init(args=args)
node = DepthCameraPublisher()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
3、结束语
总之,LiDAR提供精确的距离测量,IMU提供运动和姿态数据,深度摄像头提供密集的3D场景理解。当在ROS 2中使用TF2和适当的消息结构将它们融合在一起时,它们能够在机器人系统中实现强大的感知、SLAM和自主导航。
原文链接: About Sensors: Lidar, Depth Camera etc..
BimAnt翻译整理,转载请标明出处