I looked into the issue posted one month ago, that thrown exceptions in service-servers are not passed to the service-clients.
This is at least the case for roscpp - in rospy (and roslisp) it is implemented already.
After some "warm-up" with the respective code-parts I came up with a small patch (see attached - this is not meant to be committed!!!).
I have tested the following scenario:
- add_two_ints_server (c++, modified to throw a runtime-exception)
called by
- add_two_ints_client (py)
Usually the serialization of the response (generated in "serializeServiceResponse") contains the following content: ok-flag, msg-size, msg-payload.
But in order to make it compatible with rospy the response must contain only: ok-flag, msg-payload.
Before looking at the client part of the roscpp service handling (to also output the received error string) I would like to clarify the serialization format.
Is there any specification how a service response must look like (even in the case of "ok" being false)?
Is the current implementation of rospy/roslisl "correct" or should it be altered to also contain the message size?
Dirk
On 08.11.2011 17:31, Thibault Kruse wrote:
> I raised this a while ago here:
> https://code.ros.org/trac/ros/ticket/3590
> but i could not provide a patch myself.
>
> With a patch the ticket may get more attention.
>
> It should not be too difficult technically (I implemented it for roslisp as for
> rospy in https://code.ros.org/trac/ros/ticket/3594), but I found it too hard
> to dig into the roscpp code.
>
>
>
>
> On 11/08/2011 05:13 PM, Dirk Thomas wrote:
>> Hi,
>>
>> we are using ROS services implemented in Python as well as in C++.
>> We found one significant difference in both implementations (which makes debugging more difficult):
>> This is when a service throws an exception.
>>
>> In both languages a message is printed on the server's console.
>> In Python the string of the exception is also passed to the client.
>> But in C++ the exception is NOT passed to the client.
>>
>> Is there a technical reason why the C++-ServiceCallback does not pass the exception message?
>> If not could this be added?
>>
>> Regards,
>> Dirk
Index: clients/cpp/roscpp_serialization/include/ros/serialization.h
===================================================================
--- clients/cpp/roscpp_serialization/include/ros/serialization.h (revision 15393)
+++ clients/cpp/roscpp_serialization/include/ros/serialization.h (working copy)
@@ -833,6 +833,16 @@
serialize(s, (uint32_t)m.num_bytes - 5);
serialize(s, message);
}
+ else if (!ok) // this is only to illustrate the diff to the already existing else block
+ {
+ uint32_t len = serializationLength(message);
+ m.num_bytes = len + 1;
+ m.buf.reset(new uint8_t[m.num_bytes]);
+
+ OStream s(m.buf.get(), (uint32_t)m.num_bytes);
+ serialize(s, (uint8_t)ok);
+ serialize(s, message);
+ }
else
{
m.num_bytes = 5;
Index: clients/cpp/roscpp/src/libros/service_publication.cpp
===================================================================
--- clients/cpp/roscpp/src/libros/service_publication.cpp (revision 15393)
+++ clients/cpp/roscpp/src/libros/service_publication.cpp (working copy)
@@ -39,6 +39,8 @@
#include <boost/bind.hpp>
+#include <std_msgs/String.h>
+
namespace ros
{
@@ -126,7 +128,9 @@
catch (std::exception& e)
{
ROS_ERROR("Exception thrown while processing service call: %s", e.what());
- SerializedMessage res = serialization::serializeServiceResponse(false, 0);
+ std_msgs::String error_string;
+ error_string.data = e.what();
+ SerializedMessage res = serialization::serializeServiceResponse(false, error_string);
link_->processResponse(false, res);
return Invalid;
}