ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
What you want to do is totally valid but I think you are overseeing some things in this case.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callback (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spin()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is change that several instances of "ros::Spin" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting it). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making ros::Spin blocking, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
2 | No.2 Revision |
What you want to do is totally valid but I think you are overseeing some things in this case.Briefly: It won't work as you expect and you probably does not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callback (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spin()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is change that several instances of "ros::Spin" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting it). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making ros::Spin blocking, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
3 | No.3 Revision |
Briefly: It won't work as you expect and you probably does not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callback callbacks (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spin()" "ros::spinOnce()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is change that several instances of "ros::Spin" "ros::SpinOnce" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting it). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making ros::Spin blocking, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
4 | No.4 Revision |
Briefly: It won't work as you expect and you probably does not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callbacks (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spinOnce()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is change chances that several instances of "ros::SpinOnce" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting it). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making ros::Spin blocking, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
5 | No.5 Revision |
Briefly: It won't work as you expect and you probably does not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callbacks (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spinOnce()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is chances that several instances of "ros::SpinOnce" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should.
A callback should stay as simple and fast as possible.
In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting it).
them).
It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making ros::Spin blocking, "ros::Spin" blocking for a long time, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
6 | No.6 Revision |
Briefly: It won't work as you expect and you probably does do not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callbacks (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" function.
So basically when you call the "ros::spinOnce()" function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, you pass it a NodeHandle and each NodeHandle has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is chances that several instances of "ros::SpinOnce" will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting them). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making "ros::Spin" blocking for a long time, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.
7 | No.7 Revision |
Briefly: It won't work as you expect and you probably do not need such a complex way of designing your node.
When it comes to communication in roscpp, two kind of objects are handling callbacks:
A spinner is an object that has the ability to call the callbacks contained in a callback queue. A callback queue is the object in which each subscriber will add an element each time a message is received by resolving which kind of message should call which callbacks (and with which arguments).
Regarding the spinners, there is currently three implementations available in roscpp:
These objects may be instantiated manually in advanced ROS nodes but to avoid verbose initialization, an alternative, object-less, API is provided through functions in the ROS namespace. Aka ros::spin(), ros::spinOnce() ros::spin()
, ros::spinOnce()
and so on. This API rely on a default callback queue implemented as a singleton which is accessible through the "ros::getGlobalCallbackQueue()" ros::getGlobalCallbackQueue()
function.
So basically when you call the "ros::spinOnce()" ros::spinOnce()
function, a single-thread spinner is created and its spin method is called once using the default callback queue (see init.cpp from roscpp).
And to finish, when you create a Subscriber, Subscriber
, you pass it a NodeHandle NodeHandle
and each NodeHandle NodeHandle
has an associated callbackqueue that default to the global one but which can be overridden using the getCallbackQueue/setCallbackQueue getCallbackQueue
/setCallbackQueue
methods.
If you take a look at spinner.cpp you will see there is a mutex that make the SingleThreader thread-safe while discouraging you to use it in this case (line 48).
Conclusion: what you do is safe but will trigger regularly ROS error messages as there is chances that several instances of "ros::SpinOnce" ros::SpinOnce
will be executed in parallel.
Considering your applications, I think your callbacks are just not written as they should. A callback should stay as simple and fast as possible. In most of the cases, a callback is just feeding ROS data to your own classes which is usually as simple as copying data (and maybe converting them). It will help you ensuring that your callbacks are thread-safe (if you want to convert your node to a nodelet for instance, one day) and avoid making "ros::Spin" blocking for a long time, even in the case you are using the single-threaded spinner.
Typically, if you want to do time-consuming computations such as "leg detection", the callbacks are definitively not the place to do it.
Just, copy your data to a LegDetector object instance and call in your main thread the method that will do the heavy work. In particular here, you really don't care about losing old messages if your node is not fast enough so there is really no reason to pay the extra-burden of all the multi-thread infrastructure. Use Boost.Bind for instance, to pass a reference to your LegDetector class to the callback that will just copy the relevant laser data into it.
If, at some point, you need to synchronise the received data, use the message_filters API. In this case again, trying to use multi-thread to do so is definitively a bad idea.