0. 前言

对于很多传感器,网上基于 ROS1 的功能包比较多,对于 ROS2 的适配目前很少,但 ROS2 在稳定性、实时性方面具有更大的优势,可以投入实际的工业应用中。

这篇播客介绍了海康相机的 ROS2 功能包,是我在 ROS1 功能包 的基础上进行修改,最后在 Ubuntu20.04 ROS2 Foxy 下测试通过,大家可以直接克隆下来使用。

仓库链接:SEUZTh/hk_camera: Hikvision Camera ROS2 package (github.com)

1. 安装官方 MVS 客户端

  • 根据自己使用的计算机平台,选择对应的 tar.gz 软件包:

  • 解压并执行安装:
# 随便一个地方解压缩
sudo ./setup.sh # 将会安装在 /opt/MVS/ 下
  • /etc/ld.so.conf.d 文件中新建文件mvs.conf
sudo vi mvs.conf
  • 文件中添加如下内容(根据自己电脑的平台选择,我这里是 x64 ,所以选择这个):
/opt/vc/lib
/opt/MVS/lib/64
  • 在终端执行:
sudo ldconfig
  • 重启电脑以生效。

2. 海康相机 ROS2 功能包

  • 创建工作空间:
mkdir -p ~/ws_hk_camera/src
cd ~/ws_hikrobot_camera/src
  • 克隆功能包:
git clone https://github.com/SEUZTh/hk_camera.git
  • 编译执行:
colcon build
source install/setup.sh
ros2 run hk_camera hk_camera
ros2 run rviz2 rviz2
  • 效果如下:

3. 解析

这里记录一下我是如何将 ROS1 功能包修改为 ROS2 功能包的。

  • 查看 ROS1 功能包中依赖的包,在 ROS2 工作空间下创建对应的功能包:
ros2 pkg create hk_camera --build-type ament_cmake --dependencies rclcpp std_msgs cv_bridge image_transport
  • 如果不确定在 ROS2 中对应于 ROS1 的依赖是什么,可以使用命令进行查看:
rospack list
ros2 pkg list # ROS2
  • 下面是一个将 ROS1 依赖包映射到 ROS2 依赖包的简单对应表格:
ROS 1依赖包 ROS 2对应依赖包
actionlib action_msgs
actionlib_msgs action_msgs
actionlib_tutorials action_tutorials_interfaces
angles angles
bond -
bondcpp -
bondpy -
camera_calibration camera_calibration
camera_calibration_parsers camera_calibration_parsers
camera_info_manager camera_info_manager
catkin ament_cmake
class_loader class_loader
cmake_modules cmake_modules
compressed_depth_image_transport compressed_depth_image_transport
compressed_image_transport compressed_image_transport
control_msgs control_msgs
control_toolbox -
controller_interface -
controller_manager -
controller_manager_msgs -
cpp_common cpp_common
cv_bridge cv_bridge
depth_image_proc -
diagnostic_aggregator -
diagnostic_analysis -
diagnostic_common_diagnostics diagnostic_msgs
diagnostic_msgs diagnostic_msgs
diagnostic_updater diagnostic_updater
diff_drive_controller -
dynamic_reconfigure rclcpp
eigen_conversions tf2_eigen
filters -
forward_command_controller -
gazebo_dev -
gazebo_msgs -
gazebo_plugins -
gazebo_ros -
gazebo_ros_control -
gencpp -
geneus -
genlisp -
genmsg -
gennodejs -
genpy -
geographic_msgs geographic_msgs
geometry_msgs geometry_msgs
gl_dependency -
hardware_interface -
image_geometry image_geometry
image_proc -
image_publisher -
image_rotate -
image_transport image_transport
image_view -
interactive_marker_tutorials -
interactive_markers interactive_markers
joint_limits_interface -
joint_state_controller -
joint_state_publisher -
joint_state_publisher_gui -
joy joy
kdl_conversions tf2_kdl
kdl_parser kdl_parser
laser_assembler -
laser_filters -
laser_geometry laser_geometry
librviz_tutorial -
map_msgs map_msgs
media_export -
message_filters message_filters
message_generation message_generation
message_runtime message_runtime
mk -
nav_msgs nav_msgs
nodelet -
nodelet_topic_tools -
nodelet_tutorial_math -
pcl_conversions pcl_conversions
pcl_msgs pcl_msgs
pcl_ros -
pluginlib pluginlib
pluginlib_tutorials -
polled_camera -
position_controllers -
python_qt_binding python_qt_binding
qt_dotgraph qt_dotgraph
qt_gui qt_gui
qt_gui_cpp qt_gui_cpp
qt_gui_py_common qt_gui_py_common
qwt_dependency -
realtime_tools realtime_tools
resource_retriever resource_retriever
robot_state_publisher robot_state_publisher
ros_environment ros_environment
rosbag rosbag2
rosbag_migration_rule -
rosbag_storage rosbag2_storage
rosbash -
rosboost_cfg -
rosbuild -
rosclean -
rosconsole rclcpp_logging
rosconsole_bridge ros_bridge
roscpp rclcpp
roscpp_serialization rclcpp_serialization
roscpp_traits rclcpp_traits
roscpp_tutorials rclcpp_tutorials
roscreate -
rosgraph rosgraph
rosgraph_msgs rosgraph_msgs
roslang -
roslaunch launch
roslib -
roslint -
roslisp -
roslz4 -
rosmake -
rosmaster ros2service
rosmsg -
rosnode ros2node
rosout rcl_logging_spdlog
rospack ros2pkg
rosparam ros2param
rospy rclpy
rospy_tutorials rclpy_tutorials
rosservice ros2service
rostest launch_testing
rostime rclcpp
rostopic ros2topic
rosunit launch_testing
roswtf ros2doctor
rqt_action rqt_action
rqt_bag ros2bag
rqt_bag_plugins -
rqt_console rqt_console
rqt_dep -
rqt_graph rqt_graph
rqt_gui qt_gui
rqt_gui_cpp qt_gui_cpp
rqt_gui_py qt_gui_py
rqt_image_view rqt_image_view
rqt_launch launch
rqt_logger_level rqt_logger_level
rqt_moveit -
rqt_msg -
rqt_nav_view -
rqt_plot rqt_plot
rqt_pose_view -
rqt_publisher rqt_publisher
rqt_py_common rqt_py_common
rqt_py_console rqt_py_console
rqt_reconfigure rqt_reconfigure
rqt_robot_dashboard -
rqt_robot_monitor -
rqt_robot_steering -
rqt_runtime_monitor -
rqt_rviz -
rqt_service_caller -
rqt_shell rqt_shell
rqt_srv -
rqt_tf_tree -
rqt_top -
rqt_topic rqt_topic
rqt_web -
rviz rviz2
rviz_plugin_tutorials -
rviz_python_tutorial -
self_test -
sensor_msgs sensor_msgs
shape_msgs shape_msgs
smach -
smach_msgs -
smach_ros -
smclib -
stage -
stage_ros -
std_msgs std_msgs
std_srvs std_srvs
stereo_image_proc -
stereo_msgs stereo_msgs
tf tf2
tf2 tf2
tf2_eigen tf2_eigen
tf2_geometry_msgs tf2_geometry_msgs
tf2_kdl tf2_kdl
tf2_msgs tf2_msgs
tf2_py tf2_py
tf2_ros tf2_ros
tf_conversions tf2
theora_image_transport -
topic_tools topic_tools
trajectory_msgs trajectory_msgs
transmission_interface -
turtle_actionlib ros2action
turtle_tf turtle_tf
turtle_tf2 turtle_tf2
turtlesim turtlesim
urdf urdfdom
urdf_parser_plugin urdfdom_py
urdf_sim_tutorial -
urdf_tutorial urdfdom_tutorial
uuid_msgs unique_identifier_msgs
velodyne_driver -
velodyne_laserscan -
velodyne_msgs -
velodyne_pointcloud -
visualization_marker_tutorials -
visualization_msgs visualization_msgs
webkit_dependency -
xacro xacro
xmlrpcpp -

需要注意的是,上面只是给出了一种简单的对应,某些 ROS1 依赖包可能没有直接对应的 ROS2 依赖包,或者对应的包名称可能不完全相同。此外,对于某些特定功能或工具,ROS2 可能使用了不同的包结构或更改了依赖关系。因此,在迁移 ROS1 代码到 ROS2 时,可能需要进行进一步的调整和修改。

  • 然后就是修改 CMakeLists.txt ,编写 src/hk_camera/include/hk_camera.hppsrc/hk_camera/src/hk_camera.cpp ,其中的一些函数和消息类型需要从 ROS1 映射到 ROS2 中,下面是一些需要注意的点。

  • ROS1 中 cv_bridge::CvImagePtrboost::make_shared ,这种类型显然比 std::make_shared 更高效,但 ROS2 中没有使用这种更高效的数据结构, 这两个变量类型在 ROS 头文件中可以查看,算是一个小细节。

cv_bridge::CvImagePtr cv_ptr = boost::make_shared<cv_bridge::CvImage>(); // ROS1
cv_bridge::CvImagePtr cv_ptr = std::make_shared<cv_bridge::CvImage>(); // ROS2
  • ROS1 中发布相机消息,会产生多个话题,包括压缩图像的话题等等,但 ROS2 为了更高效,并不会自动产生这些话题,只能在代码中指定发布哪些相机话题:
xxx@xxx:~$ ros2 topic list
/clicked_point
/goal_pose
/hk_camera/rgb/camera_info
/hk_camera/rgb/compressed
/initialpose
/parameter_events
/rosout
/tf
/tf_static
xxx@xxx:~/ws_hikrobot_camera$ rostopic list 
/hikrobot_camera/camera_info
/hikrobot_camera/rgb
/hikrobot_camera/rgb/compressed
/hikrobot_camera/rgb/compressed/parameter_descriptions
/hikrobot_camera/rgb/compressed/parameter_updates
/hikrobot_camera/rgb/compressedDepth
/hikrobot_camera/rgb/compressedDepth/parameter_descriptions
/hikrobot_camera/rgb/compressedDepth/parameter_updates
/hikrobot_camera/rgb/theora
/hikrobot_camera/rgb/theora/parameter_descriptions
/hikrobot_camera/rgb/theora/parameter_updates
/rosout
/rosout_agg