Foxy Message API Review

In preparation for Foxy we are going to be putting the core messages through an API review next week. If you have any comments suggestions or otherwise please submit any comments you have about the messages using this form.

For reference here’s a document listing all the messages we will be reviewing.

ROS 2 Message Packages API Review.pdf (62.3 KB)

Please submit your comments before 2020-03-09T07:00:00Z to be considered.

8 Likes

This is great news!

The form allows feedback only at the single message level, so I’m posting some suggestions that don’t fit in that category here:

  • remove actionlib_msgs completely as it is a duplicate of action_msgs, this allows not to have to iterate on its API

  • std_msgs: Often in ROS 1 we see recommendations to “not use std_msgs directly but semantically meaningful messages instead”.
    It would be good to treat differently the ones that are expected to be used (e.g. Header) from the ones that “should not be used”
    Suggestions:

    1. take out the non-semantically meaningful messages out of std_msgs to e.g example_interfaces, and put them in another package (or remove them completely)
    2. Move the widely used ones (e.g. Header) to their own package to avoid building and installing the non-semantically meaningful ones
      It would both allow to save build time + install size as well as encouraging users to not use those in their custom messages

    Some relevant past discussion Suggestions for std_srvs

1 Like

Please see the deprecation notice embedded in the package manifest: https://github.com/ros2/common_interfaces/blob/519e851f6ac71262e45b6e5ca66bce653a72948d/actionlib_msgs/package.xml#L28-L30

  This package will be removed in a future ROS distro, once the ROS 1 bridge supports actions.

One thing I’ve wondered about is why std_msgs/Header no longer has a sequence number. The sequence number has been quite helpful in the past to detect lost messages.

It would also be interesting to add an improved message for driving robot bases. The message that has been used until now, geometry_msgs/Twist, is problematic because it does not have a header, and hence, you cannot detect message age and discard delayed commands. In the micro-ROS project, we have prototyped a replacement, see
TRVCommand and CommandHeader.

btw “TRV” stands for Translational-Rotational-Velocity.

1 Like

Wasn’t TwistStamped added for cases where this mattered? I’m not entirely sure whether there are semantics attached to it that would prevent it from being used here.

I’ve not seen it used with many mobile base drivers, but it would seem to be able to address this shortcoming of Twist.

1 Like

There is indeed now a twist stamped, but not much of the ecosystem uses it. I agree wider use would be valuable, especially in absence of a sequence.

I’m going to file a ticket for that in Navigation/related. It won’t be in for foxy, but I’ll add a deprecation warning and move into TwistStamped in G turtle.

The TRV command seems limited, I think we should stick to Twist. It can be used for omni robots with non-forward velocities and converted to ackermann trivially. Its also used on some drones.

Thanks for that comment!

Edit: ticket https://github.com/ros-planning/navigation2/issues/1594

How does twist_stamped help? It can be stamped upon generation, but maybe the navigation algorithm took very (unexpectedly) long and is thus based on old sensor information.
Or the message never arrives and you cannot check it’s timestamp -> you need a timeout detection mechanism on the receiving side to be safe.

Which problem does the stamped message tackle which cannot be caught with a timeout detection?

To me that’s the wrong way of thinking. A stamp provides additional information to the receiver which may be useful or not, depending on the implementation. For example, it can also detect the case where the clocks are going out of sync, etc.

We’re not usually skimping on fields, so why do it here?

1 Like

I’m not against it, I was actually curious what this would solve in addition to a timeout detector which one would need anyway.

But in the ticket it was already pointed out that arriving out of order was a valid usecase. And out-of-sync clocks is actually another one. So I’m game!

The TRV command is limited intentionally, as a way of communication by the low-level driver to the upper level what the platform is capable of. That’s what interfaces are for, wouldn’t you agree?

btw, a twist message uses 7 floating point fields to convey information that, for differential drive can be communicated as 2 entries, and even for omnidirectional platforms could be communicated as 3 entries. This may not matter much when everything is on an industrial PC or similiar compute platform, but in micro-ROS, we have defined messages for communicating with micro-controllers that may be on a low-bandwith link, or even only wirelessly attached.

Granted, right now we waste what we gained through a rather large header, but that is being addressed :wink:

Edit regarding ackermann: I have so far been under the impression that Twist cannot usefully be converted for use by Ackermann steering platforms. That’s what my colleagues who use such platforms told me, and what I’ve also seen through things like ackermann_msgs. If you disagree, that might be useful information to share.

As we covered in the ticket, but repeating shortly here for cross referencing:

If you stop running a controller from a timeout, that’s not to say that the information that you are receiving is current, nor is it a promise that this data is in order with async communications afoot (though ROS2 helps this greatly). Just saying “I haven’t received a message in X seconds” is not the same thing as “was this command newer than X seconds to execute, and newer than my last message” by actual intent and not by reception.

I have to break that statement down - let me know if I’m reading you correctly. If you’re communicating between the low-level driver (what’s “low level” to you, we all have different definitions. I’m thinking hardware controller driving the motor) and the upper-level (which I’m thinking is a TX2, NUC, or other compute module), what’s wrong with TwistStamped? If you were to argue that this is for internal use for low-level drivers for your specific application, I say have at it, but once you hit the main compute module, we should follow conventions that generalize.

“Generalize” meaning to use messages with large portability across many types of systems. That message is only suitable for differential-type robots. That makes anything you design with that message type automatically incompatible with >50% of the community (with omnidirectional or ackermann robots, drones, cars, submarines (?)). The great thing about Twist messages is that they’re 3D velocities in position and angle and therefore if you support it, you support any 3DOF system moving through space.

Your comment on “that’s what interfaces are for” – I’m not sure what you’re getting at there. If you’re saying that you use TRV messages for internal use, that’s totally fine, go for it. But I think for community facing open-source code, we should make sure that our work generalizes, as much as practical given your constraints, to as wide a variety of things as possible. Something like Micro-ROS should have great portability so I would believe this is something you’d want to support.

http://wiki.ros.org/teb_local_planner/Tutorials/Planning%20for%20car-like%20robots

As above, Twist is 3DOF representation. Any rigid-body robot can have their motion described this way. See script (there’s alot of unrelated words, just something I’ve seen used before).

Ah, that sounds reasonable, the middleware is certainly the right place to manage this. The only question is: How do I get the number then? I searched a bit but couldn’t find it.

Thank you to everyone for your input and discussions.

I’ve collated the comments into a review doc on common_interfaces.

Please use the Github PR to make any further comments or suggestions or give any other feedback on the existing comments.

I will be going over these actions to triage them for scale and prioritization on Friday the 13th. If you would like to be involved in the meeting please ping me directly.

I’m referring to the drivers implementing the robot interface (e.g., kobuki_driver), regardless of whether they do the actual motor control, or whether they are talking to something that does. A differential drive is already a combination of at least two motors anyway.

While I agree that generalization is a good goal, I’m not sure that just putting everything you might need, regardless of whether it is actually supported, into one message is a good strategy to achieve it.

Firstly, to actually generate the content of the message, you need to know what your robot is capable of. You would not use a controller for differential drive robots to steer your drone, right? If you have a different controller anyway, it is not difficult to have it send a different message.

Secondly, command velocities are sent over a topic, and topics have no back-channel. Therefore, what would happen if you send an y- or z-velocity to your differential drive robot? Is it supposed to ignore it? Do nothing? This is not a robust interface.

When I say “that’s what interfaces are for”, I mean that interfaces are supposed to communicate the capabilities of the entity implementing them. Twist fails this criterion.

TEB is actually a pretty good example of why Twist is not a good interface, and they readily admit they are only using it because it’s (currently) the only thing supported by move_base: It supports two different ways of interpreting the data in a Twist message – the usual translation and rotational velocity interpretation, and the interpretation where instead of a rotational velocity a steering angle is sent. This is configured using a parameter. Good interface? I think not.

Of course I don’t know everybody (by far) who is using ROS for car-like vehicles, but of those that I know, nobody is using either move_base or Twist.

1 Like

Hi,

Well what I don’t want to do is get defensive about this but I think we have starkly opposing thoughts on this topic. I’ll outline my thoughts in respect to your comments, but this seems like a discussion to be had with a wider and engaged audience from across the mobile robotics community.

So something as the “host machine” interface to the hardware (the program which takes ROS commands and sends them over the wire to some microcontroller driving the base or something). Ok, not what I think of as low-level, but good to have a common definition to work with.

In this case, this is typically running on the host machine (main CPU) which probably has some power behind it. Even in the case of limited-resource processors, if its running ROS and able to fuse sensors and output some message for a command, its going to be powerful enough that the extra few bytes of a Twist message aren’t important. I thought the argument you were trying to make was if you had ROS messages going over the wire itself, which extra fields could be not ideal.

Even in that case, your example is oversimplified. While some applications can get away with just velocity commands, in practice, you probably need other fields like torque characteristics and time-out durations, etc for an industrial application. So dropping Twist to 2 numbers as the rationale for professional applications that require this level of optimization to create a new message seems tongue in cheek to make a point.

Lets say that a different way then. For instance you have a controller, lets say a DWA, Lattice, sampling, etc controller. Many types of controllers exist, but these are common ones to analyze. Many of these controller require some profile of motion (how much can it turn, how fast, etc). These controllers can be trivially reconfigured to support differential and omni-directional platforms with about 3 parameter changes running the same code. In some cases, like TEB, they can even generalize to car-like robots. So what you propose if a controller were to publish at TRV message is that controllers which algorithmically can support 2-3 different robot base types should have unique and different messages for each? That doesn’t seem right.

Having multiple message types, TRV, TAV, TOV, makes now these controllers no longer swappable to other applications easily. A big, big reason the ROS ecosystem is so active is that we give people the ability to trivially swap out capabilities using common interfaces like geometry_msgs/Twist and plugin interfaces. You don’t like this controller, use that controller. And there are plenty of controllers to choose from, though once you get super-serious on an industrial setting, you may choose to create your own. However, I can say from first-hand experience consulting and third-hand experience from robotics companies, that many robotics companies do use controllers like TEB in production, today. Including large heavy machinery outdoors, in warehouses, and in human-centric environments.

I think that comes from your anecdotal experience as a professional ROS user and developer. I agree for people like us that’s not prohibitively hard, but if every controller, in every package, across the ecosystem used a different message format and these weren’t able to be cross-used easily, where would we be today? If as a user, nothing worked well out of the box and I had to made adapters on top of adapters to get a basic demo working, I wouldn’t bother. We have these conventions of how we represent types of data so that we can built toolchains that are hardware invariant to process or work with data. If you think Twist is insufficient, I can probably come up with 20 other places outside the controller and hardware driver that you would need to fork and modify to support your specific message format to have work including things like:

  • robot_localization
  • some of the SLAM libraries
  • Gazebo/Ignition
  • RVIZ (with certain plugins), etc.

So now, you don’t just own your custom message, you’re now forking gazebo_ros_pkgs, slam_karto, robot_localization, maybe some rviz stuff, just off the top of my head. If we didn’t have a convention around pointcloud data, where would we be in depth processing capabilities? Is it a perfect message? Absolutely not. But its the inperfection we agreed upon to build capabilities on top of that are as flexible as possible to enable the design intent of ROS for highly configurable systems.

In reality, if you need a 3D perception system because you’re working with a large mobile or mobile-manipulator task (with an omnidirectional base), there’s not a huge reason that your local trajectory following methods can’t also be run on a drone. This isn’t a strong argument I want to focus on though, that’s was just illustrative.

I agree that this is not ideal. However, it is the current minimum-viable solution for standardizing the way we build systems and toolsets to support them. I would argue though, that if you know that this message is used, it would be part of a designer creating a fault-tolerant system to make sure it handles it in the ideal way for your application. Throw exceptions, log, ignore, etc. I’d assert that you should be able to handle faults in a clean way in a robotics application and this is no different, though self-imposed vs something you can’t help like sensor data being messy or issues with connectivity. Having some standard REP about what to do in this situation would have value. My personal suggestion would be to throw exceptions because if that’s happening, there’s clearly something terribly wrong.

I think you’re taking their words out of context. See block of text copy-pasted from that link below:

Some command interfaces (such as the stage simulator in car-like mode) require a geometry_msgs/Twist, but with changed semantics. The angular velocity ( z -axis) is interpreted as steering angle. Note, changing the semantics of a message is not preferred in general, better switch to the ackermann_msgs interface if possible.

Its clear to me that this is in discussion about Ackermann robot support, not the general representation of Twist for most types of robots that run TEB. The author of this system doesn’t use Ackermann type robots so its not a shocker that there’s not been more work to try to support it natively because it doesn’t have utility and the conversion process is a trivial mathematical operation based on robot characteristics.

That may be part of your issue - there are plenty of robotics companies using ROS that have car-like vehicles. And more are coming to market daily with delivery robots and other robots that require to break out of the 2D-planar clean environment differential and omnidirectional robots shine. They may be using Ackermann messages, but I would put money on it that alot of them are using TEB or some MPC that gives out a body-frame 3DOF target state and they’re being converted into Ackermann steering messages no differently than the script above.

I don’t think too many folks (though there are some) that use move_base out of the box. But there are a variety of move_base-like projects such as Move Base Flex and Robot Navigation that are used in production by thousands of robots globally by the likes of Magazino and Locus Robotics. I’d also put money on it they use Twist for the reasons mentioned above unless they’d like to create a ton of existing infrastructure in-house for little if any value add to their customers. Keeping in mind ROS2 is around, the Navigation2 stack is targeted at production robotics applications. I want to see the mobile and manipulation ecosystems in ROS2 mature to a point that they are viable commercial solutions. There have been great strides to that end and we’re not too far off from it.


Phew that was alot. Now here’s my thoughts that aren’t just counter-points. I’m all for having a discussion about a new message format to describe control efforts to a base Twist2 or whatever, but that should be then a discussion and not an assertion by making use of a custom message in one corner of the community without consulting the others that this directly impacts. If there’s a legitimate concern, we should have a proper discussion about it, weighing trade offs, and coming to some resolution in the form of an REP. I’m all for a new format, especially in ROS2 where we have more ability to change things since we’re not EOLing it in a few years. But that should be a larger and informed decision.

Maybe we do something like in the Image or Pointcloud2 message where we have some data embedded field and some metadata around what is supplied in it. That way you get fewer bytes and we don’t break compatibility, though requiring a whole-lot of rework across the ecosystem.

I’d just like to mention that long discussions about specific issues is probably better done on their own discourse post or an issue on the appropriate issue tracker.

Right now we’ve got multiple topics of conversation going and we’re potentially interleaving the discussions. I think it’s going to make it harder for people to retroactively follow these discussions.

But please do continue the discussions.


Unfortunately we don’t have that yet. We do have a GUID for the publisher that sent a message when you receive one with a subscription, but not the sequence number which is part of a series of sequence numbers for that particular publisher. It would be added here:

As for how the middleware could supply it, I think RTPS may already have this but it may not be exposed. If not we could potentially send it with some of the available metadata options available in RTPS. Worst case a middleware could wrap all user messages in a message that has an additional sequence number field, which is sort of what we do for Services.

1 Like

Done: Is "Twist" (still) a good velocity command interface

2 Likes

Thanks, opened https://github.com/ros2/rmw/issues/201