JuliaRobotics / MeshCatMechanisms.jl

3D Visualization of mechanisms and URDFs using MeshCat.jl and RigidBodyDynamics.jl
Other
40 stars 9 forks source link

Better documentation #15

Closed han-so1omon closed 6 years ago

han-so1omon commented 6 years ago

It is unclear from the demo and code comments how to manipulate an arbitrary robot model. I have a single body, single joint (base to world) model loaded. My intent is to run a dynamics model in a networked server and use MeshCatMechanisms as a display. My goal is simply to load the model and then apply arbitrary transforms onto it as the display refreshes. The demos work fine, so that is not the issue.

When it comes to setting up the model, it is unclear how to do things like: set origin at center of display, set model transformations. It is also unclear what variables are involved in set_configuration!() function. It seems like the mechanism visualizer, the joints, and some transform parameter are the inputs. However, it is not clear what the transform parameter is. The third parameter is a list of Float64 numbers corresponding to joints. I can't think of a transform that can be fully described by a single number, though.

After digging, it seems like the key may be in the RigidBodyDynamics package, but it has taken a long time to figure this out.

Apologies if this response is unorganized, but I am a bit rushed to write this and am still quite confused in how a robot can be arbitrarily assigned a transformation. Perhaps adding documentation for just this will be of use to others as well. My current attempt is shown below:

` homog(t::Translation) = homog(AffineMap(eye(3),t.v))

vis = Visualizer() urdf = joinpath(pwd(), "resources", "quadrotor.urdf")

urdf = joinpath(pwd(), "resources", "Acrobot.urdf")

robot = parse_urdf(Float64, urdf) delete!(vis) mvis = MechanismVisualizer(robot, URDFVisuals(urdf), vis) body = bodies(robot)[end] body_frame = default_frame(body) setelement!(mvis,body_frame) at = homog(Translation(0,0,-1)) set_configuration!(mvis, findjoint(mvis.state.mechanism, "base_link_to_world"), [1.0])

open(vis) ` Edit: Above example fails with: ERROR: LoadError: BoundsError: attempt to access 0-element SubArray{Float64,1,Array{Float64,1},Tuple{UnitRange{Int64}},true} at index [Base.OneTo(1)]

rdeits commented 6 years ago

You are correct that RigidBodyDynamics.jl is the key here, as all of the logic for kinematics and dynamics is entirely handled in that package.

set_configuration!(vis, args...) does exactly two things:

  1. It forwards your arguments to set_configuration!(state, args...) where state is the RigidBodyDynamics.MechanismState holding the state of the mechanism in the visualizer.
  2. It uses that MechanismState to update the rendered positions of all the bodies

To see the possible arguments to set_configuration!(state, ...), you can see the RigidBodyDynamics docs here: http://www.juliarobotics.org/RigidBodyDynamics.jl/stable/mechanismstate.html#RigidBodyDynamics.set_configuration!-Tuple{RigidBodyDynamics.MechanismState,AbstractArray{T,1}%20where%20T}

The simplest way to set the configuration is simply set_configuration!(vis, q) where q is a vector of the generalized joint positions for whatever your robot happens to be. For the Acrobot model, q is just a 2-element vector of joint angles.

Note that the key here is that set_configuration!() is used to set the generalized coordinates of the mechanism itself. That is, only the <joint> tags in the URDF. If you want to just move the visualizer around in a way that isn't supported by the actual robot's joints, then you need the lower-level settransform!() from MeshCat.jl.

For example, to move the whole visualizer:

using MeshCat: Visualizer, settransform!
using CoordinateTransformations: Translation
using MeshCatMechanisms: MechanismVisualizer, URDFVisuals

vis = Visualizer()
# move the root of the visualizer around
settransform!(vis, Translation(0., 0, 1))

# Add the mechanism visualizer below the root, at the path `/mechanism`. 
mvis = MechanismVisualizer(robot, URDFVisuals(urdf), vis[:mechanism])

does that help?

han-so1omon commented 6 years ago

That is helpful, thank you. Currently my robot rotates about some point not on the body and it is unclear how to get it to rotate about the centroid.

The biggest issue is that there is little to no documentation for basic things with respect to using URDF robots. I think it will be useful to have documentation for the following questions.

Where is the centroid of my robot in the body? What does a fixed link mean? How to set a rotation/translation origin? How to fit camera to show robot in center? What is visualizer? It seems to be the whole model, but that is not clear. I initially took it to mean the camera is the visualizer. What is a mechanism visualizer? I guess the URDF model has multiple visual tags and joints between them. Perhaps mechanism visualizer is best described as the visualization of a joint and corresponding links.

I am willing to help with some of this but I don't have enough knowledge of the MeshCat/URDF system yet.

rdeits commented 6 years ago

Where is the centroid of my robot in the body? What does a fixed link mean? How to set a rotation/translation origin?

These are actually specific to RigidBodyDynamics.jl, so I'd suggest first familiarizing yourself with the documentation here: http://www.juliarobotics.org/RigidBodyDynamics.jl/stable/ and the example notebooks here: https://github.com/JuliaRobotics/RigidBodyDynamics.jl/tree/master/notebooks (the "Quickstart" may be particularly useful). A fixed joint corresponds to a <joint type="fixed"> in a URDF and represents a connection between two bodies that cannot move. I'm not sure about the answers to the other two questions, but if the RigidBodyDynamics.jl docs don't help you can try asking over there.

How to fit camera to show robot in center?

There's currently no way to do that automatically. You can either move the robot itself (using the method I posted above) or move the camera to a specific location, as in https://github.com/rdeits/MeshCat.jl/blob/master/animation.ipynb

What is visualizer? It seems to be the whole model, but that is not clear. I initially took it to mean the camera is the visualizer.

Visualizer is the primary type used by MeshCat.jl to store an entire 3D scene. The Visualizer itself knows nothing about your robot mechanism: everything it deals with is just a tree of arbitrary geometries connected with arbitrary transforms.

MechanismVisualizer wraps the Visualizer type in order to provide helpful additional methods, like setting the configuration of the entire scene just from the joint angles of your robot. So a MechanismVisualizer is a Visualizer associated with a particular RigidBodyDynamics.Mechanism.

I am willing to help with some of this but I don't have enough knowledge of the MeshCat/URDF system yet.

Yes please! You are totally right that the documentation is lacking here (I've mostly written this package for my own use and haven't given a ton of thought to the new-user experience). I would be very grateful for any PRs you feel like opening.

han-so1omon commented 6 years ago

Thanks. I'm closing this issue. I forked the repo. If I am able to add anything I will submit a PR.

rdeits commented 6 years ago

:+1: and please let me know if there are other things that are confusing or difficult. This package is very new and I'm sure that there's a lot that can be improved in the API or docs.