本工作区聚合了机器人末端姿态采集、棋盘格检测、相机驱动以及手眼标定的完整链路。以下文档帮助你快速了解各个节点/脚本的作用、启动方式与常见问题排查方法。
- 操作系统:Ubuntu 22.04 + ROS 2 Humble(其它发行版请据此调整依赖包名)。
- 基础依赖:
sudo apt update sudo apt install ros-humble-rclpy ros-humble-tf2-ros ros-humble-cv-bridge \ ros-humble-image-geometry ros-humble-rclcpp-components python3-serial pip3 install --user opencv-python numpy - 如果使用大恒相机,请安装官方 SDK 并确认
daheng_camera.xml参数文件已根据实际型号配置。
cd ~/easy_handeye2_ws
colcon build
source install/setup.bash如只需编译单个包,可追加
--packages-select <package_name>。
rmos_cam提供工业相机或 USB 相机的采集组件,发布/image_raw图像。my_robot_driver/chessboard_detector在图像中检测棋盘格,并在 TF 中发布camera_color_optical_frame → chessboard变换。my_robot_driver/robot_tf_publisher从串口 IMU 读取末端姿态,发布robot_base_frame → robot_effector_frame变换。handeye_sampler.py监听两路 TF,人工输入save指令采集稳定姿态。handeye_solver读取采集结果,使用 OpenCV 提供的多种手眼标定算法求解effector → camera变换。
- 作用:从
/dev/ttyACM0读取 IMU 自定义协议帧,解析四元数并发布 TF。 - 主要特性:
- 支持 SOF/EOF 帧同步与缓存剔除;
- 内置欧拉角镜像+常量补偿(当前对 pitch/yaw 取反,并叠加 135° yaw 偏置及 180° roll 翻转);
- 10 Hz 定时发布
robot_base_frame → robot_effector_frame,平移默认为零。
- 默认串口参数:115200 波特率、超时 100 ms,自定义帧长 25 字节(详见结构体说明)。
- 运行:
ros2 run my_robot_driver robot_tf_publisher
- 常用参数调整:若设备路径或 SOF/EOF 标记不同,请编辑
my_robot_driver/robot_tf_publisher.py中的self.serial_port、SOF_MARKER、EOF_MARKER。 - 调试建议:
- 使用
scripts/imu_frame_inspector.py观测原始四元数、增量角度:ros2 run my_robot_driver robot_tf_publisher python3 src/my_robot_driver/scripts/imu_frame_inspector.py --port /dev/ttyACM0
- 若 TF 始终未更新,请检查串口权限 (
sudo usermod -a -G dialout $USER) 以及 IMU 是否持续输出。
- 使用
-
作用:在输入图像流中检测棋盘格角点,求解位姿后发布 TF、Pose 与调试图像。
-
话题:
- 订阅:
/image_raw(可通过参数修改),可选订阅CameraInfo; - 发布:
/chessboard/pose、/chessboard/debug_image、/tf。
- 订阅:
-
关键参数:
参数 默认值 说明 chessboard_width8 内角点列数 chessboard_height6 内角点行数 square_size0.025 棋盘格边长 (m) image_topic/image_raw输入图像话题 camera_info_yaml空 指向 camera_info.yaml直接加载内参use_camera_info_topicFalse若为 True,则等待 CameraInfo 话题 enable_clahe/median_blur_kernelTrue / 5 提升图像清晰度 use_findchessboard_sbTrue 常规检测失败时使用 findChessboardCornersSB兜底camera_frame/chessboard_framecamera_color_optical_frame/chessboardTF 帧名 -
运行示例:
ros2 run my_robot_driver chessboard_detector \ --ros-args \ -p image_topic:=/camera/color/image_raw \ -p camera_info_yaml:=/path/to/camera_info.yaml \ -p chessboard_width:=8 -p chessboard_height:=6 -p square_size:=0.03
ros2 run my_robot_driver chessboard_detector --ros-args -p camera_info_yaml:=/home/hejie/easy_handeye2_ws/src/my_robot_driver/config/camera_info.yaml
-
调试技巧:
- 使用
rqt_image_view /chessboard/debug_image检查角点质量; - 若提示 "PnP 求解失败",请确认相机内参是否加载正确;
- 出现
tf2::ExtrapolationException时,可强制使用节点时间戳,或检查上游图像时间是否回退。 - ros2 run rqt_image_view rqt_image_view /chessboard/debug_image
- 使用
- 定位:通过组件容器加载大恒或 USB 相机驱动,统一发布
image_raw。 - 启动文件:
ros2 launch rmos_cam cam.launch.py camera_type:=<usb|daheng>。 - 参数文件:
- 大恒相机参数从
rmos_bringup/config/daheng_node.yaml读取; - 额外的
config/daheng_camera.xml提供 SDK 级别的宽高、曝光、增益等默认设置。
- 大恒相机参数从
- 输出:
/daheng_node/image_raw或/usb_node/image_raw(可在 launch 中通过remappings适配)。
- 调试提示:
- 启动前确保
LD_LIBRARY_PATH已包含大恒 SDK; - 若容器未加载组件,可运行
ros2 component types/ros2 component list检查; - USB 摄像头需系统识别为 Video4Linux 设备,可使用
v4l2-ctl --list-devices排查。
- 启动前确保
-
入口:在工作区根目录执行
python3 src/handeye_sampler.py(脚本内部自启 ROS2 节点)。 -
依赖帧:
- 机器人姿态:
base_frame→effector_frame(默认robot_base→robot_effector,可通过参数覆盖); - 目标姿态:
camera_frame→target_frame(默认camera_color_optical_frame→chessboard)。
- 机器人姿态:
-
采样逻辑:
- 节点以
poll_rate(默认 30 Hz)轮询 TF,并比较平移/旋转变化是否低于阈值; - 连续满足
consecutive_required次后提示 "Transforms stable"; - 终端输入
save手动保存当前姿态对,写入output_file(JSON); - 若姿态与前一次过于接近,会拒绝保存以避免冗余。
- 节点以
-
常用参数:
参数 默认值 说明 translation_threshold0.0008 m 判断稳定的平移阈值 rotation_threshold_deg0.15° 判断稳定的旋转阈值 min_sample_interval1.0 s 两次满足条件间隔 max_samples30 达到后自动退出 output_filehandeye_samples.json结果保存路径 appendTrue是否在已有文件末尾追加 -
建议流程:
- 启动后等待终端出现 “Transforms stable” 提示,再输入
save; - 从不同方位/距离采集 ≥10 组数据以提高解算稳定性;
- 采集完成后按
Ctrl+C或输入quit/exit结束节点。
- 启动后等待终端出现 “Transforms stable” 提示,再输入
-
入口:
python3 handeye_solver.py --input handeye_samples.json --method park --save-yaml effector_to_camera.json。 -
算法选择:支持
tsai(默认)、park、horaud、andreff,底层调用cv2.calibrateHandEye。 -
输出:
- 终端打印平移/四元数;
- 若提供
--save-yaml,会导出可供 TF 静态发布的 JSON/YAML 数据。
-
常见问题:
- 少于 3 组样本将报错;
- 姿态差异过小时结果不稳定,需采集更多不同姿态。
-
可选可视化:
python3 handeye_samples_viz.py --input handeye_samples.json可查看采样分布。
- 启动相机:
ros2 run rmos_cam daheng_camera。 - 启动棋盘格检测:
ros2 run my_robot_driver chessboard_detector --ros-args ...,确认/chessboard/debug_image正常。 - 启动 IMU TF 发布:
ros2 run my_robot_driver robot_tf_publisher,使用ros2 run tf2_ros tf2_echo robot_base_frame robot_effector_frame验证输出。 - 采集姿态样本:
python3 src/handeye_sampler.py,在终端根据提示输入save。 - 求解标定:
python3 handeye_solver.py --method park --save-yaml effector_to_camera.json。 - 应用结果:将求得的平移/四元数加入机器人 TF 树,或通过
static_transform_publisher发布。
- 串口读不到数据:检查串口权限、波特率、线缆连接;若缓冲区爆满,可降低定时器频率或在固件端减少广播频率。
- 棋盘格检测抖动:调整
translation_threshold/rotation_threshold_deg使采样更严格,或在图像预处理参数中增大 CLAHE 的clip_limit。 - TF 始终不更新:使用
ros2 run tf2_ros tf2_monitor查看 TF 更新周期;如时间戳倒退,请确保所有节点使用同一时间基准。 - OpenCV 缺失:
ImportError: cv2时请pip3 install opencv-python或安装系统包sudo apt install python3-opencv。
my_robot_driver/scripts/imu_frame_inspector.py:串口原始数据调试助手。handeye_samples_viz.py:用于评估采样姿态覆盖范围。
欢迎根据实际项目补充示例配置、相机标定文件及许可证信息。若在使用中遇到新的问题,也建议把解决经验追加到本 README 中,便于后续协作。