Skip to content
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

Joint default values need to be stored in Joint #13065

Open
joemasterjohn opened this issue Apr 15, 2020 · 31 comments
Open

Joint default values need to be stored in Joint #13065

joemasterjohn opened this issue Apr 15, 2020 · 31 comments
Assignees

Comments

@joemasterjohn
Copy link
Contributor

I'm working on parsing the <joint><axis><initial_position> tag to set the default angle for a RevoluteJoint and a PrismaticJoint in multibody/parsing/detail_sdf_parser.cc. Here is my branch (currently only parsing RevoluteJoint):

https://github.com/joemasterjohn/drake/tree/parsing_joint_initial_position

Right now RevoluteJoint and PrismaticJoint are deferring ownership of the their default positions (RevoluteJoint::set_default_angle() and PrismaticJoint::set_default_translation() respectively) to their Mobilizer. This disallows setting the initial position prior to the parent MultibodyTree being finalized because of a precondition in get_mutable_mobilizer(). I believe the default position should live in the Joint class. Thoughts?

@joemasterjohn
Copy link
Contributor Author

\cc @amcastro-tri

@joemasterjohn joemasterjohn self-assigned this Apr 15, 2020
@sherm1
Copy link
Member

sherm1 commented Apr 15, 2020

I agree, @joemasterjohn. All the parsing info ought to reside in the Joint so we can create and destroy the mobilizer graph as an afterthought.

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 15, 2020

BTW This isn't our policy per se, but I do like to title issues that make it obvious they're an issue, not a PR (e.g. "Joint default values need to be deferred to mobilizer" or "Should make [...]").

@joemasterjohn joemasterjohn changed the title Joint default value deferred to Mobilizer Joint default values need to be stored in Joint Apr 20, 2020
@EricCousineau-TRI
Copy link
Contributor

As @jwnimmer-tri pointed out, my commented here may make this issue moot:
#13105 (comment)

Can you edit this to remove the reference to initial_position? It will be deprecated when SDFormat 1.8 comes out:
https://github.com/osrf/sdformat/blame/master/Changelog.md#L13
@scpeters, @azeey, and I discussed it (offline, unfortunately), and feel that is redundant to storing some level of state (e.g. in some sort of //state tag).

For more info, see PR link in changelog.

Sorry for not reading this more fully!

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 20, 2020

FTR, it was deprecated as it was (a) redundant w.r.t. //world/state and (b) not used at all in Gazebo (or maybe anything else?).

Here is the spec for //world/state in SDFormat 1.7:
http://sdformat.org/spec?ver=1.7&elem=state

Perhaps you can instruct detail_sdf_parser.cc how to recognize this and parse a subset (e.g. /state/model/joint/angle), but it may not be uber straightforward - also, it does not look like spec is super straightforward (e.g. only angle, even for prismatic or multi-DoF joints? it may be tailored only for maximal coordiantes, not minimal coordiantes?).

FYI @scpeters @azeey

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 20, 2020

Basically, I think this issue should maybe be reworded to "Should teach SDFormat parser to read //world/state". (and state should ideally not be coupled to a given model?)

@sherm1
Copy link
Member

sherm1 commented Apr 20, 2020

//world/state looks like a mechanism for recording a trajectory -- that doesn't seem to cover the same territory as setting the default value for a joint's coordinates. (For example it wants simulation and real time stamps in nanoseconds!) It also records output values like acceleration which are not state at all, but rather simulation results.

initial_position seems orthogonal to //world/state. Can you explain why you think the latter is sufficient?

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 21, 2020

I don't see anything in it that looks like it records a trajectory. It just asks for time as the state.

And FTR I'm not necessarily saying all of //world/state is best suited for our needs (e.g. maximal coordinates, non-state things like acceleration, real time), but I like the general intent - to record the state of the world, rather than try and couple it into a model's definition (not instantiation) like you would (but shouldn't?) do with //model/joint/axis/initial_position.

We can always take a subset of the element that works best for us, and then work on refining that element with OSRC (e.g. make quantities coupled to dynamics engines be tagged as such).

@sherm1
Copy link
Member

sherm1 commented Apr 21, 2020

See my comment in #13105. I do think the model definition should include initial_position when that is a property of the model rather than just an arbitrary setting. That occurs much more often with closed topology systems than with tree-structured ones.

@EricCousineau-TRI
Copy link
Contributor

@sherm1 I'm all for abstracting away the zero configuration such that q==0. makes physical sense.
However, to me that seems to be a separate item from specifying a initial configuration (e.g. q_0 which may not be 0 when you initialize the state).

Which are y'all advocating for the most?

To me, zero configuration may need set_my_magical_bias_thinger (but I am completely on board with specifying this at the model level), whereas initial configuration is in line with reaching SetDefaultState (but I'm not a fan as I feel that it may be an abuse of definition and redundant w.r.t. something global like //world/state).

BTW Is this the real root motivation for this issue? If so, would be super nice to have that stated in the overview!

@sherm1
Copy link
Member

sherm1 commented Apr 21, 2020

Is this the real root motivation for this issue?

I'm not sure which of things above you're referring to? My motivation would be to associate a reasonable non-zero default value for a joint's coordinates if that makes sense for the model (as opposed to just something application dependent). So SetDefaultState() would not necessarily set all the joint coords to zero. An app can always override that, the point is to have a reasonable default, and zero is not always reasonable. For closed topology systems, zero is often the "flatline" configuration from which it is nearly impossible to compute an assembled configuration.

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 21, 2020

Ah, I see. Yes, if the default value is explicitly intended to be for the aspect of a model, and not be confused with trying to capture the model's state, then yeah, I guess I can see this purpose.
I was initially thrown off by the mention of initial_position, which is a rather ambiguous name, and seems redundant w.r.t. //world/state.

My suggestion is to make this Drake-specific for now; do not use SDFormat's effectively unsupported (and soon-to-be-deprecated) //joint/axis/initial_position. Instead, define <drake:default_value/> (or whatever is more appropriately named for the joint).

I'm not sure which of things above you're referring to?

I was referring to the intended application of using the default value for use with closed-loop topologies. At first, since the intent was to use initial_position, I was not sure if it was an attempt to set initial conditions for a simulation (I very much want to make sure that this is not what the property is used for!).

@sherm1
Copy link
Member

sherm1 commented Apr 21, 2020

Gotcha, yes that makes sense. drake::default_position or something like that would be a better name.

@amcastro-tri
Copy link
Contributor

This is a great discussion, thank you guys @sherm1 and @EricCousineau-TRI.
What about something like this? which would allow in the future to also specify velocities without having to deprecate parsing tags.

<joint name = ....>
<drake:default_state>
  <!--As many entries as dofs per joint. -->
  <drake:position> 1.0 2.0 </drake:position>
  <drake:velocity> 1.0 2.0 </drake:velocity> <!-- For some future. -->
</drake:default_state>
</joint>

@joemasterjohn
Copy link
Contributor Author

Yes, thanks @sherm1, @EricCousineau-TRI and @amcastro-tri . Sorry I'm late to the party and didn't make it clear that the intention for parsing the <initial_position> tag was to store a default configuration of a closed-loop topology where the zero configuration doesn't make much sense.

I'll try to make the issue and related PR(#13105) agnostic to the particular tag the parser would actually use.

@EricCousineau-TRI
Copy link
Contributor

@joemasterjohn Sweet! That sounds great!

@amcastro-tri Er, can you explain more we why we'd want a non-zero default velocity?
Non-zero default position makes sense in light of Sherm's explanation, but I'm not yet onboard with a non-zero default velocity - it sounds like it's creeping towards initial conditions, not accommodating model-specific attributes.

@amcastro-tri
Copy link
Contributor

That's actually a good point @EricCousineau-TRI. I was trying to avoid some future deprecation. What do you think @sherm1 ?

@sherm1
Copy link
Member

sherm1 commented Apr 21, 2020

Yes, I was going to make the same point but @EricCousineau-TRI beat me to it. A recommended initial configuration makes sense as part of the modeler's work, but a non-zero initial velocity would be up to the particular application using that model.

@amcastro-tri
Copy link
Contributor

ok, thanks for the clarification (sry for the close/open spam, github crushed on me this morning and I followed up by pressing the wrong buttons).

Then we'd like something like?:

<joint name = ....>
<drake:default_position> 1.0 2.0 </drake:default_position>
</joint>

@jwnimmer-tri
Copy link
Collaborator

If we agree that it's semantically valid for the xml to store a non-zero default position per the modeler, then I'm unclear on why http://sdformat.org/spec?ver=1.7&elem=joint#axis_initial_position is going to be deprecated, @EricCousineau-TRI? Can we just use the standard element and undo the deprecation? Or do we really want to highlight "initial" vs "default" somehow being different?

@EricCousineau-TRI
Copy link
Contributor

I would like to converge on terminology that makes the purpose clear, so yes, I want to keep the deprecation.

@EricCousineau-TRI
Copy link
Contributor

That being said, I will still discuss with @scpeters and @azeey on Thursday to see what they think.

@EricCousineau-TRI
Copy link
Contributor

EricCousineau-TRI commented Apr 21, 2020

On @amcastro-tri's point, I don't have a concrete suggestion on the syntax. From reviewing the current docs, we don't have long-form example of what multi-axis joints look like:
http://sdformat.org/tutorials?tut=spec_model_kinematics&cat=specification&#joint

So will have that in the Thurs meeting. @amcastro-tri @joemasterjohn Would y'all (or one of you) want to join the meeting to discuss this?

@joemasterjohn
Copy link
Contributor Author

@EricCousineau-TRI sure thing, you can go ahead and invite me.

@EricCousineau-TRI
Copy link
Contributor

Done!

@RobotLocomotion RobotLocomotion deleted a comment from amcastro-tri Apr 21, 2020
sammy-tri pushed a commit that referenced this issue Apr 27, 2020
This is a PR to have the Joint class store a default value and to pass the value to its mobilizer implementation upon construction of the joint implementation.

Solves the issue of mobilizers storing default joint positions (#13065)
@sherm1 sherm1 added the component: multibody plant MultibodyPlant and supporting code label May 11, 2020
@RussTedrake
Copy link
Contributor

Seems like this could have been closed via #13105?

@RussTedrake
Copy link
Contributor

Or perhaps the issue has taken on more meaning that the issue name suggests, and should be renamed to "set default joint positions via sdf" or something more up to date?

RussTedrake added a commit to RussTedrake/drake that referenced this issue Aug 31, 2022
…ives

Adds the ability to set default joint positions and default free body
poses in the add_model directive. I would have liked to be able to
enable a tag like default_positions which takes a vector, but the
position vector is not defined until after Finalize(), so it
unavailable at parsing time.

Related to RobotLocomotion#13065, and this slack discussion:
https://drakedevelopers.slack.com/archives/C2WBPQDB7/p1601749507024400
RussTedrake added a commit to RussTedrake/drake that referenced this issue Aug 31, 2022
…ives

Adds the ability to set default joint positions and default free body
poses in the add_model directive. I would have liked to be able to
enable a tag like default_positions which takes a vector, but the
position vector is not defined until after Finalize(), so it
unavailable at parsing time.

Related to RobotLocomotion#13065, and this slack discussion:
https://drakedevelopers.slack.com/archives/C2WBPQDB7/p1601749507024400
sherm1 pushed a commit that referenced this issue Aug 31, 2022
…ives (#17802)

* [multibody/parsing] Add support for default positions in model directives

Adds the ability to set default joint positions and default free body
poses in the add_model directive. I would have liked to be able to
enable a tag like default_positions which takes a vector, but the
position vector is not defined until after Finalize(), so it
unavailable at parsing time.

Related to #13065, and this slack discussion:
https://drakedevelopers.slack.com/archives/C2WBPQDB7/p1601749507024400
@RussTedrake
Copy link
Contributor

@joemasterjohn -- can you update or close this issue (per my comment just above)?

@jwnimmer-tri
Copy link
Collaborator

The discussions around #15948 are somewhat related here. Now that model directives can specify default joint positions as of #17802, we will eventually need Drake's SDFormat parser to reach feature parity on that front so that our DMD->SDF conversion tool has a way to convert that spelling.

As such, we'll need some XML tag in our SDFormat parser for the initial joint position. That could be a custom tag like <drake:default_position> as discussed above, but ideally I would rather have us advocate for an upstream SDFormat-specified tag in this case, since this is an important feature that is not otherwise expressible in stock SDFormat -- in other words, this is not merely sugar.

If that process it too slow, we can start with the drake-custom tag for now, but I doesn't seem like it should be difficult to do it correctly from the get-go.

@jwnimmer-tri
Copy link
Collaborator

I would like to converge on terminology that makes the purpose clear, so yes, I want to keep the deprecation.

I think we need to get out in front of this. I assume it will take a little while to adjust SDFormat, prior to Drake being able to use the new spelling.

SDFormat needs a spec upgrade that defines your new preferred spelling (e.g., default_position), and ideally its 1_N.convert automatic converter recipe should respell initial_position to default_position automatically for people (when their file identifies as an earlier sdformat version where initial_position was available).

Is there a tracking issue (feature request) anywhere on the SDFormat side yet? I was not able to find one.

@jwnimmer-tri
Copy link
Collaborator

See also related discussion in #19230.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants