MoCap 1-handed lift. How to set up simulation to transition between holding/not holding object

Hi there!

I am working on setting up a simulation in which a person picks up an object (one-handed) from one location then transfers the object to a new location. The human model is driven by mocap data (xsens/bvh files), and I am hoping to attach a segment to the human hand to simulate the object that is being moved. My questions currently are:

  1. How can I rigidly attach a segment (to simulate the lifted object) to hand segment with the point of attachment being the palmjoint node?
  2. What would be the best method to simulate the transition between holding and not holding the object?

I’m sure it’s simple enough, but I haven't found a way that is working properly. I’ve tried to follow some of the examples provided in the AMMR (such as the BenchPress and StandingLift), but I am running into the limits of my understanding of how to apply the same techniques to models that are driven with mocap data.

To simulate the transition between holding and not holding the object, I have thought of a couple of ideas, but I have not found a way to implement either (if they are possible at all). Idea #1) Is it possible to define the mass of a segment such that it can change throughout the trial? I have the time information of when the object is being held and when it is not, so if there is a way that I can transition the mass to 0 or nearly zero when during the “not-holding” time periods that could accomplish what I am trying to simulate. Idea #2) Could there be a way of changing joint constraints throughout the trial that could allow the human hand to engage and disengage with the lifted object at the time periods that I specify? This discussion: Define joints only at specific times (https://forum.anyscript.org/t/define-joints-only-at-specific-times/5987) seems to provide such a solution for a similar question as mine. If this is the best approach, I will have more questions for you because I do not quite understand the answer as it is provided and how it might pertain to my simulations.

Thank you,

Lindsay Schuring

2 Likes

Hi @lschuring - great to see you are still active in modelling!

You actually stumbled across a rather difficult situation here, but I will try and explain the the best I can.

The attachment of the object to the hand is rather easy - you can define a joint between the to reference frames to connect them. See here for a tutorial on the mater.

To model the hand grabbing and letting go of the object is the tricky part.
The only feasible way at the moment is to use conditional contact muscles (if you ever tried the GRF prediction, that is made this way)

You would need a simplified version of what we have as class templates located under AMMR/Tools/ModelUtilities/FrictionContactMuscles/. You must define a function to know whether contact should be made or not - it could be the distance between the hand node and the object. Next, you need some muscles that switch on when the hand is close enough.
The snippet uses a special muscle model that can take a use a function to define the strength of it.
there are 12 muscles in total to carry all 6-DoF in as both push and pull muscles.

On top of all this you need to specify some driver/constraints to "carry" the object when it is not in contact with the hand - otherwise it would be kinematically indeterminate.
Most likely this driver/constraint will use the reciprocal of the function that determines the contact.

Best regards,
Bjørn
AnyBody Technology

// Strength when contact is active
AnyVar Strength = 3000;
// Some function to determine if contact should be active or not.
AnyVar UserDefinedStrengthFunction= iffun(ltfun(Lin.Pos[0]-0.02),Strength,0.0);

// Muscle model used for contact muscles
AnyMuscleModelUsr1 ContactMuscleModel=   {
  F0 = 0.000000;
  S = .UserDefinedStrengthFunction;
};        
  
// Linear measure between the two objects
AnyKinLinear Lin={
  AnyRefFrame &Box = BaseObject;
  AnyRefFrame &Hand = TargetObject;
  Ref=0;
};

// rotational measure between the two objects
AnyKinRotational Rot = {
    AnyRefFrame& Box = BaseObject;
    AnyRefFrame& Hand = TargetObject;
    Type = RotVector;
};

// 12 muscles to carry all 6-DoF in both a pull and push direction (specified by the `ForceDirection`
AnyGeneralMuscle Muscle00a={
    AnyKinMeasureOrg LinMeasureOrg0 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {0};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle00b={
    AnyKinMeasureOrg LinMeasureOrg0 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {0};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};

AnyGeneralMuscle Muscle01a={
    AnyKinMeasureOrg LinMeasureOrg1 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {1};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle01b={
    AnyKinMeasureOrg LinMeasureOrg1 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {1};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};

AnyGeneralMuscle Muscle02a={
    AnyKinMeasureOrg LinMeasureOrg2 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {2};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle02b={
    AnyKinMeasureOrg LinMeasureOrg2 = {
        AnyKinMeasure& ref1 = .Lin;
        MeasureOrganizer = {2};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};

AnyGeneralMuscle Muscle03a={
    AnyKinMeasureOrg RotMeasureOrg0 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {0};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle03b={
    AnyKinMeasureOrg RotMeasureOrg0 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {0};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};

AnyGeneralMuscle Muscle04a={
    AnyKinMeasureOrg RotMeasureOrg1 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {1};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle04={
    AnyKinMeasureOrg RotMeasureOrg1 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {1};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};

AnyGeneralMuscle Muscle05a={
    AnyKinMeasureOrg RotMeasureOrg2 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {2};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=1;
    EXCLUDE_MUSCLE_METABOLISM  
};
AnyGeneralMuscle Muscle05b={
    AnyKinMeasureOrg RotMeasureOrg2 = {
        AnyKinMeasure& ref1 = .Rot;
        MeasureOrganizer = {2};
    };
    AnyMuscleModelUsr1 &ref1=.ContactMuscleModel;
    ForceDirection=-1;
    EXCLUDE_MUSCLE_METABOLISM  
};