Original issue is at ros2#33. Here's the thread:
jacobperron:
The ROS 1 version uses a parameter to read the robot description. The ROS 2 version reads the description from a file, with the path provided as a command line argument. Two questions:
-
What was the reason for this change? I guess it was related to parameters not being available in ROS 2 at the time.
-
Are there plans to switch back to using a parameter?
I ask because this has impact for users porting launch scripts from ROS 1. For example, (I think) typical usage with xacro in a launch file would look something like this:
<launch>
<param name="robot_description" command="$(find xacro)/xacro '$(find foo_description)/urdf/foo.urdf.xacro'" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
</launch>
Translating this file into a ROS 2 launch script, I would expect it to look like:
<launch>
<node name="robot_state_publisher" pkg="robot_state_publisher" exec="robot_state_publisher">
<param name="robot_description" cmd="$(exec-in-pkg xacro xacro) '$(find-pkg-share foo_description)/urdf/foo.urdf.xacro'" />
</node>
</launch>
Ignoring the fact that xacro
isn't ported to ROS 2 yet and the cmd
attribute isn't a valid attribute for the <param>
tag (but it should be I think), I expect many people will run into the challenge of updating launch files similar to this example.
Is there an alternative workflow you imagine?
clalancette:
1. What was the reason for this change? I guess it was related to parameters not being available in ROS 2 at the time.
@Karsten1987 Did the initial port here. I'm guessing that the current state is because there were no parameters at the time, but I'm not sure.
2. Are there plans to switch back to using a parameter?
Personally, I'm on the fence with it. I sort of think of parameters as "optional" things you might configure on a node. In this case, the description is really core to what robot_state_publisher
does, so it kind of makes sense that you have to provide it as a command-line parameter at startup time. There is another argument here that you may want to launch robot_state_publisher
without any description and then provide one later (this is sort of the base case of having the description be dynamic at runtime). But I would argue that you still don't want to use a parameter, since it is somewhat hard to notify all downstream users of changes. You can do it via the /parameter_events
topic, but then you have to filter out all of the non-robot-description
updates in your downstream subscriber callbacks, or use a namespace. It seems to be simpler to just have a topic and a service on robot_state_publisher
; current_description
(latched), and set_description
. That way it is easy to update all of the downstream consumers.
All of that being said, these are just some thoughts floating around my head, and I haven't really run them by anyone yet. So there may be significant downsides to doing something like that. Let me ask a different question: other than the porting effort, do you see a significant problem with the current state of affairs?
sloretz:
- Are there plans to switch back to using a parameter?
A parameter is only on one node, but multiple nodes may need it (ex: MoveIt RobotModel()
needs a URDF). I think this is why robot_state_publisher
publishes a "latched" robot_description
topic. I don't think there are plans to change, but a good option may be to make robot_state_publisher
a consumer of the robot_description
topic published by a brand new robot_description_publisher
. That would enable someone to load descriptions from someplace other than the filesystem by replacing robot_description_publisher
without needing to reimplement robot_state_publisher
too. It would also make it easier to enable robot_state_publisher
to handle changing robot descriptions, since it would have to do something when it received a message.
jacobperron:
Don't get me wrong, I think current latched publisher makes sense. What I think is awkward with the current implementation is that we have to start robot_state_publisher
by loading a URDF from a file. It would be better, IMO, to read a URDF as a string (like in ROS 1), or support both options.
The issue with the current state of affairs is that I can't run a tool like xacro (which can output URDF as a string) and pass it to robot_state_publisher. E.g.
ros2 run robot_state_publisher robot_state_publisher $(xacro /path/to/my/model.urdf)
It requires a two step process, first write the output of xacro to a file and then pass it to robot_state_publisher. I don't have a strong opinion on if we use a parameter (like in ROS 1) or a regular CLI arg to pass the URDF as a string, but it seems like a valid use-case to me.
clalancette:
I see the problem, and yeah, that sucks.
But I don't think a parameter is the solution. I discussed this with @IanTheEngineer, and we came up with a different solution. What if we instead allowed -
as the filename, and then took the URDF from stdin? That would be more Linux-y, solve this particular problem, and be relatively easy to implement (there is a slight concern about this working on Windows, but I think we can figure something out). We'd also probably want to add some launch support syntax for it, though that can come later. Thoughts?
jacobperron:
What if we instead allowed - as the filename, and then took the URDF from stdin?
Sounds fine to me.
karsten1987:
a bit late here, but yes. The initial plan was to load the urdf content as a parameter, but as the functionality wasn't there at the time, the only workaround I've seen was to load it from file.
There is a respective PR for rviz which then displays the robot model from that parameter.
@clalancette What's the problem with the parameter? I think in Dashing we can set the parameter e.g. via a launch file which would reflect pretty much the behavior ROS1 does. Does it not? That would then even rule out things as cross platform, because all xacro
has to do is output the final urdf content.
clalancette:
@clalancette What's the problem with the parameter? I think in Dashing we can set the parameter e.g. via a launch file which would reflect pretty much the behavior ROS1 does. Does it not? That would then even rule out things as cross platform, because all xacro
has to do is output the final urdf content.
We can do that, but I'm questioning whether we should. In particular, see my comments in ros2#33 (comment) ; I think we should be moving more to a world where the URDF can be dynamically changed, and I think that is easier with a topic than with a parameter.
jacobperron:
I think we should be moving more to a world where the URDF can be dynamically changed, and I think that is easier with a topic than with a parameter.
To be fair, parameters are dynamically reconfigurable π
clalancette:
To be fair, parameters are dynamically reconfigurable grin
They are, but it is much more cumbersome to get notified of it. Yes, you can subscribe to /parameter_events
, but then you have to filter parameter updates from the rest of the system. You could put it in a namespace to workaround that, but it just seems easier as a topic.
I also go back to my earlier statement that it just doesn't seem like the correct semantics for a parameter. It is integral to how robot_state_publisher
works, not something optional/default, so it seems more like it belongs as a command-line/topic, rather than a parameter. But I'll admit this is subjective.
jacobperron:
Maybe we're talking about two different things.
Correct me if I'm wrong, but I thought the flow of data is:
URDF loaded by -> robot_state_publisher
-> publishes description on a topic
Those who want to be notified of description changes can subscribe to the published topic. But, I'm concerned with how robot_state_publisher
is loading it. In fact, I don't think the description can be updated dynamically with the current implementation. Using a parameter would give us that for free.
clalancette:
Maybe we're talking about two different things.
Correct me if I'm wrong, but I thought the flow of data is:
I'm sort of conflating them, sorry.
URDF loaded by -> robot_state_publisher
-> publishes description on a topic
Right, that's the current situation.
Those who want to be notified of description changes can subscribe to the published topic. But, I'm concerned with how robot_state_publisher
is loading it. In fact, I don't think the description can be updated dynamically with the current implementation. Using a parameter would give us that for free.
Having the URDF is central to what robot_state_publisher
does, so I think that passing it on the command-line makes sense (that is, it is a required component). Making it a parameter is convenient, but it also seems like a misuse of the semantics of parameters. You are right that it is currently not possible to update the URDF, but my earlier proposal was to add a service that allowed you to do so.
mogumbo:
I'm one of the users Jacob was originally talking about. The trouble I see with the current state of affairs: writing xacro results to a file and then loading them is awkward and extra effort, robot_state_publisher publishes an empty /robot_description topic, and I can't figure out any syntax for feeding xacro results to robot_state_publisher in an XML launch file.
Having dynamic robot descriptions sounds great, but it also sounds like a huge can of worms. I currently only need static robot descriptions and would love to have easy solutions for spawning robots in both python and XML right away. My current solution is to save xacro results to a temporary file and pass the filename to spawn_entity.py. XML isn't an option for me yet.
clalancette:
I'm one of the users Jacob was originally talking about. The trouble I see with the current state of affairs: writing xacro results to a file and then loading them is awkward and extra effort,
Agreed. My proposal of using the stdin trick for the file would allow you to pipe the results from xacro directly into robot_state_publisher.
robot_state_publisher publishes an empty /robot_description topic
That shouldn't be. It will currently only publish once it has gotten its first update; are you sure that is happening?
and I can't figure out any syntax for feeding xacro results to robot_state_publisher in an XML launch file.
I think we'd be able to do something with the XML launch file and the stdin trick, but I'll have to check on that.
Having dynamic robot descriptions sounds great, but it also sounds like a huge can of worms. I currently only need static robot descriptions and would love to have easy solutions for spawning robots in both python and XML right away.
Sure, but it is a huge can of worms that we have been kicking down the road for years. I'm not saying that I want to solve the dynamic problem today, but I do want to make it so that the solution we start here at least allows a little more dynamicity. I also want to make sure that we are using features as they are semantically intended, and it is not clear to me that the description as a parameter is that.
mogumbo:
I don't know what kind of update robot_state_publisher is expecting. I see that it subscribes to /joint_states, but no information will be generated on that topic until after the robot is spawned and libgazebo_ros_joint_state_publisher.so starts publishing.
Anyway, the particulars of this problem are a bit out of scope for this thread. Maybe I should take it elsewhere.