编译
脚本
v3_gaosi_img_pose_flag.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #!/bin/bash #外部给与执行权限 #sudo chmod +x run_ros_nodes.sh # 定义 ROS 安装路径 #安装时候添加到系统路径了 不需要每次都source ROS_SETUP = "/opt/ros/noetic/setup.bash" # 定义工作目录路径 自己的工程没有加到系统路径,每次需要source WORKSPACE_DIR = "/home/r9000k/v2_project/gaosi_slam/ros/ros_cgg" conda_envs = "/home/r9000k/anaconda3" # 修改2-1 自己的conda 安装路径 #ROS_cv_briage_dir="/home/r9000k/v1_software/opencv/catkin_ws_cv_bridge/devel/setup.bash" # 修改2-2 自己编译的cv_briage包节点,貌似不用也行 制定了依赖opencv3.4.9 而非自带4.2 #echo $ROS_cv_briage_dir conda_envs_int = $conda_envs "/etc/profile.d/conda.sh" # 不用改 conda自带初始化文件 echo $conda_envs_int conda_envs_bin = $conda_envs "/envs/gaussian_splatting/bin" # 不用改 conda自带python安装位置 脚本中需要指定是conda特定的环境python而不是系统默认的 echo $conda_envs_bin ROS_SETUP = "/opt/ros/noetic/setup.bash" #不用改 安装时候添加到系统路径了 不需要每次都source 这里留着 #指定目录 # 启动 ROS Master echo "Starting ROS 总结点..." gnome - terminal - - bash - c "\ cd $WORKSPACE_DIR; source devel / setup.bash; \ roscore; \ exec bash" # 等待 ROS Master 启动 sleep 3 # 运行 C++ 发布节点 # echo "Running C++ 发布节点..." # gnome-terminal -- bash -c "\ # cd $WORKSPACE_DIR; source devel/setup.bash; \ # rosrun gaosi_img_pose_flag image_pose_flag_publisher; \ # exec bash" # echo "Running C++ 订阅节点..." # gnome-terminal -- bash -c "\ # cd $WORKSPACE_DIR; source devel/setup.bash; \ # rosrun gaosi_img_pose_flag image_pose_flag_subscriber; \ # exec bash" # 运行python节点 python_DIR = "${WORKSPACE_DIR}/src/gaosi_img_pose_flag/src" echo "Running python image_pose_publisher发布节点..." gnome - terminal - - bash - c " \ cd $WORKSPACE_DIR; source devel / setup.bash; \ source $conda_envs_int; \ conda activate gaussian_splatting ; \ cd $python_DIR; \ / usr / bin / python3 image_pose_publisher.py; \ exec bash" # 运行python节点 echo "Running python image_pose_subscriber订阅节点..." gnome - terminal - - bash - c " \ cd $WORKSPACE_DIR; source devel / setup.bash; \ source $conda_envs_int; \ conda activate gaussian_splatting ; \ cd $python_DIR; \ / usr / bin / python3 image_pose_subscriber.py; \ exec bash" |
包
1 创建自定义消息
1 | ImagePose.msg |
1 2 3 4 | # ImagePose.msg sensor_msgs/Image image std_msgs/Float64 flag geometry_msgs/Pose pose |
1 | CMakeLists.txt |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | cmake_minimum_required(VERSION 3.0.2) project(gaosi_img_pose_flag) find_package(catkin REQUIRED COMPONENTS roscpp geometry_msgs sensor_msgs cv_bridge message_filters # 消息同步 image_transport std_msgs # 自定义消息 message_generation # 自定义消息 ) # 自定义消息 add_message_files( FILES ImagePose.msg ) # 自定义消息 generate_messages( DEPENDENCIES std_msgs sensor_msgs geometry_msgs ) find_package(OpenCV REQUIRED) find_package(Boost REQUIRED COMPONENTS filesystem) find_package(Eigen3 REQUIRED) catkin_package( CATKIN_DEPENDS roscpp geometry_msgs sensor_msgs cv_bridge std_msgs message_runtime DEPENDS Boost ) include_directories( ${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} "/usr/local/include/eigen3" ) # 编译发布节点 add_executable(image_pose_flag_publisher src/image_pose_flag_publisher.cpp) # 自定义消息引用 add_dependencies(image_pose_flag_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(image_pose_flag_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} ) add_executable(image_pose_flag_subscriber src/image_pose_flag_subscriber.cpp) add_dependencies(image_pose_flag_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(image_pose_flag_subscriber ${catkin_LIBRARIES} ${OpenCV_LIBRARIES}) |
package.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?xml version= "1.0" ?> <package format= "2" > <name>gaosi_img_pose_flag</name> <version>0.0.1</version> <description> A package to publish and subscribe to images and GPS data using ROS. </description> <!-- Maintainer of the package --> <maintainer email= "your_email@example.com" >Your Name</maintainer> <!-- License of the package --> <license>MIT</license> <!-- Build tool required to build this package --> <buildtool_depend>catkin</buildtool_depend> <!-- Dependencies of the package during build and runtime --> <build_depend>roscpp</build_depend> <build_depend>sensor_msgs</build_depend> <build_depend>cv_bridge</build_depend> <build_depend>eigen</build_depend> <build_depend>geometry_msgs</build_depend> <build_depend>message_filters</build_depend> <build_depend>image_transport</build_depend> <!--自定义消息 --> <build_depend>message_generation</build_depend> <build_depend>message_runtime</build_depend> <build_depend>std_msgs</build_depend> <exec_depend>roscpp</exec_depend> <exec_depend>sensor_msgs</exec_depend> <exec_depend>cv_bridge</exec_depend> <exec_depend>eigen</exec_depend> <exec_depend>geometry_msgs</exec_depend> <exec_depend>message_filters</exec_depend> <exec_depend>image_transport</exec_depend> <!--自定义消息 --> <exec_depend>message_generation</exec_depend> <exec_depend>message_runtime</exec_depend> <exec_depend>std_msgs</exec_depend> <!-- Declare additional dependencies required for building this package --> <build_export_depend>roscpp</build_export_depend> <build_export_depend>sensor_msgs</build_export_depend> <build_export_depend>cv_bridge</build_export_depend> <build_export_depend>eigen</build_export_depend> <build_export_depend>geometry_msgs</build_export_depend> <build_export_depend>message_filters</build_export_depend> <build_export_depend>image_transport</build_export_depend> <!--自定义消息 --> <build_export_depend>message_generation</build_export_depend> <build_export_depend>message_runtime</build_export_depend> <build_export_depend>std_msgs</build_export_depend> <!-- Export information, can be used by other packages --> <export> <!-- Export any specific information here --> </export> </package> |
image_pose_publisher.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #!/usr/bin/env python import rospy from sensor_msgs.msg import Image from std_msgs.msg import Float64 from geometry_msgs.msg import Pose from gaosi_img_pose_flag.msg import ImagePose # 更换为你包的名字 from cv_bridge import CvBridge import numpy as np import cv2 class ImagePosePublisher: def __init__( self ): # Initialize node rospy.init_node( 'image_pose_publisher' , anonymous = True ) # Initialize publishers self .pub = rospy.Publisher( 'image_pose_topic' , ImagePose, queue_size = 10 ) # Create a bridge between OpenCV and ROS self .bridge = CvBridge() # Create or load a sample image self .image = np.zeros(( 480 , 640 , 3 ), dtype = np.uint8) # Black image # Set flag self .flag = Float64() self .flag.data = 1.23 # Example double value # Set pose self .pose = Pose() self .pose.position.x = 1.0 self .pose.position.y = 2.0 self .pose.position.z = 3.0 self .pose.orientation.x = 0.0 self .pose.orientation.y = 0.0 self .pose.orientation.z = 0.0 self .pose.orientation.w = 1.0 # Set publish rate self .rate = rospy.Rate( 10 ) # 10 Hz self .publish() def publish( self ): while not rospy.is_shutdown(): msg = ImagePose() # Convert OpenCV image to ROS image message msg.image = self .bridge.cv2_to_imgmsg( self .image, encoding = "bgr8" ) msg.flag = self .flag msg.pose = self .pose # Publish message self .pub.publish(msg) self .rate.sleep() if __name__ = = '__main__' : try : ImagePosePublisher() except rospy.ROSInterruptException: pass |
image_pose_subscriber.py
image_pose_subscriber.py 例子0 工程多线程加速版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <ros/ros.h> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 #include <queue> #include <mutex> #include <thread> #include <iostream> / / Global variables std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> data_queue; std::mutex queue_mutex; / / Callback function to handle incoming messages void callback(const gaosi_img_pose_flag::ImagePose::ConstPtr& msg) { std::lock_guard<std::mutex> lock(queue_mutex); data_queue.push(msg); } / / Thread function to process the queue void processQueue() { while (ros::ok()) { std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> local_queue; { std::lock_guard<std::mutex> lock(queue_mutex); std::swap(local_queue, data_queue); / / Safely access the queue } while (!local_queue.empty()) { auto msg = local_queue.front(); local_queue.pop(); / / Process the message ROS_INFO( "Processing flag: %.2f" , msg - >flag.data); ROS_INFO( "Processing pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg - >pose.position.x, msg - >pose.position.y, msg - >pose.position.z, msg - >pose.orientation.x, msg - >pose.orientation.y, msg - >pose.orientation.z, msg - >pose.orientation.w); } / / Optional: Sleep to avoid busy waiting std::this_thread::sleep_for(std::chrono::milliseconds( 100 )); } } void spinThread() { ros::spin(); / / 处理回调函数积累消息 } int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_processor" ); ros::NodeHandle nh; / / Initialize the subscriber ros::Subscriber sub = nh.subscribe( "image_pose_topic" , 10 , callback); / / Create a thread to process the queue std::thread processing_thread(processQueue); / / Start a thread to run ros::spin() std::thread spin_thread(spinThread); ros::Rate rate( 1 ); / / Hz 频率 while (ros::ok()) { / / Call ros::spinOnce() to process callbacks ros::spinOnce(); / / Process the queue / / processQueue(); / / Sleep for the rest of the loop period rate.sleep(); } / / ros::spin(); / / Join the processing thread before exiting if (processing_thread.joinable()) { processing_thread.join(); } / / Join the spin thread before exiting if (spin_thread.joinable()) { spin_thread.join(); } return 0 ; } |
image_pose_subscriber.py 例子1 简单版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #!/usr/bin/env python import rospy from sensor_msgs.msg import Image from std_msgs.msg import Float64 from geometry_msgs.msg import Pose from gaosi_img_pose_flag.msg import ImagePose # 更换为你包的名字 from cv_bridge import CvBridge import cv2 class ImagePoseSubscriber: def __init__( self ): # Initialize node rospy.init_node( 'image_pose_subscriber' , anonymous = True ) # Initialize subscriber self .sub = rospy.Subscriber( 'image_pose_topic' , ImagePose, self .callback) # Create a bridge between OpenCV and ROS self .bridge = CvBridge() # Create an OpenCV window cv2.namedWindow( "Received Image" ) def callback( self , msg): try : # Convert ROS image message to OpenCV image cv_image = self .bridge.imgmsg_to_cv2(msg.image, desired_encoding = "bgr8" ) cv2.imshow( "Received Image" , cv_image) cv2.waitKey( 30 ) except Exception as e: rospy.logerr( "Failed to convert image: %s" , str (e)) rospy.loginfo( "Received flag: %.2f" , msg.flag.data) rospy.loginfo( "Received pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg.pose.position.x, msg.pose.position.y, msg.pose.position.z, msg.pose.orientation.x, msg.pose.orientation.y, msg.pose.orientation.z, msg.pose.orientation.w) def run( self ): rospy.spin() if __name__ = = '__main__' : try : subscriber = ImagePoseSubscriber() subscriber.run() except rospy.ROSInterruptException: pass |
image_pose_subscriber.py 例子2 类内部单独线程处理版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <std_msgs/Float64.h> #include <geometry_msgs/Pose.h> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 #include <queue> #include <mutex> #include <thread> class ImagePoseSubscriber { public: ImagePoseSubscriber() { / / Initialize subscriber sub_ = nh_.subscribe( "image_pose_topic" , 10 , &ImagePoseSubscriber::callback, this); / / Start processing thread processing_thread_ = std::thread(&ImagePoseSubscriber::processQueue, this); } ~ImagePoseSubscriber() { / / Join the thread before destruction if (processing_thread_.joinable()) { processing_thread_.join(); } } private: ros::NodeHandle nh_; ros::Subscriber sub_; std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> data_queue_; std::mutex queue_mutex_; std::thread processing_thread_; bool stop_thread_ = false; void callback(const gaosi_img_pose_flag::ImagePose::ConstPtr& msg) { std::lock_guard<std::mutex> lock(queue_mutex_); data_queue_.push(msg); } void clearQueue() { std::lock_guard<std::mutex> lock(queue_mutex_); std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> empty; std::swap(data_queue_, empty); } void processQueue() { while (!stop_thread_) { std::this_thread::sleep_for(std::chrono::milliseconds( 100 )); / / Adjust as needed std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> local_queue; { std::lock_guard<std::mutex> lock(queue_mutex_); / / 通过交换对象内部的数据成员来完成操作。这个过程不涉及对数据的实际拷贝。 std::swap(local_queue, data_queue_); } while (!local_queue.empty()) { auto msg = local_queue.front(); / / 它返回队列中第一个元素的引用,但不移除它。 local_queue.pop(); / / 移除队列中第一个元素 try { / / Convert ROS image message to OpenCV image cv::Mat cv_image = cv_bridge::toCvCopy(msg - >image, "bgr8" ) - >image; cv::imshow( "Received Image" , cv_image); cv::waitKey( 30 ); } catch (cv_bridge::Exception& e) { ROS_ERROR( "cv_bridge exception: %s" , e.what()); } ROS_INFO( "Received flag: %.2f" , msg - >flag.data); ROS_INFO( "Received pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg - >pose.position.x, msg - >pose.position.y, msg - >pose.position.z, msg - >pose.orientation.x, msg - >pose.orientation.y, msg - >pose.orientation.z, msg - >pose.orientation.w); } } } }; int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_subscriber" ); ImagePoseSubscriber image_pose_subscriber; ros::spin(); return 0 ; } |
image_pose_subscriber.py 例子3-1 类外部(主线程)单独线程处理版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include <ros/ros.h> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 #include <queue> #include <mutex> #include <thread> class ImagePoseSubscriber { public: ImagePoseSubscriber() { / / Initialize subscriber sub_ = nh_.subscribe( "image_pose_topic" , 10 , &ImagePoseSubscriber::callback, this); } / / Function to access the queue from outside std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> getQueueSnapshot() { std::lock_guard<std::mutex> lock(queue_mutex_); return data_queue_; / / Return a copy of the queue } / / Optionally, you can also provide a function to clear the queue void clearQueue() { std::lock_guard<std::mutex> lock(queue_mutex_); std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> empty; std::swap(data_queue_, empty); } private: ros::NodeHandle nh_; ros::Subscriber sub_; std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> data_queue_; std::mutex queue_mutex_; void callback(const gaosi_img_pose_flag::ImagePose::ConstPtr& msg) { std::lock_guard<std::mutex> lock(queue_mutex_); data_queue_.push(msg); } }; void processQueue(ImagePoseSubscriber& subscriber) { while (ros::ok()) { std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> queue_snapshot = subscriber.getQueueSnapshot(); while (!queue_snapshot.empty()) { auto msg = queue_snapshot.front(); queue_snapshot.pop(); / / Process the message (e.g., display image or log pose data) / / This is just an example of processing ROS_INFO( "Processing flag: %.2f" , msg - >flag.data); ROS_INFO( "Processing pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg - >pose.position.x, msg - >pose.position.y, msg - >pose.position.z, msg - >pose.orientation.x, msg - >pose.orientation.y, msg - >pose.orientation.z, msg - >pose.orientation.w); } / / Optionally, add a sleep to prevent busy waiting std::this_thread::sleep_for(std::chrono::milliseconds( 100 )); } } int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_processor" ); / / Initialize ImagePoseSubscriber ImagePoseSubscriber image_pose_subscriber; / / Create a thread to process the queue std::thread processing_thread(processQueue, std::ref(image_pose_subscriber)); / / Spin ROS ros::spin(); / / Join the processing thread before exiting if (processing_thread.joinable()) { processing_thread.join(); } return 0 ; } |
image_pose_subscriber.py 例子3-2 非类外部(主线程)单独线程处理版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <ros/ros.h> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 #include <queue> #include <mutex> #include <thread> #include <iostream> / / Global variables std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> data_queue; std::mutex queue_mutex; / / Callback function to handle incoming messages void callback(const gaosi_img_pose_flag::ImagePose::ConstPtr& msg) { std::lock_guard<std::mutex> lock(queue_mutex); data_queue.push(msg); } / / Thread function to process the queue void processQueue() { while (ros::ok()) { std::queue<gaosi_img_pose_flag::ImagePose::ConstPtr> local_queue; { std::lock_guard<std::mutex> lock(queue_mutex); std::swap(local_queue, data_queue); / / Safely access the queue } while (!local_queue.empty()) { auto msg = local_queue.front(); local_queue.pop(); / / Process the message ROS_INFO( "Processing flag: %.2f" , msg - >flag.data); ROS_INFO( "Processing pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg - >pose.position.x, msg - >pose.position.y, msg - >pose.position.z, msg - >pose.orientation.x, msg - >pose.orientation.y, msg - >pose.orientation.z, msg - >pose.orientation.w); } / / Optional: Sleep to avoid busy waiting std::this_thread::sleep_for(std::chrono::milliseconds( 100 )); } } int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_processor" ); ros::NodeHandle nh; / / Initialize the subscriber ros::Subscriber sub = nh.subscribe( "image_pose_topic" , 10 , callback); / / Create a thread to process the queue std::thread processing_thread(processQueue); / / Spin ROS ros::spin(); / / Join the processing thread before exiting if (processing_thread.joinable()) { processing_thread.join(); } return 0 ; } |
image_pose_flag_publisher.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <std_msgs/Float64.h> #include <geometry_msgs/Pose.h> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 class ImagePosePublisher { public: ImagePosePublisher() { / / Initialize publisher pub_ = nh_.advertise<gaosi_img_pose_flag::ImagePose>( "image_pose_topic" , 10 ); / / Load or create a sample image image_ = cv::Mat::zeros( 480 , 640 , CV_8UC3); / / Black image / / Set flag flag_.data = 1.23 ; / / Example double value / / Set pose pose_.position.x = 1.0 ; pose_.position.y = 2.0 ; pose_.position.z = 3.0 ; pose_.orientation.x = 0.0 ; pose_.orientation.y = 0.0 ; pose_.orientation.z = 0.0 ; pose_.orientation.w = 1.0 ; / / Set publish rate ros::Rate loop_rate( 10 ); / / 10 Hz while (ros::ok()) { gaosi_img_pose_flag::ImagePose msg; / / Convert OpenCV image to ROS image message msg.image = * cv_bridge::CvImage(std_msgs::Header(), "bgr8" , image_).toImageMsg(); msg.flag = flag_; msg.pose = pose_; / / Publish message pub_.publish(msg); ros::spinOnce(); loop_rate.sleep(); } } private: ros::NodeHandle nh_; ros::Publisher pub_; cv::Mat image_; std_msgs::Float64 flag_; geometry_msgs::Pose pose_; }; int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_publisher" ); ImagePosePublisher image_pose_publisher; return 0 ; } |
image_pose_flag_subscriber.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <std_msgs/Float64.h> #include <geometry_msgs/Pose.h> #include <cv_bridge/cv_bridge.h> #include <opencv2/opencv.hpp> #include <gaosi_img_pose_flag/ImagePose.h> // 更换为你包的名字 class ImagePoseSubscriber { public: ImagePoseSubscriber() { / / Initialize subscriber sub_ = nh_.subscribe( "image_pose_topic" , 10 , &ImagePoseSubscriber::callback, this); } private: ros::NodeHandle nh_; ros::Subscriber sub_; void callback(const gaosi_img_pose_flag::ImagePose::ConstPtr& msg) { try { / / Convert ROS image message to OpenCV image cv::Mat cv_image = cv_bridge::toCvCopy(msg - >image, "bgr8" ) - >image; cv::imshow( "Received Image" , cv_image); cv::waitKey( 30 ); } catch (cv_bridge::Exception& e) { ROS_ERROR( "cv_bridge exception: %s" , e.what()); } ROS_INFO( "Received flag: %.2f" , msg - >flag.data); ROS_INFO( "Received pose: Position(%.2f, %.2f, %.2f), Orientation(%.2f, %.2f, %.2f, %.2f)" , msg - >pose.position.x, msg - >pose.position.y, msg - >pose.position.z, msg - >pose.orientation.x, msg - >pose.orientation.y, msg - >pose.orientation.z, msg - >pose.orientation.w); } }; int main( int argc, char * * argv) { ros::init(argc, argv, "image_pose_subscriber" ); ImagePoseSubscriber image_pose_subscriber; ros::spin(); return 0 ; } |
分类:
3_2 ROS
, 1_1_0SLAM工具集合
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
2022-09-13 条形码识别
2018-09-13 ESP8266 HTTP 项目(1)在刻度盘上进行ESP8266 NodeMCU模拟读取的步骤