279 lines (212 with data), 8.8 kB
#class_template CreateTorqueDriver (CreateZeroMomentPointAsExtraSeg=0,
ForceApplicationPoint,
LevelForMeasurePlane,
TargetPointForZeroMoment
){
#var AnyVec3 InitialPositionForPointWithZeroMoment;
#var AnyVar WeightOnSoftDriver;
#var AnyVec3 GravityVector ;
#var AnyVar WeightOnEqFunction;
#var AnyFloat ExternalForce_T;
#var AnyFloat ExternalForce_Data;
#var AnyVar MassOfHumanSegments ;
AnyFolder HumanSegs ={};
//CreateZeroMomentPointAsExtraSeg can be used to let the model create a segment at the point of zero moment
//then this segment can be constrained to be always with the foot stance area, this is done in a different class
//by setting the CreateZeroMomentPointAsExtraSeg =1 will be created which is following the ZMP
//So the ZMP point is unconstrained until it is forced by something else to stay within some bounds or
//at a location
//The ZeroMomentPoint segment is carried by the global ref all six dof
//The motion drivers applied here has no reactions,
AnyKinMeasureLinComb P_Vec = {
AnyKinCoM Human_CoM = { AnyFolder& Human = ..HumanSegs; };
#if CreateZeroMomentPointAsExtraSeg==1
AnyKinMeasure &ref = .PointWithZeroMoment_lin;
#else
AnyKinLinear lin ={
AnyRefFrame &ref2=..TargetPointForZeroMoment ;
};
#endif
Coef = {{1,0,0, -1,0,0}, {0,1,0, 0,-1,0}, {0,0,1, 0,0,-1}};
Const = {0,0,0};
OutDim = 3;
};
//Force application point zero point
AnyKinMeasureLinComb R_Vec = {
AnyKinLinear forceapplicationpoint = { AnyRefFrame& target = ..ForceApplicationPoint; };
#if CreateZeroMomentPointAsExtraSeg==1
AnyKinMeasure &ref = .PointWithZeroMoment_lin;
#else
AnyKinLinear lin ={
AnyRefFrame &ref2=..TargetPointForZeroMoment ;
};
#endif
Coef = {{1,0,0, -1,0,0}, {0,1,0, 0,-1,0}, {0,0,1, 0,0,-1}};
Const = {0,0,0};
OutDim = 3;
};
AnyKinMeasureLinComb PCrossCoM = {
AnyKinMeasureLinComb &ref=.P_Vec ;
AnyFloat W = .MassOfHumanSegments*.GravityVector;
Coef = {
{0 ,W[2],-W[1]},
{-W[2],0 ,W[0] },
{W[1] ,-W[0],0 }
};
OutDim = 3;
};
AnyKinMeasureOrg Rx = {AnyKinMeasure &ref = .R_Vec; MeasureOrganizer = {0};};
AnyKinMeasureOrg Ry = {AnyKinMeasure &ref = .R_Vec; MeasureOrganizer = {1};};
AnyKinMeasureOrg Rz = {AnyKinMeasure &ref = .R_Vec; MeasureOrganizer = {2};};
AnyFolder F_ext = {
AnyFloat T =.ExternalForce_T;
AnyFloat Data= .ExternalForce_Data;
};
#include "CrossProduct.any"
//summation R x F + P x W (W=CoM*Mass)
AnyKinMeasureLinComb EquilibriumEq = {
AnyKinMeasureLinComb &ref=.RCrossF ;
AnyKinMeasureLinComb &ref2=.PCrossCoM ;
Coef = .WeightOnEqFunction*{{1,0,0, 1,0,0}, {0,1,0, 0,1,0}, {0,0,1, 0,0,1}};
Const = {0,0,0};
OutDim = 3;
};
//This function drives PointwithZeroMoment into equilibrium point
//it moves the seg PointWithZeroMoment into a position where the moment is as close as possible to zero
//note that Z is not driven since Gravity compensation can not be used for reducing moments around Z
AnyKinEqSimpleDriver EquilibriumEq_Driver ={
AnyKinMeasureLinComb &ref=.EquilibriumEq ;
DriverPos={0,0};
DriverVel={0,0};
CType={Soft,Soft}; //ideally should be hard
WeightFun={&wt};
MeasureOrganizer={0,1};
Reaction.Type= {Off,Off}; //we do not want reactions here... muscles are to do the work
AnyFunConst wt = {Value = ..WeightOnSoftDriver*{1,1}*1.0;};
};
//this section introduces a new dummy segment which represents the zero moment point
//the segment is then driven to be located at the location which should have zero moment
#if CreateZeroMomentPointAsExtraSeg==1
//this is the segment which is being driven to a point of zero moment
AnySeg PointWithZeroMoment = {
Mass = 0.00;
Jii = 0.000*{1,1,1};
r0 = .InitialPositionForPointWithZeroMoment;
//make it visual
AnyDrawNode Sphere ={
RGB={1,0,0};
ScaleXYZ={1,1,1}*0.035;
};
};
//linear measure
AnyKinLinear PointWithZeroMoment_lin = { AnyRefFrame &ref2 = .PointWithZeroMoment; };
//rotational measure
AnyKinRotational PointWithZeroMoment_rot = {AnyRefFrame &ref = .PointWithZeroMoment; Type = PlanarAngles;};
//lock rotational measure to zero
AnyKinEq lock_PointWithZeroMoment_rot = {AnyKinMeasure &ref = .PointWithZeroMoment_rot;};
//lock moment in z plane wrt to jnt
AnyKinEq lock_PointWithZeroMoment_lin_z = {
AnyKinLinear PointWithZeroMoment_lin = {
AnyRefFrame &ref1 = ..LevelForMeasurePlane;
AnyRefFrame &ref2 = ..PointWithZeroMoment;
};
MeasureOrganizer = {2};
};
AnyReacForce PointWithZeroMoment_lin_xy={
AnyKinMeasureOrg PointWithZeroMoment_xy= {
AnyKinLinear PointWithZeroMoment_lin = {
AnyRefFrame &ref1 = ...LevelForMeasurePlane;
AnyRefFrame &ref2 = ...PointWithZeroMoment;
};
MeasureOrganizer = {0,1};
};
};
// The lines below can be used to force the moment point towards a specific location
// if not used the model will only feel the bounds and not try to make the model have balance
// between the middle of the feet.
// //This function drives PointwithZeroMoment into the desired equilibrium point
// //if the driver is fullfilled the point of zero moment is in the joint center
// AnyKinEqSimpleDriver DriverBetween_PointWithZeroMoment_TargetPointForZeroMoment ={
// AnyKinLinear Lin ={
// AnySeg &ref1=..PointWithZeroMoment ;
// AnyRefFrame &ref2=..TargetPointForZeroMoment ;
// };
// DriverPos={0,0};
// DriverVel={0,0};
// MeasureOrganizer={0,1};
// CType={Soft,Soft};
// WeightFun={&wt};
// // AnyFunConst wt = {Value = ..WeightOnSoftDriver*{1,1};};
// AnyFunConst wt = {Value = {1,1};};
//
// };
#endif
AnyFolder Visualizations ={
AnyFunInterpol Fexternal={
Data=..F_ext.Data;
T=..F_ext.T;
Type=PiecewiseLinear;
};
AnyDrawVector DrawForce = {
Vec = 0.01*.Fexternal(..P_Vec.t) ; //just need a time val
PointAway = On;
GlobalCoord = On;
AnySeg &ref = .. ForceApplicationPoint;
Opacity=0.2;
Line.Thickness=0.01;
Line.RGB={0,1,0};
Line.End.Style = {5} ;
Line.End.Thickness = 3*Line.Thickness;
Line.End.Length = 4*Line.Thickness;
Line.Start.Style = {0};
Line.Start.Thickness = 3*Line.Thickness;
Line.Start.Length = 3*Line.Thickness;
Line.Start.RGB = {1,0,0};
};
};
#if CreateZeroMomentPointAsExtraSeg==1
//Draw sphere
// AnyDrawSphere PointWithZeroMoment_draw = {Position = .PointWithZeroMoment.r; ScaleXYZ = 0.05*{0,1,0};};
#endif
//Draw sphere
//AnyDrawSphere TargetPointForZeroMoment_draw = {Position = .TargetPointForZeroMoment.r; ScaleXYZ = 0.025*{1,1,1}; RGB={0,1,0};Opacity =0.3;};
AnyDrawLine RCrossF_Drawing ={
AnyRefFrame &ref=Main.Model.Environment.GlobalRef;
#if CreateZeroMomentPointAsExtraSeg==1
p0= .PointWithZeroMoment_lin.Pos;
#else
p0=.TargetPointForZeroMoment.r ;
#endif
p1=p0+0.002*.RCrossF.Pos;
Line.Thickness=.007;
Line.RGB={0,0,1};
};
AnyDrawLine PCrossCoM_Drawing ={
AnyRefFrame &ref=Main.Model.Environment.GlobalRef;
#if CreateZeroMomentPointAsExtraSeg==1
p0= .PointWithZeroMoment_lin.Pos;
#else
p0=.TargetPointForZeroMoment.r ;
#endif
p1=p0+0.002*.PCrossCoM.Pos;
Line.Thickness=.007;
Line.RGB={0,0,0};
};
// AnyDrawLine P_Vec_Drawing ={
// AnyRefFrame &ref=Main.Model.Environment.GlobalRef;
// p0= .PointWithZeroMoment_lin.Pos;
// p1=p0+.P_Vec.Pos;
// Line.Thickness=.002;
// Line.RGB={0,0,1};
//
// };
//
//AnyDrawLine R_Vec_Drawing ={
// AnyRefFrame &ref=Main.Model.Environment.GlobalRef;
// p0= .PointWithZeroMoment_lin.Pos;
// p1=p0+.R_Vec.Pos;
// Line.Thickness=.002;
// Line.RGB={0,0,1};
//
// };
};