-
Notifications
You must be signed in to change notification settings - Fork 168
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
[ROS 2] Separate robot description publishing from robot state publishing #144
Comments
This was kind of a design decision when I revamped In ROS 1, the XML text of To be totally clear, that idea of "ownership" wasn't meant to preclude using it in another way. But it was meant to make people think about how to design their system for dynamic changes to the description. So here we are :). I guess I'll ask the obvious question: would it be possible in your system to turn things around so that [1] Previously in ROS 2 we had nothing that "owned" the robot_description. That meant that each program that wanted the description had to be passed it during startup. The problem with that model is that it becomes a lot harder to do updates to the description, which is why I wanted to find a place for the description to live. |
Yup, If I understand correctly: the parameter server owned the robot description in ROS 1. Right now in ROS 2
If I understand correctly the ownershipp idea isn't new; it's the change to a topic that forces thinking about dynamic changes - like what should the system do if a new robot description is published.
This question seems to be assuming a different use case - I should have given more detail in the issue description. I see it making sense for the simulation component to consume the robot description if the robot being simulated runs ROS 2 and one wants to simulate it. They would start the robot software and spawn it in the simulation when that's ready. The use case I'm looking at is different. There is a working simulation already and someone wants to interact with it using ROS tools. The simulation has a world which includes a description of a robot it's simulating, but the robot may not run ROS 2 at all. I don't think it makes sense for the simulation to consume a robot description because it already works fine even if no ROS 2 code is running - it doesn't need or want a dependency on ROS, it just wants to occasionally use it when convenient. This issue isn't about changing the idea of something owning the robot description or about changing the mechanism that deliveres it to consumers. The result I'd like to see is a dedicated node publishes the robot description with nodes that do useful things with a robot description (like joint_state_publisher, robot_state_publisher, and the RViz robot model display) only being subscribers. That allows someone to take ownership of the description without losing access to any of those tools. |
I see, thanks for the clarification.
So just to make sure I understand you properly. In a fully ROS 2 robot, you would run In the non-ROS 2 use case you outline above, you would not run Is that an accurate description of what you'd like to achieve? |
Yup! How's that sound? |
We should be able to make it work, but there are some details to work out on how to do it. I see a few different ways:
@sloretz Any other ideas come to mind? |
I was thinking something along the lines of option 1. Say |
I sort of prefer option 3, since it is easy to document them separately. But if you like option 1, that's OK with me too.
I will say that I don't particularly like this. It feels like it is easy for the user to shoot themselves in the foot. The user starts up |
I too think this would be helpful. An issue I've faced previously with robot_state_publisher is that for complicated robots you need joint_state_publisher (or joint_state_controller) to be working before robot_state_publisher will work correctly (in my experience on ROS1, I haven't had any luck with this on ROS2 yet but it could be a different error that's blocking the robot_description itself). What compounds this issue in ROS2 is that it's much harder to troubleshoot and start the simulation for a new robot since everything relies on robot_state_publisher publishing the description to spawn the robot, but that can only be done once the joint_states are published (correct me if I'm wrong). This is intensified by the ongoing work in ros_control where it's tough to determine if the latest commit has broken things or if one is simply doing something wrong for the controllers or anywhere else in the chain (including the urdf definition, the launch file, etc). |
It's not that you need
There was a bug back in Dashing where the
Right, this is one of the things I wanted to support with having The idea here is to make it so that another entity in the system is the "owner" of the URDF, and |
i'm a bit late to the game here, but my group has had lots of troubles handling |
I thought about that when I originally implemented the topic, but the problem is that it isn't dynamic. If the description changes, then the downstreams have no way of knowing they have to fetch it again, unless I'd be interested to hear why you struggled with this, and why it matters "when" the client receives the robot description. Since the |
I'd say just on principle retrieving a required parameter should be done as a blocking call. Otherwise I have to use some sort of looping sleep for an arbitrary duration and hold up execution until the robot description callback has been hit. With a service you can spin until future complete to guarantee you get it or error out otherwise. Also can't you use the on_parameter_event call to add a callback when a parameter of a remote node changes? I think that should solve the problem; however, in my 10 or so years of doing this i've never seen the URDF change at runtime and I can certainly say i've never written any code myself that's capable of handling a runtime change to the URDF 😆 I know that's no reason to not support it though. Let me know what you think |
That's true. Though I'll mention that the spin_until_future complete is really just a convenience; you could do the same with a local promise/future that doesn't get set until the callback from the
Oh yeah, I guess that is true. You could do that instead.
I know for sure that there are use-cases out there where this is useful; just think of a manipulator changing an end-effector tool. That said, this isn't a feature for everyone; if you have a robot that never changes itself, this feature may not be useful to you. I'll also say that this is a bit of a chicken-and-egg problem, in that we've never had support for changing URDF in the core before, so this is the first (baby) steps towards that. |
Is this supported right now? Im developing modular robots and it would be a perfect fit to change the URDF on-line |
I would say that it is implemented in |
I don't think I've seen mentioned that there's often more information to "describe" a robot than just the URDF. Our applications typically also involved things like an SRDF for planning information and other various configuration data. Right now what usually happens is the application launch file "owns" everything by reading the input files and distributing them to whatever nodes need them via parameters. However, this is not dynamic, often ends up duplicating information, and can't easily scale to multiple robots. It would be very nice to have a dedicated node that was the source of truth for this information and then you could easily have a single node per robot with fully dynamic behavior. |
Right, that was actually one of the pieces of thinking behind this proposal initially. Instead of having robot_state_publisher be the source of truth for the URDF, have it be a consumer from some other entity. That entity, in turn, could easily have all of the "description" of the robot. That said, this kind of thing is probably very application-specific. I'm not sure how much we can reasonably generalize the concept, but if someone has time, it would be interesting to try to create a node that can do this. Someone would also need to take up this issue and create a PR for it (I don't think it will be particularly challenging, but we have to keep the existing functionality working as well so there is a bit of trickiness to doing it). |
I have been trying to change the URDF dinamically and i have found some problems. What i did was to launch robot_state_publisher with a URDF containing 2 links. If i try to add new links, it works correctly and the the topics /tf_static and /tf updates themself with the new URDF. The problem comes when you launch the robot_state_publisher with some links and try to remove some of them. The tfs still contains the links and joints that you removed when updating the URDF. Looks that removing the links is not fully suported yet |
I took a quick look at the robot_state_publisher code, and it seems to do the correct thing. When a new URDF comes in, it completely removes all internal knowledge of segments and mimic joints, then parses the URDF and rebuilds it. From then on out, it should only ever publish tf frames corresponding to those new joints. That said, there are several possibilities of what is going wrong in your testing:
I probably won't have time to debug this anytime soon, but that's the order in which I would debug things. If you have time to look at it, I'd be happy to review pull requests that fixes it. |
Than you for the quick response. The tfs that should be published has a correct timestamp but the ones that were removed from the URDF are beeing republished with the last time stamp calculated (before changing the URDF). |
OK, that's good to know. Are these old transforms being published on |
Yes, at least for the static ones, the transforms that were removed from the URDF are being published in |
Thanks for the testing. Here's the problem: https://github.com/ros2/geometry2/blob/f72c9d31a95b1863d7fd0fdbac77102b674f3317/tf2_ros/src/static_transform_broadcaster.cpp#L52-L72 . In particular, notice that all transforms in the incoming message are added to a class variable called I guess the thinking here is that all static transforms that are known by this node are published all at once, and no duplicates are sent. And that makes some sense with the current QoS being set to transient local with a depth of 1. There's two ways we could fix this:
The first option runs the risk of changing the semantics, since some programs may be relying on the "additive" behavior of So with all of that said, see ros2/geometry2#523 and #197 , which should fix this particular problem. Note that those PRs are still in draft, and will remain so until I get confirmation that they actually fix the issue. |
I don't know if this makes sense but a cleaner/filter that removes from the |
The issue is that for That said, another way we could do this would be to add a new method to |
I've run into a situation where I want to use robot_state_publisher to publish tf transforms for a robot description, but I also want to provide the robot description via code. I'd like to take SDFormat XML describing a robot in simulation and publish joint states from the simulation, but let robot_state_publisher handle turning those joint states into tf transforms.
Currently that means starting
robot_state_publisher
with command line arguments or a parameter yaml file set to that robot_description. I'd much rather publish the robot description myself and have an already running robot_state_publisher consume it from a topic.The text was updated successfully, but these errors were encountered: