|
| 1 | +#include "infinite_sense.h" |
| 2 | +#include "mv_cam.h" |
| 3 | + |
| 4 | +#include <ros/ros.h> |
| 5 | +#include <cv_bridge/cv_bridge.h> |
| 6 | +#include <image_transport/image_transport.h> |
| 7 | +#include <sensor_msgs/Imu.h> |
| 8 | + |
| 9 | + |
| 10 | +struct cam_config { |
| 11 | + bool onboard_imu = true;// 使用内部IMU |
| 12 | + bool extern_imu = false;// 使用外部IMU,TODO |
| 13 | + std::string imu_name = "onboard_imu"; |
| 14 | + |
| 15 | + // 相机名称 + 设备ID |
| 16 | + std::pair<std::string, int> CAM1 = {"cam_1", 1}; |
| 17 | + std::pair<std::string, int> CAM2 = {"cam_2", -1}; |
| 18 | + std::pair<std::string, int> CAM3 = {"cam_3", -1}; |
| 19 | + std::pair<std::string, int> CAM4 = {"cam_4", -1}; // -1 代表没有 |
| 20 | + |
| 21 | + // 通信方式 |
| 22 | + int type = 0; // 0 --> 串口通信 1 --> 网口通信 |
| 23 | + std::string uart_dev = "/dev/ttyACM0"; |
| 24 | + std::string net_ip = "192.168.1.188"; |
| 25 | + int net_port = 8888; |
| 26 | +}; |
| 27 | +cam_config cfg; |
| 28 | + |
| 29 | +using namespace infinite_sense; |
| 30 | +inline ros::Time CreateRosTimestamp(const uint64_t mico_sec) { |
| 31 | + uint32_t nsec_per_second = 1e9; |
| 32 | + auto u64 = mico_sec * 1000; |
| 33 | + uint32_t sec = u64 / nsec_per_second; |
| 34 | + uint32_t nsec = u64 - (sec * nsec_per_second); |
| 35 | + return {sec, nsec}; |
| 36 | +} |
| 37 | + |
| 38 | +class CamDriver { |
| 39 | + public: |
| 40 | + CamDriver(ros::NodeHandle &nh) : node_(nh), it_(node_), camera_name_("cam_1"), imu_name_("imu_1") {} |
| 41 | + void ImuCallback(const void *msg, size_t) { |
| 42 | + const auto *imu_data = static_cast<const ImuData *>(msg); |
| 43 | + sensor_msgs::Imu imu_msg_data; |
| 44 | + imu_msg_data.header.frame_id = "map"; |
| 45 | + imu_msg_data.header.stamp = CreateRosTimestamp(imu_data->time_stamp_us); |
| 46 | + |
| 47 | + imu_msg_data.angular_velocity.x = imu_data->g[0]; |
| 48 | + imu_msg_data.angular_velocity.y = imu_data->g[1]; |
| 49 | + imu_msg_data.angular_velocity.z = imu_data->g[2]; |
| 50 | + |
| 51 | + imu_msg_data.linear_acceleration.x = imu_data->a[0]; |
| 52 | + imu_msg_data.linear_acceleration.y = imu_data->a[1]; |
| 53 | + imu_msg_data.linear_acceleration.z = imu_data->a[2]; |
| 54 | + |
| 55 | + imu_msg_data.orientation.w = imu_data->q[0]; |
| 56 | + imu_msg_data.orientation.x = imu_data->q[1]; |
| 57 | + imu_msg_data.orientation.y = imu_data->q[2]; |
| 58 | + imu_msg_data.orientation.z = imu_data->q[3]; |
| 59 | + imu_pub_.publish(imu_msg_data); |
| 60 | + } |
| 61 | + |
| 62 | + // 自定义回调函数 |
| 63 | + void ImageCallback(const void *msg, size_t) { |
| 64 | + const auto *cam_data = static_cast<const CamData *>(msg); |
| 65 | + const cv::Mat image_mat(cam_data->image.rows, cam_data->image.cols, CV_8UC1, cam_data->image.data); |
| 66 | + sensor_msgs::ImagePtr image_msg = |
| 67 | + // mono8:灰度类型,bgr8:彩图,具体需要根据相机类型进行修改 |
| 68 | + cv_bridge::CvImage(std_msgs::Header(), "mono8", image_mat).toImageMsg(); |
| 69 | + image_msg->header.stamp = CreateRosTimestamp(cam_data->time_stamp_us); |
| 70 | + image_pubs_[cam_data->name].publish(image_msg); |
| 71 | + } |
| 72 | + void Init() { |
| 73 | + if (cfg.type == 0) { |
| 74 | + synchronizer_.SetUsbLink(cfg.uart_dev, 921600); |
| 75 | + } else if (cfg.type == 1) { |
| 76 | + synchronizer_.SetNetLink(cfg.net_ip, cfg.net_port); |
| 77 | + } |
| 78 | + |
| 79 | + mv_cam_ = std::make_shared<MvCam>(); |
| 80 | + synchronizer_.UseSensor(mv_cam_); |
| 81 | + |
| 82 | + if (cfg.onboard_imu) { |
| 83 | + imu_pub_ = node_.advertise<sensor_msgs::Imu>(cfg.imu_name, 1000); |
| 84 | + } |
| 85 | + |
| 86 | + if (cfg.CAM1.second >= 0) mv_cam_->SetParams({{cfg.CAM1.first, CAM_1}}); |
| 87 | + if (cfg.CAM2.second >= 0) mv_cam_->SetParams({{cfg.CAM2.first, CAM_2}}); |
| 88 | + if (cfg.CAM3.second >= 0) mv_cam_->SetParams({{cfg.CAM3.first, CAM_3}}); |
| 89 | + if (cfg.CAM4.second >= 0) mv_cam_->SetParams({{cfg.CAM4.first, CAM_4}}); |
| 90 | + |
| 91 | + |
| 92 | + if (cfg.CAM1.second >= 0) image_pubs_[cfg.CAM1.first] = it_.advertise(cfg.CAM1.first, 30); |
| 93 | + if (cfg.CAM2.second >= 0) image_pubs_[cfg.CAM2.first] = it_.advertise(cfg.CAM2.first, 30); |
| 94 | + if (cfg.CAM3.second >= 0) image_pubs_[cfg.CAM3.first] = it_.advertise(cfg.CAM3.first, 30); |
| 95 | + if (cfg.CAM4.second >= 0) image_pubs_[cfg.CAM4.first] = it_.advertise(cfg.CAM4.first, 30); |
| 96 | + |
| 97 | + synchronizer_.Start(); |
| 98 | + std::this_thread::sleep_for(std::chrono::milliseconds(5000)); |
| 99 | + |
| 100 | + if (cfg.onboard_imu) { |
| 101 | + Messenger::GetInstance().SubStruct( |
| 102 | + cfg.imu_name, std::bind(&CamDriver::ImuCallback, this, std::placeholders::_1, std::placeholders::_2)); |
| 103 | + } |
| 104 | + |
| 105 | + if (cfg.CAM1.second >= 0) Messenger::GetInstance().SubStruct(cfg.CAM1.first, std::bind(&CamDriver::ImageCallback, this, std::placeholders::_1, std::placeholders::_2)); |
| 106 | + if (cfg.CAM2.second >= 0) Messenger::GetInstance().SubStruct(cfg.CAM2.first, std::bind(&CamDriver::ImageCallback, this, std::placeholders::_1, std::placeholders::_2)); |
| 107 | + if (cfg.CAM3.second >= 0) Messenger::GetInstance().SubStruct(cfg.CAM3.first, std::bind(&CamDriver::ImageCallback, this, std::placeholders::_1, std::placeholders::_2)); |
| 108 | + if (cfg.CAM4.second >= 0) Messenger::GetInstance().SubStruct(cfg.CAM4.first, std::bind(&CamDriver::ImageCallback, this, std::placeholders::_1, std::placeholders::_2)); |
| 109 | + } |
| 110 | + |
| 111 | + void Run() { |
| 112 | + ros::Rate loop_rate(1000); |
| 113 | + while (ros::ok()) { |
| 114 | + ros::spinOnce(); |
| 115 | + loop_rate.sleep(); |
| 116 | + } |
| 117 | + synchronizer_.Stop(); |
| 118 | + } |
| 119 | + |
| 120 | + private: |
| 121 | + ros::NodeHandle &node_; |
| 122 | + ros::Publisher imu_pub_; |
| 123 | + image_transport::ImageTransport it_; |
| 124 | + std::unordered_map<std::string, image_transport::Publisher> image_pubs_; |
| 125 | + std::shared_ptr<MvCam> mv_cam_; |
| 126 | + Synchronizer synchronizer_; |
| 127 | + std::string camera_name_; |
| 128 | + std::string imu_name_; |
| 129 | +}; |
| 130 | + |
| 131 | +int main(int argc, char **argv) { |
| 132 | + ros::init(argc, argv, "ros_demo", ros::init_options::NoSigintHandler); |
| 133 | + ros::NodeHandle node; |
| 134 | + CamDriver demo_node(node); |
| 135 | + demo_node.Init(); |
| 136 | + demo_node.Run(); |
| 137 | + |
| 138 | + return 0; |
| 139 | +} |
0 commit comments