联合标定三维雷达和IMU,第一步要先对齐两种传感信息的时间戳。
ros官网提供了message_filters用于对齐多种传感信息的时间戳。
http://wiki.ros.org/message_filters#Time_Synchronizer
注意,对齐传感信息时间戳有两种方式,一种是时间戳完全对齐 ExactTime Policy ,另一种是时间戳相近
ApproximateTime Policy ,前者更为严格。
msg_syn.h
#ifndef CLIMBING_ROBOT_GT_MAP_ #define CLIMBING_ROBOT_GT_MAP_ #include <string> #include <ros/ros.h> #include <rosbag/bag.h> #include <sensor_msgs/PointCloud2.h> #include <geometry_msgs/PoseStamped.h> #include <message_filters/subscriber.h> #include <message_filters/synchronizer.h> #include <message_filters/sync_policies/approximate_time.h> namespace climbing_robot { class MsgSynchronizer{ public: MsgSynchronizer(ros::NodeHandle node); ~MsgSynchronizer(){}; void callback(const sensor_msgs::PointCloud2::ConstPtr& ori_pointcloud, const geometry_msgs::PoseStamped::ConstPtr& ori_pose); inline void CloseBag() { msg_syn_bag.close(); } private: // ros::Publisher pubVelodyne; // ros::Publisher pubImu; std::string syn_bag_path; rosbag::Bag msg_syn_bag; }; }//namespace climbing_robot #endif// CLIMBING_ROBOT_GT_MAP_
msg_syn.cpp
#include "msg_syn.h" #include <iostream> namespace climbing_robot { MsgSynchronizer::MsgSynchronizer(ros::NodeHandle node) { // pubVelodyne = nh.advertise<sensor_msgs::PointCloud2>("/Syn/imu/data", 1); message_filters::Subscriber<geometry_msgs::PoseStamped> pose_sub(node, "/vrpn_client_node/RigidBody/pose", 1); message_filters::Subscriber<sensor_msgs::PointCloud2> velodyne_sub(node, "/velodyne_points", 1); typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, geometry_msgs::PoseStamped> approximate_policy; message_filters::Synchronizer<approximate_policy> sync(approximate_policy(10), velodyne_sub, pose_sub); sync.registerCallback(boost::bind(&MsgSynchronizer::callback, this, _1, _2)); node.getParam("msg_syn_bag_path", syn_bag_path); msg_syn_bag.open(syn_bag_path, rosbag::bagmode::Write); ros::spin(); } void MsgSynchronizer::callback(const sensor_msgs::PointCloud2::ConstPtr& ori_pointcloud, const geometry_msgs::PoseStamped::ConstPtr& ori_pose) { ROS_INFO("pointcloud stamp value is: %f", ori_pointcloud->header.stamp.toSec()); ROS_INFO("pose stamp value is: %f", ori_pose->header.stamp.toSec()); // ros::Time timestamp = ori_pointcloud.header.stamp; msg_syn_bag.write("/velodyne_points", ori_pointcloud->header.stamp, *ori_pointcloud); msg_syn_bag.write("/vrpn_client_node/RigidBody/pose", ori_pointcloud->header.stamp, *ori_pose); // pubVelodyne.publish(syn_pointcloud); } }//namespace climbing_robot
main.cpp
#include "msg_syn.h" int main(int argc, char** argv) { ros::init(argc, argv, "msg_synchronizer"); ros::NodeHandle node("~"); ROS_INFO("\033[1;32m---->\033[0m Sync msgs node Started."); climbing_robot::MsgSynchronizer synchronizer(node); // ros::spin(); synchronizer.CloseBag(); return 0; }
非常注意2点:
A
sync.registerCallback(boost::bind(&mySynchronizer::callback, this, _1, _2));
由于callback函数是类内函数,所以要使用类内成员函数的写法;
加上this关键字;
参考:https://blog.csdn.net/Felaim/article/details/78212738#commentBox
B
ros::spin(); 要放在订阅函数之后。如果放在主函数中,由于作用域的原因,会出现无法订阅/topic的错误。
参考:https://www.cnblogs.com/liu-fa/p/5925381.html