ros-controls / ros2_control

Generic and simple controls framework for ROS 2
https://control.ros.org
Apache License 2.0
507 stars 301 forks source link

Acceleration Limits from URDF #340

Open destogl opened 3 years ago

destogl commented 3 years ago

Currently, the URDF defines the only position, velocity, and effort limits for each joint. What if one would like to have acceleration limits too? This is especially interesting for industrial scenarios where no effort measurements are provided and where no knowledge about tools and object's mass is unknown.

How are you defining these limits?

@bmagyar @Karsten1987 @v-lopez @olivier-stasse

gavanderhoorn commented 3 years ago

MoveIt's joint_limits.yaml? The same file structure is supported by ros_control's joint_limits_interface.

AndyZe commented 3 years ago

^Playing devil's advocate, what if you aren't using MoveIt? Maybe it's a mobile robot base, not an arm.

To me, it's weird that pos/vel/effort are in the URDF but not acceleration. I think jerk might as well be added, too, to make it future proof.

gavanderhoorn commented 3 years ago

^Playing devil's advocate, what if you aren't using MoveIt? Maybe it's a mobile robot base, not an arm.

the file is not MoveIt specific. It just happens to use the same structure as the one used by MoveIt.

(the link is also to the ros_control wiki, not to anything connected to MoveIt)

olivier-stasse commented 3 years ago

We broke several times our robot by having limits spread around in several places. I believe that such important data should be as much as possible at the source: the URDF description.

gavanderhoorn commented 3 years ago

The nice thing about separate files is that it inherently supports loading overrides from application-specific packages.

And this happens a lot.

If everything is part of the urdf, there is no other way to do that but forking and branching.

olivier-stasse commented 3 years ago

Why not modifying robot_description such that the acceleration field is inside the urdf when loading the file ?

Then each package providing a robot for ros2-control could add this information without having a different way of providing the parameter.

Each ros2 controller would knew where to find to the information.

We could have the best of both world ?

gavanderhoorn commented 3 years ago

Why not modifying robot_description such that the acceleration field is inside the urdf when loading the file ?

I'm not aware of any work in the direction of runtime modifiable URDFs -- which seems to be what you're suggesting.

How would you guarantee all consumers are aware of the changes?

olivier-stasse commented 3 years ago

How would you guarantee all consumers are aware of the changes?

Even more simpler if you need to change the URDF to have the ros2-control tags in the URDF file, I would suggest to modify the URDF at this time.

Then the consumer would be aware.

olivier-stasse commented 3 years ago

And no runtime modification of the URDF.

gavanderhoorn commented 3 years ago

How would you guarantee all consumers are aware of the changes?

Even more simpler if you need to change the URDF to have the ros2-control tags in the URDF file, I would suggest to modify the URDF at this time.

so then managing application-specific configurations -- or even temporary overrides of limits -- would require duplication of the urdf, correct?


Edit: what I'm trying to say is: if data which has a high probability of needing/seeing changes in application scenarios (ie: things like limits) gets stored in the same file as something which is relatively rigid (ie: kinematic structure, appearance, etc), you make it harder to reuse the static parts. Instead of being able to install a description package from upstream and then overlaying changes to limits based on application requirements, you'll need to duplicate the upstream artefact and then make the changes there.

There are of course more concerns here -- such as the one raised in https://github.com/ros-controls/ros2_control/issues/340#issuecomment-795897463 -- but just putting everything into the URDF is not necessarily the most efficient way.

olivier-stasse commented 3 years ago

There are of course more concerns here -- such as the one raised in #340 (comment) -- but just putting everything into the URDF is not necessarily the most efficient way.

Agree, IMHO for this specific information the best source of information is the robot manufacturer. Thus it seems strange to have it located somewhere else than the URDF.

gavanderhoorn commented 3 years ago

I believe we're misunderstanding each other.

I'm specifically talking about overriding the (default) limits for application-specific scenarios.

How would the OEM know what those limits should be?

olivier-stasse commented 3 years ago

I believe we're misunderstanding each other.

I'm specifically talking about overriding the (default) limits for application-specific scenarios.

How would the OEM know what those limits should be?

Ah yes sorry. Good question. In practice for the robot we do ourselves the limit are part of the command interface. It could also be part of the state interface depending on the control mode or the environment (such as the temperature) to be read by the controllers.

gavanderhoorn commented 3 years ago

That's all good if you're in control of the total robot, or it's a custom machine that you're writing a driver for.

I'm thinking about COTS robots used in (industrial) work cells.

In practice for the robot we do ourselves the limit are part of the command interface.

and how does the command interface know what the limits should be?

olivier-stasse commented 3 years ago

That's all good if you're in control of the total robot, or it's a custom machine that you're writing a driver for.

I'm thinking about COTS robots used in (industrial) work cells.

If your COTS robots is allowing you to change such limit on-line, having it in the control interface seems to be a good choice.

In practice for the robot we do ourselves the limit are part of the command interface.

and how does the command interface know what the limits should be?

A trajectory optimizer (TrajOpt for instance) should give you a motion that meet the maximum limit provided by the URDF. To be safe you can then ask the closed source industrial controller to follow the trajectory with the max speed being 5 percent above or below the planned trajectory and send it online through the control interface.


EDIT all of this is about acceleration for joint, which was I believe is the main topic. Other limits have a different meaning and of course this would not be relevant.

gavanderhoorn commented 3 years ago

There must be some lost-in-translation happening here. This is my last comment on this matter.

The discussion here started with @destogl asking what a good place would be for limits other than the ones currently supported by the joint element in URDFs.

The two options mentioned so far are:

  1. placing them in the urdf -- regardless of whether the spec supports it (I believe, this is my interpretation)
  2. using an external file

I offered the input that separate files make it easier to store application-specific configuration data (ie: work cell limits or similar) in separate packages without having to change the upstream package. This separates responsibilities, namely static structure vs (dynamics) limits and similar data.

What I don't understand is how placing things in control interfaces or state interfaces changes the fact you'll still need to store the limits somewhere. Regardless of whether limits are changed on-line or not, the data needs to come from somewhere.

AndyZe commented 3 years ago

@gavanderhoorn makes a good point. An external yaml file (joint_limits.yaml) is an easy way to define lower limits than the URDF.

An external yaml is also the "path of least resistance." It requires no change from MoveIt and it doesn't require ros2_control to re-parse the URDF. And no change to the URDF standard.

I think if both MoveIt and ros2_control standardize on joint_limits.yaml, it would become a good standard.

It is not so easy to modify the URDF from an industrial robot_description package. Generally that would require forking the robot description package. Nobody likes to do that.

So, I think @gavanderhoorn has changed my mind, we should use joint_limits.yaml

v-lopez commented 3 years ago

A small note, In ROS2 I believe the standard is to publish robot_description as a topic, instead of as a ROS param. So handling changes to the URDF dynamically would be pretty straightforward with a Subscriber.

But the question of how would you have this modified URDF with limits per application is something else. One solution that we use for something similar, is for the xacro file that generates the URDF to accepts a file defining some alternate limits or offsets. In our case calibration offsets resulting from eye hand calibration.

For instance the tiago_description takes as an input, a directory (if undefined, uses the directory with the default configuration)

After calibration, our robots provide a new directory with the proper offsets, so he URDF is modified accordingly.

So, if the original URDF allows such configuration, it makes sense that all the joint information resides in the same place. And everyone who handles the URDF doesn't have to be modified to take into account joint_limits.yaml or any other file.

destogl commented 3 years ago

Thank you all for the lively discussion with exciting ideas. In the following, I try to wrap the discussion up and propose an approach with corresponding TODOs (and priorities). As an additional reference, I consulted joint_limits_interface wiki page in ROS1.

  1. The primary storage for the limits should be URDF (xacro) file provided by the manufacturer or ROS integrator.
    • [ ] extend URDF limits syntax with acceleration and jerk limits (Medium)
  2. We encourage authors of URDF-files to use parameterized limits as done for UR and Tiago robots.
    • [ ] Example in ros-controls/ros2_control_demos with loadable limits from a file in URDF/xacro (Medium)
  3. Use the joint_limits.yaml file as the override of URDF-limits (as done in ROS1)
    • [ ] Make compatible implementation as in ROS1 (High)
    • [ ] Write documentation in ros-controls/control.ros.org repo (High)

I hope these few points address all of the concerns. And now I am going to tackle those High-priority TODOs.