点击(此处)折叠或打开
- 什么时候用ros::spin()和ros::spinOnce()
- 当只有话题订阅时, 则程序只需要在话题消息来临时响应回调函数即可, 即为使用 ros::spin(), 即为死循环.
- 当还有其他事情要做,是仅仅把时间片给ROS系统用,可以用来响应一些订阅回调(也可能什么也没做)或者给ROS系统做一些其他事情, 完毕后ROS系统再把时间片回到程序中来.
- 一般的用法:
- ros::Rate loop_rate(10);
- while (ros::ok()) {
- do_something();
- ros::spinOnce();
- loop_rate.sleep();
- }
点击(此处)折叠或打开
- #include "ros/ros.h"
- #include "ros/callback_queue.h"
- #include "std_msgs/String.h"
-
- #include <boost/thread.hpp>
- /**
- * tutorial demonstrates the use of custom separate callback queues that can be processed
- * independently, whether in different threads or just at different times.
- * 演示了自定义独立回调队列的使用,
- * 这些回调队列可以在不同的线程中独立处理,也可以在不同的时间进行处理。
- */
-
- void chatterCallbackMainQueue(const std_msgs::String::ConstPtr& msg)
- {
- ROS_INFO_STREAM("I heard: [ " << msg->data << "] in thread [" << boost::this_thread::get_id() << "] (Main thread)");
- }
-
- //主线程中的调用
- void chatterCallbackCustomQueue(const std_msgs::String::ConstPtr& msg)
- {
- ROS_INFO_STREAM("I heard: [ " << msg->data << "] in thread ["
- << boost::this_thread::get_id() << "]");
- }
-
- /**
- * The custom queue used for one of the subscription callbacks
- */
- ros::CallbackQueue g_queue; //第一步:用于订阅回调的自定义队列
- void callbackThread()
- {
- ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
-
- ros::NodeHandle n;
- while (n.ok())
- {
- //第四步: 执行自定义队列中的回调函数.
- // CallbackQueue类有两种调用内部回调的方法:callAvailable()和callOne()。
- // callAvailable()将获取队列中当前的所有内容并调用它们。callOne()将简单地调用队列上最古老的回调。
- g_queue.callAvailable(ros::WallDuration(0.01));
- }
- }
-
- int main(int argc, char **argv)
- {
- ros::init(argc, argv, "listener_with_custom_callback_processing");
- ros::NodeHandle n;
-
- /**
- * The SubscribeOptions structure lets you specify a custom queue to use for a specific
- * subscription. SubscribeOptions结构允许您指定用于特定订阅的自定义队列
- * You can also set a default queue on a NodeHandle using the
- * NodeHandle::setCallbackQueue() function.
- * 还可以使用NodeHandle::setCallbackQueue()函数在节点句柄上设置默认队列
- *
- * AdvertiseOptions and AdvertiseServiceOptions offer similar functionality.
- * 对于话题发布者, 有 AdvertiseOptions 和 AdvertiseServiceOptions 可以使用
- */
- //第二步: 声明订阅或者发布选项, 然后和订阅器/发布器绑定在一起
- ros::SubscribeOptions ops = ros::SubscribeOptions::create<std_msgs::String>
- ("chatter", 1000, chatterCallbackCustomQueue, ros::VoidPtr(), &g_queue);
- ros::Subscriber sub = n.subscribe(ops);
-
- ros::Subscriber sub2 = n.subscribe("chatter", 1000, chatterCallbackMainQueue);
-
- //第三步: 声明线程.
- boost::thread chatter_thread(callbackThread);
- ROS_INFO_STREAM("Main thread id=" << boost::this_thread::get_id());
-
- ros::Rate r(1);
- while (n.ok())
- {
- ros::spinOnce();
- r.sleep();
- }
-
- chatter_thread.join();
-
- return 0;
- }
MultiThreadedSpinner对象
允许您指定用于调用回调的线程数。如果没有指定显式的#,它将使用系统上可用的硬件线程的#。这里我们显式地指定4个线程
点击(此处)折叠或打开
- ros::MultiThreadedSpinner s(4);
- ros::spin(s) //主要是 spin
AsyncSpinner
可以认为是写在while外边的spinOnce. while内仅仅需要sleep即可. 这样主线程,子线程可以并行执行.
点击(此处)折叠或打开
- ros::AsyncSpinner s(4);
- s.start();
- ros::Rate r(5);
- while (ros::ok())
- {
- ...
- r.sleep();
- }
多个不同的topic 用一个回调处理
点击(此处)折叠或打开
- void callback(const ImageConstPtr& image_color_msg,
- const ImageConstPtr& image_depth_msg,
- const CameraInfoConstPtr& info_color_msg,
- const CameraInfoConstPtr& info_depth_msg)
- {
- ....
- }
- int main(int argc, char** argv)
- {
- ros::init(argc, argv, "vision_node");
-
- ros::NodeHandle nh;
-
- //不同类型的topic订阅
- message_filters::Subscriber<Image> image_color_sub(nh,"/camera/rgb/image_raw", 1);
- message_filters::Subscriber<Image> image_depth_sub(nh,"/camera/depth_registered/image_raw", 1);
- message_filters::Subscriber<CameraInfo> info_color_sub(nh,"/camera/rgb/camera_info", 1);
- message_filters::Subscriber<CameraInfo> info_depth_sub(nh,"/camera/depth_registered/camera_info", 1);
- pointcloud_pub = nh.advertise<PointCloud> ("mypoints", 1);
-
- //定义规则
- typedef sync_policies::ApproximateTime<Image, Image, CameraInfo, CameraInfo> MySyncPolicy;
- //规则化实例
- Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), image_color_sub, image_depth_sub, info_color_sub, info_depth_sub);
- //绑定回调
- sync.registerCallback(boost::bind(&callback, _1, _2, _3, _4)); // _1 代表实力的第一个对象.
-
- ros::spin();
-
- return 0;
- }
点击(此处)折叠或打开
- void init()
- {
- node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(chatterCallback, _1, "User 1"));
- node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(chatterCallback, _1, "User 2"));
- node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(chatterCallback, _1, "User 3"));
- }
-
- void chatterCallback(const std_msgs::String::ConstPtr& msg, std::string user_string)
- {
- ROS_INFO("I heard: [%s] with user string [%s]", msg->data.c_str(), user_string.c_str());
- }
点击(此处)折叠或打开
- #include "ros/ros.h"
-
- /**
- * This tutorial demonstrates the use of timer callbacks.
- */
-
- void callback1(const ros::TimerEvent&)
- {
- ROS_INFO("Callback 1 triggered");
- }
-
- void callback2(const ros::TimerEvent&)
- {
- ROS_INFO("Callback 2 triggered");
- }
-
- int main(int argc, char **argv)
- {
- ros::init(argc, argv, "talker");
- ros::NodeHandle n;
-
- ros::Timer timer1 = n.createTimer(ros::Duration(0.1), callback1); //0.1秒一次
- ros::Timer timer2 = n.createTimer(ros::Duration(1.0), callback2); //1秒一次
-
- ros::spin();
-
- return 0;
- }
点击(此处)折叠或打开
- void timerCallback(const ros::TimerEvent&, ros::Publisher vel_pub)
- {
- ...
- }
- ros::Publisher vel_pub = nh.advertise<han_agv::VelEncoder>("HansAGV/encoder_vel", 1);
- ros::Timer decoder_timer = nh.createTimer(ros::Duration(0.1), boost::bind(timerCallback, _1, vel_pub))
点击(此处)折叠或打开
- #include "ros/ros.h"
- #include "std_msgs/String.h"
-
- #include <sstream>
-
- /**
- * This tutorial demonstrates how to get a callback when a new subscriber connects
- * to an advertised topic, or a subscriber disconnects.
- */
-
- uint32_t g_count = 0;
-
- void chatterConnect(const ros::SingleSubscriberPublisher& pub)
- {
- std_msgs::String msg;
- std::stringstream ss;
- ss << "chatter connect #" << g_count++;
- ROS_INFO("%s", ss.str().c_str());
- msg.data = ss.str();
-
- pub.publish(msg); // This message will get published only to the subscriber that just connected
- }
-
- void chatterDisconnect(const ros::SingleSubscriberPublisher&)
- {
- ROS_INFO("chatter disconnect");
- }
-
- int main(int argc, char **argv)
- {
- ros::init(argc, argv, "notify_connect");
- ros::NodeHandle n;
-
- /**
- * This version of advertise() optionally takes a connect/disconnect callback
- * advertise 有连接和断开的回调注册
- */
- ros::Publisher pub = n.advertise<std_msgs::String>("chatter", 1000, chatterConnect, chatterDisconnect);
-
- ros::spin();
-
- return 0;
- }