-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rclpy raw subscriptions #242
rclpy raw subscriptions #242
Conversation
I've updated the implementation to use rmw's allocator (I believe) properly. Let me know if this is a reasonable way to go about this and I'll round it out with tests and an example. |
The idea here looks good to me. This needs a rebase, and as you mentioned tests and examples, but I think we can go ahead with this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marking this as "Request changes" until it is rebased and comments are fixed.
Thanks for the review. I'll have a chance to work on the rebase, requested changes and tests this weekend. |
90fb8e7
to
9194f0f
Compare
I think this PR is done now. I don't believe that this functionality requires a demo node, although I can happily add one. It's fairly esoteric and demo nodes are aimed at beginners. Unit tests pass locally for the package, however the build farm test is failing. I think it's due to the build farm compiling against bouncy debs (specifically bouncy rcl), when this is built against and branched off of the latest master branch. Let me know if you believe that is my fault and I'll dig further to fix it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It generally looks good to me. One remark I'd have though is that the test is maybe not necessarily complete here. Just because the received message has a non-zero amount of bytes, doesn't necessarily mean the message is complete and correct.
In your opinion, how much effort would it be to expose the rcl_serialize
and rcl_deserialize
functions to this PR? This would allow to instantiate the message being published, serialize it and byte-wise compare the received message.
self.assertIsNotNone(self.raw_subscription_msg, 'raw subscribe timed out') | ||
self.assertIs(type(self.raw_subscription_msg), bytes, 'raw subscribe did not return bytes') | ||
# The length might be implementation dependant, but shouldn't be zero | ||
self.assertNotEqual(len(self.raw_subscription_msg), 0, 'raw subscribe invalid length') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this really test that the incoming message is complete and correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only partially tests the incoming message.
That said, it seems unlikely that it's incorrect given that the rclpy code does not manipulate the array. If a non-zero array is passed up, it means that rcl_take_serialized_message returned bad data, and it should have its own tests. I understand the desire for completeness though, and if we do expose deserialization to rclpy we can make this test more robust.
@josephduchesne thanks for all the work done here. In the meantime, I am actually in favor of having a demo similar to the C++ version of it so that the demo packages don't diverge too much. I don't consider them only aiming at beginners, but also to literally demonstrate the capabilities of ROS 2 and their respective APIs. |
I poked around the rcl code and it appears that this doesn't exist in rcl. The functions you are thinking of are probably rmw_serialize and rmw_deserialize. That raises some design questions. How would these look: rmw_ret_t
rmw_deserialize(
const rmw_serialized_message_t * serialized_message,
const rosidl_message_type_support_t * type_support,
void * ros_message) string_message = rclpy.deserialize(input_bytes, std_msgs.msg.String) rmw_ret_t
rmw_serialize(
const void * ros_message,
const rosidl_message_type_support_t * type_support,
rmw_serialized_message_t * serialized_message) output_bytes = rclpy.serialize(std_msgs_string_object) Should I go ahead with this, or is this too much of a diversion from this original ticket? It's not prohibitively complex, but I'm not sure the use case justifies the effort at the moment. This would be required if someone wanted to implement something like ros1's rosbag (ros2bag doesn't use the rmw serialization system AFIK, and for good reasons- although it appears to me to result in an inevitable performance hit due to the abstraction). Other than that I don't think it provides much value. |
I believe it makes sense to add this here, e.g. once you've received binary data, eventually the binary data should be converted to ROS messages again. This use case is also helpful for the tests of this PR. In case, the proposed python API for the self.pub = self.create_publisher(String, 'chatter') https://github.com/ros2/demos/blob/master/demo_nodes_py/demo_nodes_py/topics/talker.py#L26 With that the proposed API: string_message = rclpy.deserialize(std_msgs.msg.String, input_bytes)
binary_message = rclpy.serialize(std_msgs.msg.String, message) Let us know if you want to work a little bit more on this. Otherwise, we could go ahead and merge this and ticket the remaining tasks. |
For |
Unfortunately, I don't think I'll have time in the next few weeks to work on further extending rclpy, and it would be nice to unblock the I can try to do the rclpy.deserialize/rclpy.serialize work around the holidays, but that's probably about as much work as this PR by itself, again. |
Concerns handled, clearing review for others to review.
@Karsten1987 can this be merged? |
The current branch does not compile with the latest master version and has to be rebased as far as I can tell. |
…d implicit type cast error uint8 -> char with explicit cast
Latest master branch merged in, compiled and tested in a clean source install of ros2 crystal (with the minor fixes performed). Also updated the sister request in ros2/demos#287 in the same way although it worked without changes after merging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one little comment, but lgtm.
PyObject * python_bytes = PyBytes_FromStringAndSize((char *)(msg.buffer), msg.buffer_length); | ||
rmw_ret_t r_fini = rmw_serialized_message_fini(&msg); | ||
if (r_fini != RMW_RET_OK) { | ||
PyErr_Format(PyExc_RuntimeError, "Failed to deallocate message buffer: %d", r_fini); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it return NULL
in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It now returns NULL after decremented the python_bytes
refcount in this error condition. If this is an adequate solution, I think this might finally be merge-able :)
…ne/rclpy into add-raw-subscription-option
Thanks for iterating over this. |
Note: This implementation is incomplete and at the moment this PR exists primarily for getting feedback.
This is being done so that ros2cli#132 can implement "ros2 topic bw".
The general idea is to allow creating a raw subscription like so:
This will call rcl_take_serialized_message rather than rcl_take internally, and return a python byte array representing the serialised message.