From 03b041b120cc0ca2c5638578e88db5964fd4faa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Passault?= Date: Mon, 3 Jun 2024 11:59:41 +0200 Subject: [PATCH] Better documentation for kinematics loop closure --- docs/source/_static/img/opened_chain.png | Bin 0 -> 37113 bytes docs/source/design.rst | 13 +----- docs/source/index.rst | 1 + docs/source/kinematic_loops.rst | 55 +++++++++++++++++++++++ 4 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 docs/source/_static/img/opened_chain.png create mode 100644 docs/source/kinematic_loops.rst diff --git a/docs/source/_static/img/opened_chain.png b/docs/source/_static/img/opened_chain.png new file mode 100644 index 0000000000000000000000000000000000000000..abf02a5375f893432ae12c7e651b7845d18576e7 GIT binary patch literal 37113 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 R2Rab=nOwFsc&YCe|33yarJeu) literal 0 HcmV?d00001 diff --git a/docs/source/design.rst b/docs/source/design.rst index b197314..5e89355 100644 --- a/docs/source/design.rst +++ b/docs/source/design.rst @@ -56,18 +56,6 @@ frames on standard output. Here is a `link `_ of a document that can be used as a frame (note: the center cube is 5mm side, so you might need 2.5mm offset to center it). -Closing frames --------------- - -If your robot includes closing loop, those can't be handled in the URDF file directly since the robot has to have -a kinematics structure that is a tree. - -However, it is possible to add multiple frames, and to make constraints out of them during your simulation. - -If you add a relation with ``closing_something`` as name, two frames will be added to your URDF -(``closing_something_1`` and ``closing_something_2``) that will be attached to the two parts mated. -It's up to you to handle it further by adding proper constraints. - Joint frames ------------ @@ -77,3 +65,4 @@ Thus, they are always revolving around the z axis, or translating along the z ax .. image:: _static/img/zaxis.png :align: center + : diff --git a/docs/source/index.rst b/docs/source/index.rst index d60d526..648da12 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -21,5 +21,6 @@ to descriptions format like **URDF** or **SDF**, so that you can use them for ph installation commands design + kinematic_loops config pure-shapes diff --git a/docs/source/kinematic_loops.rst b/docs/source/kinematic_loops.rst new file mode 100644 index 0000000..a1e43e6 --- /dev/null +++ b/docs/source/kinematic_loops.rst @@ -0,0 +1,55 @@ +Handling kinematic loops +======================== + +Some robots have *kinematic loops*, meaning that the kinematic chain is not a tree but a graph. +Here is an example: + +Introduction +------- + +Here is a 2D planar robot with kinematic loop, we assume the two first joints to be actuated and the others to +be passive: + +.. raw:: html + +
+ +
+
+ + +Here, the two branches are connected together, thus this can't be represented as a tree. +URDF doesn't allow to directly represent this type of structure. We need to break it down in a tree, and enforce the +closing constraints in software during execution. +To enforce the constraints, frames can be placed at relevant positions, here is an example for the above robot: + +.. image:: _static/img/opened_chain.png + :width: 200px + :align: center + +Using onshape-to-obot +--------------------- + +The above mentionned example can be achieved by adding :ref:`frames `. However, this would require to +manually place two frames at each closing position. Onshape-to-robot comes with a more convenient way to achieve this, +by using mate connectors. + +If you add a relation with ``closing_something`` as name, two frames will be added to your URDF +(``closing_something_1`` and ``closing_something_2``) that will be attached to the two parts mated. + +This way, the closure is handled in onshape exactly the way it should appear in the final mechanism, and will result +in the two frames being placed at the correct position in the URDF. + +Here is the complete `Onshape assembly `_ for the above example robot. +The onshape-to-robot export is available `here `_. + +Handling constraints on execution time +-------------------------------------- + +Here are some ressources on how to handle kinematic loops in software: + +* In MuJoCo, you can add an `equality `_ constraint in your XML model. +* In `pyBullet `_, you can use `createConstraint` method to add the relevant constraint. +* In the `PlaCo `_ solver, you can create a `RelativePositionTask`. See the `kinematics loop documentation section `_ for more details. Some examples created with onshape-to-robot can be found in the `example gallery `_.