Search Unity

How to set initial configurable joint rotations?

Discussion in 'ML-Agents' started by Omelette_au_Goulage, Dec 9, 2020.

  1. Omelette_au_Goulage

    Omelette_au_Goulage

    Joined:
    Jun 9, 2020
    Posts:
    14
    I am using ml agents to teach a humanoid robot to imitate an animation. For example I have an animation of a backflip and the agent has a reward function that tries to match the positions of joints to that of the animation (kinda like the DeepMimic article). So far the agent learns to do a backflip and walk from an animation. Because the animation for walking and backflip starts from the same position (humanoid is standing straight with arms besides his body), the configurable joint initial angles are fine being set to a fixed rotation.
    But now I would like for it to learn some new movements, which requires the humanoid's initial joint rotations to be different at the start of each episode, so the humanoid initial position matches the animation initial position.
    So:
    Is it possible to set the initial configurable joint rotation? Does configurable joint have such a parameter to set? One (really ugly and impractical) workaround would be that at the start of each episode I set for example the shoulder Gameobject rotation, and then configure the configurable joint's rotation limits for each axis according to the shoulder Gameobject rotation. But this seems way to much unnecessary work since all of that could be solved with one parameter in the configurable joint component (which I cannot find).

    TL;DR: Is it possible to set configurable joint's initial rotation?
     
  2. mbaske

    mbaske

    Joined:
    Dec 31, 2017
    Posts:
    473
    You can simply copy the initial character pose by setting the jointed rigidbodies' positions and rotations to match the animation. Make sure to also set the initial target rotations for your joints.
     
  3. Omelette_au_Goulage

    Omelette_au_Goulage

    Joined:
    Jun 9, 2020
    Posts:
    14
    If I understand correctly: I should rotate the rigidbody(ies) connected to the joint to match the animation initial rotation. In the attached picture I rotated the left arm of the humanoid from shoulder up. The problem with this is that the configurable joint limits also change (as seen in the picture) and now the arm has different achievable space than before and also setting the target rotation to 0, would take the arm to different position than before (before it would want t point downwards, after it would want to point at 45° to the right).
    Is there another way to rotate the arm, so that the joint limits stay the same as in original position?
     

    Attached Files:

  4. mbaske

    mbaske

    Joined:
    Dec 31, 2017
    Posts:
    473
    I've worked on a very similar project recently. Per default, my rigged (animated) character is in T-pose with all its local bone rotations at 0/0/0. The physical character consists of rigidbodies which are all on the same hierarchy level (I once read you shouldn't nest rigidbodies in Unity, but I'm not sure if that's still valid). The rigidbodies are connected with configurable joints whose default rotation is also at 0/0/0 and I'm using the default joint axes. The global positions of rigged bones and associated rigidbodies must be the same. These are also the anchor positions for the joints.
    Each rigidbody's 'local' rotation with respect to its connected body is therefore the delta between its global rotation and that of its connected body's global rotation, e.g. upper_arm_local_rotation = Quaternion.Inverse(shoulder_global_rotation) * upper_arm_global_rotation. Now we can easily sync local rotations between the two character variants. In order to apply the first animation frame's pose to the physics, I copy the global positions and rotations of the bones to the rigidbodies and set the joint target rotations to match the local rotations of the bones. This way, the joint limits and default (0) target rotations don't change.

    As an alternative to using joints, check out ArticulationBody https://docs.unity3d.com/2020.1/Documentation/ScriptReference/ArticulationBody.html

    EDIT Setting global positions and rotations on the first animation frame is just to prevent the rigidbodies from bouncing around. The setup also works if you just apply the joint target rotations, but you'd probably need to wait for the physics to settle down before you can start the agent loop. Depends on how different the initial rotations are from T-pose.
     
    Last edited: Dec 10, 2020
  5. Omelette_au_Goulage

    Omelette_au_Goulage

    Joined:
    Jun 9, 2020
    Posts:
    14
    So I've read your reply couple of times and all this time I was adjusting the Rigidbody's Gameobject rotation and I've just now realized that Rigidbody can have it's rotation adjusted directly (which is what you were saying all along). And now it works!
    Thank you!
     
  6. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    Thank you both for this insight, This behavior has been frustrating me for a while now as I couldn't pre-pose my armatures without loosing the initial joint limits. (Odd that I stumbled across it in the Ai/Ml subforum, but ok)

    For further clarification:
    Unless I'm doing something wrong, once a RigidBody joint and it's rotational limits are set, one can never again alter the GameObject's rotation using the unity editor's transform fields. Seems like I need to create a custom editor script for when a RB and joint exist on the same object to hide the default transform fields and replace them with one that serializes to the RB's rotation property.
     
  7. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    254
    Thank you for this nugget, IT helps address an issue I've been having with limited rotation joints for a while now.

    For my clarification, if I configured a joint's limits in it's identify rotation, how would I rotate it into a more comfortable position within the editor as I can no linger use the transform rotation without the rotation limits also shifting. I tried setting the RigidBody rotation in the editor, but that doesn't affect the change I need.

    Essentially, how can I set the joints rotation limits, then rotate the joint to a starting rotation in the editor without having to physics simulate the joints movement to that starting state? Do I need to set both the RigidBody's rotation and the joints transform rotation in the editor at the same time?
     
  8. mbaske

    mbaske

    Joined:
    Dec 31, 2017
    Posts:
    473
    With a joint on your gameobject, you normally set the object's rotation via the joint's target value - which is already serialized in the joint component inspector. The joint then controls the transform rotation, so yes, you wouldn't set the transform values directly, once you have a joint. In order to pre-pose an object, you could set an initial joint target value though.

    EDIT
    > without having to physics simulate the joints movement to that starting state?
    I don't think it'll work without physics. AFAIK, setting the target value doesn't do anything in edit mode.