Constraint::LineOnLineContact::LineOnLineContact
   (MobilizedBody&      mobod_F,
    const Transform&    defaultEdgeFrameF,
    Real                defaultHalfLengthF,
    MobilizedBody&      mobod_B,
    const Transform&    defaultEdgeFrameB,
    Real                defaultHalfLengthB,
    bool                enforceRolling)
:   Constraint(new LineOnLineContactImpl(enforceRolling))
{
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSubsystem() && mobod_B.isInSubsystem(),
        "Constraint::LineOnLineContact","LineOnLineContact",
        "Both mobilized bodies must already be in a SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSameSubsystem(mobod_B),
        "Constraint::LineOnLineContact","LineOnLineContact",
        "The two mobilized bodies to be connected must be in the same "
        "SimbodyMatterSubsystem.");

    mobod_F.updMatterSubsystem().adoptConstraint(*this);

    updImpl().m_mobod_F     = updImpl().addConstrainedBody(mobod_F);
    updImpl().m_mobod_B     = updImpl().addConstrainedBody(mobod_B);
    updImpl().m_def_X_FEf   = defaultEdgeFrameF;
    updImpl().m_def_hf      = defaultHalfLengthF;
    updImpl().m_def_X_BEb   = defaultEdgeFrameB;
    updImpl().m_def_hb      = defaultHalfLengthB;
}
Constraint::SphereOnPlaneContact::SphereOnPlaneContact
   (MobilizedBody&      planeBody,
    const Transform&    defaultPlaneFrame,
    MobilizedBody&      sphereBody,
    const Vec3&         defaultSphereCenter,
    Real                defaultSphereRadius,
    bool                enforceRolling)
:   Constraint(new SphereOnPlaneContactImpl(enforceRolling))
{
    SimTK_APIARGCHECK_ALWAYS(   planeBody.isInSubsystem()
                             && sphereBody.isInSubsystem(),
        "Constraint::SphereOnPlaneContact","SphereOnPlaneContact",
        "Both bodies must already be in a SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK_ALWAYS(planeBody.isInSameSubsystem(sphereBody),
        "Constraint::SphereOnPlaneContact","SphereOnPlaneContact",
        "The two bodies to be connected must be in the same "
        "SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK1_ALWAYS(defaultSphereRadius > 0,
        "Constraint::SphereOnPlaneContact","SphereOnPlaneContact",
        "The sphere radius must be greater than zero but was %g.",
        defaultSphereRadius);

    planeBody.updMatterSubsystem().adoptConstraint(*this);

    updImpl().m_planeBody_F     = updImpl().addConstrainedBody(planeBody);
    updImpl().m_ballBody_B      = updImpl().addConstrainedBody(sphereBody);
    updImpl().m_def_X_FP        = defaultPlaneFrame;
    updImpl().m_def_p_BO        = defaultSphereCenter;
    updImpl().m_def_radius      = defaultSphereRadius;
}
Constraint::SphereOnSphereContact::SphereOnSphereContact
   (MobilizedBody&      mobod_F, 
    const Vec3&         defaultCenter_F, 
    Real                defaultRadius_F, 
    MobilizedBody&      mobod_B, 
    const Vec3&         defaultCenter_B,
    Real                defaultRadius_B,
    bool                enforceRolling)
:   Constraint(new SphereOnSphereContactImpl(enforceRolling))
{
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSubsystem() && mobod_B.isInSubsystem(),
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "Both mobilized bodies must already be in a SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK_ALWAYS(mobod_F.isInSameSubsystem(mobod_B),
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "The two mobilized bodies to be connected must be in the same "
        "SimbodyMatterSubsystem.");
    SimTK_APIARGCHECK2_ALWAYS(defaultRadius_F > 0 && defaultRadius_B > 0,
        "Constraint::SphereOnSphereContact","SphereOnSphereContact",
        "The sphere radii must be greater than zero; they were %g and %g.",
        defaultRadius_F, defaultRadius_B);

    mobod_F.updMatterSubsystem().adoptConstraint(*this);

    updImpl().m_mobod_F         = updImpl().addConstrainedBody(mobod_F);
    updImpl().m_mobod_B         = updImpl().addConstrainedBody(mobod_B);
    updImpl().m_def_p_FSf       = defaultCenter_F;
    updImpl().m_def_radius_F    = defaultRadius_F;
    updImpl().m_def_p_BSb       = defaultCenter_B;
    updImpl().m_def_radius_B    = defaultRadius_B;
}
Esempio n. 4
0
Force::MobilityLinearDamperImpl::
MobilityLinearDamperImpl(const MobilizedBody&   mobod, 
                         MobilizerUIndex        whichU,
                         Real                   defaultDamping) 
:   m_matter(mobod.getMatterSubsystem()), 
    m_mobodIx(mobod.getMobilizedBodyIndex()), m_whichU(whichU), 
    m_defaultDamping(defaultDamping) 
{
}
Esempio n. 5
0
Force::MobilityConstantForceImpl::MobilityConstantForceImpl
   (const MobilizedBody&    mobod, 
    MobilizerUIndex         whichU,
    Real                    defaultForce) 
:   m_matter(mobod.getMatterSubsystem()), 
    m_mobodIx(mobod.getMobilizedBodyIndex()), m_whichU(whichU), 
    m_defaultForce(defaultForce) 
{
}
Esempio n. 6
0
Force::MobilityLinearSpringImpl::
MobilityLinearSpringImpl(const MobilizedBody&    mobod, 
                         MobilizerQIndex         whichQ,
                         Real                    defaultStiffness, 
                         Real                    defaultQZero) 
:   m_matter(mobod.getMatterSubsystem()), 
    m_mobodIx(mobod.getMobilizedBodyIndex()), m_whichQ(whichQ), 
    m_defaultStiffness(defaultStiffness), m_defaultQZero(defaultQZero)
{
}
//==============================================================================
//                            GET REACTION PAIR
//==============================================================================
static ReactionPair getReactionPair(const State&         state,
                                    const MobilizedBody& mobod) 
{
    SpatialVec p = mobod.findMobilizerReactionOnParentAtFInGround(state);
    SpatialVec c = mobod.findMobilizerReactionOnBodyAtMInGround(state);
    const Rotation& R_GC = mobod.getBodyRotation(state);
    const Rotation& R_GP = mobod.getParentMobilizedBody().getBodyRotation(state);
    ReactionPair pair;
    pair.reactionOnChildInChild   = ~R_GC*c; // from Ground to Child
    pair.reactionOnParentInParent = ~R_GP*p; // from Ground to Parent
    return pair;
}
Esempio n. 8
0
Force::MobilityLinearStopImpl::MobilityLinearStopImpl
   (const MobilizedBody&      mobod, 
    MobilizerQIndex           whichQ, 
    Real                      defaultStiffness,
    Real                      defaultDissipation,
    Real                      defaultQLow,
    Real                      defaultQHigh) 
:   m_matter(mobod.getMatterSubsystem()), 
    m_mobodIx(mobod.getMobilizedBodyIndex()), m_whichQ(whichQ), 
    m_defStiffness(defaultStiffness), m_defDissipation(defaultDissipation),
    m_defQLow(defaultQLow), m_defQHigh(defaultQHigh)
{
}
Esempio n. 9
0
SpatialVec Force::DiscreteForces::
getOneBodyForce(const State& state, const MobilizedBody& mobod) const {
    const Vector_<SpatialVec>& bodyForces = getImpl().getAllBodyForces(state);
    if (bodyForces.size() == 0) {return SpatialVec(Vec3(0),Vec3(0));}

    return bodyForces[mobod.getMobilizedBodyIndex()];
}
Esempio n. 10
0
 MyConstraintImplementation(MobilizedBody& mobilizer, Real speed)
   : Implementation(mobilizer.updMatterSubsystem(), 0,1,0),  
     theMobilizer(), whichMobility(), prescribedSpeed(NaN)
 {
     theMobilizer = addConstrainedMobilizer(mobilizer);
     whichMobility = MobilizerUIndex(0);
     prescribedSpeed = speed;
 }
Esempio n. 11
0
Real Force::DiscreteForces::
getOneMobilityForce(const State& state, const MobilizedBody& mobod,
                    MobilizerUIndex whichU) const {
    const Vector& mobForces = getImpl().getAllMobilityForces(state);
    if (mobForces.size() == 0) {return 0;}

    return mobod.getOneFromUPartition(state, whichU, mobForces);
}
Esempio n. 12
0
void Force::DiscreteForces::
setOneBodyForce(State& state, const MobilizedBody& mobod,
                const SpatialVec& spatialForceInG) const {
    Vector_<SpatialVec>& bodyForces = getImpl().updAllBodyForces(state);
    if (bodyForces.size() == 0) {
        bodyForces.resize(getImpl().m_matter.getNumBodies());
        bodyForces.setToZero();
    }
    bodyForces[mobod.getMobilizedBodyIndex()] = spatialForceInG;
}
Esempio n. 13
0
void Force::DiscreteForces::
addForceToBodyPoint(State& state, const MobilizedBody& mobod,
                    const Vec3& pointInB, const Vec3& forceInG) const {
    Vector_<SpatialVec>& bodyForces = getImpl().updAllBodyForces(state);
    if (bodyForces.size() == 0) {
        bodyForces.resize(getImpl().m_matter.getNumBodies());
        bodyForces.setToZero();
    }
    mobod.applyForceToBodyPoint(state, pointInB, forceInG, bodyForces);
}
Esempio n. 14
0
void Force::DiscreteForces::
setOneMobilityForce(State& state, const MobilizedBody& mobod,
                    MobilizerUIndex whichU, Real f) const {
    Vector& mobForces = getImpl().updAllMobilityForces(state);
    if (mobForces.size() == 0) {
        mobForces.resize(state.getNU());
        mobForces.setToZero();
    }
    // Don't use "apply" here because that would add in the force.
    mobod.updOneFromUPartition(state, whichU, mobForces) = f;
}
Esempio n. 15
0
void ObservedPointFitter::
createClonedSystem(const MultibodySystem& original, MultibodySystem& copy, 
                   const Array_<MobilizedBodyIndex>& originalBodyIxs, 
                   Array_<MobilizedBodyIndex>& copyBodyIxs,
                   bool& hasArtificialBaseBody) 
{
    const SimbodyMatterSubsystem& originalMatter = original.getMatterSubsystem();
    SimbodyMatterSubsystem copyMatter(copy);
    Body::Rigid body = Body::Rigid(MassProperties(1, Vec3(0), Inertia(1)));
    body.addDecoration(Transform(), DecorativeSphere(Real(.1)));
    std::map<MobilizedBodyIndex, MobilizedBodyIndex> idMap;
    hasArtificialBaseBody = false;
    for (int i = 0; i < (int)originalBodyIxs.size(); ++i) {
        const MobilizedBody& originalBody = originalMatter.getMobilizedBody(originalBodyIxs[i]);
        MobilizedBody* copyBody;
        if (i == 0) {
            if (originalBody.isGround())
                copyBody = &copyMatter.Ground();
            else {
                hasArtificialBaseBody = true; // not using the original joint here
                MobilizedBody::Free free(copyMatter.Ground(), body);
                copyBody = &copyMatter.updMobilizedBody(free.getMobilizedBodyIndex());
            }
        }
        else {
            MobilizedBody& parent = copyMatter.updMobilizedBody(idMap[originalBody.getParentMobilizedBody().getMobilizedBodyIndex()]);
            copyBody = &originalBody.cloneForNewParent(parent);
        }
        copyBodyIxs.push_back(copyBody->getMobilizedBodyIndex());
        idMap[originalBodyIxs[i]] = copyBody->getMobilizedBodyIndex();
    }
    copy.realizeTopology();
    State& s = copy.updDefaultState();
    copyMatter.setUseEulerAngles(s, true);
    copy.realizeModel(s);
}
Esempio n. 16
0
Force::TwoPointConstantForceImpl::TwoPointConstantForceImpl(const MobilizedBody& body1, const Vec3& station1,
        const MobilizedBody& body2, const Vec3& station2, Real force) : matter(body1.getMatterSubsystem()),
        body1(body1.getMobilizedBodyIndex()), station1(station1),
        body2(body2.getMobilizedBodyIndex()), station2(station2), force(force) {
}
Esempio n. 17
0
    virtual void generateDecorations(const State& state, Array_<DecorativeGeometry>& geometry) override {
        const Vec3 frcColors[] = {Red,Orange,Cyan,Green,Blue,Yellow};
        m_system.realize(state, Stage::Velocity);

        const int ncont = m_compliant.getNumContactForces(state);
        for (int i=0; i < ncont; ++i) {
            const ContactForce& force = m_compliant.getContactForce(state,i);
            const ContactId     id    = force.getContactId();
			// define if it's femur_lat -> femur_med contact pair: id=8
			//if (id == 6 || id == 8 || id==4 || id==2 || id==10 )
			//	continue;
			ContactSnapshot cs = m_compliant.getContactTrackerSubsystem().getActiveContacts(state);
			//cout <<  "contact: " << id << endl;
			//ContactId idFemur = cs.getContactIdForSurfacePair( ContactSurfaceIndex(2), ContactSurfaceIndex(3));
			//ContactId idMeniscFemur1 = cs.getContactIdForSurfacePair( ContactSurfaceIndex(0), ContactSurfaceIndex(2));
			//ContactId idMeniscTibia1 = cs.getContactIdForSurfacePair( ContactSurfaceIndex(0), ContactSurfaceIndex(4));
			//ContactId idMeniscFemur2 = cs.getContactIdForSurfacePair( ContactSurfaceIndex(1), ContactSurfaceIndex(3));
			//ContactId idMeniscTibia2 = cs.getContactIdForSurfacePair( ContactSurfaceIndex(1), ContactSurfaceIndex(4));
			ContactId idLatFemurTibia = cs.getContactIdForSurfacePair( ContactSurfaceIndex(0), ContactSurfaceIndex(2));
			ContactId idMedFemurTibia = cs.getContactIdForSurfacePair( ContactSurfaceIndex(1), ContactSurfaceIndex(2));
			ContactId idFemur = cs.getContactIdForSurfacePair( ContactSurfaceIndex(0), ContactSurfaceIndex(1));

			if (id == idFemur)
				continue;

			const SimbodyMatterSubsystem& matter = m_compliant.getMultibodySystem().getMatterSubsystem();
			// get tibia's mobilized body
			MobilizedBody tibiaMobod = matter.getMobilizedBody(MobilizedBodyIndex(22));
			MobilizedBody femurLatmobod = matter.getMobilizedBody(MobilizedBodyIndex(19));
			MobilizedBody femurMedmobod = matter.getMobilizedBody(MobilizedBodyIndex(20));

			//for (int numContacts=0; numContacts<cs.getNumContacts(); numContacts++)
			//{
				//ContactSurfaceIndex csi1 = cs.getContact(numContacts).getSurface1();
				//ContactSurfaceIndex csi2 = cs.getContact(numContacts).getSurface2();
				//cout << "surf1: " << csi1 << " surf2: " << csi2 << endl;
			//}
			if (cs.getNumContacts()>0)
			{
				DecorativeGeometry decTibiaContactGeometry = tibiaMobod.getBody().updDecoration(0);
				decTibiaContactGeometry.setOpacity( 0.9);
				decTibiaContactGeometry.setColor( Gray);

				DecorativeGeometry decFemurLatContactGeometry = femurLatmobod.getBody().updDecoration(0);
				decFemurLatContactGeometry.setOpacity(1);
				decFemurLatContactGeometry.setColor(Gray);

				DecorativeGeometry decFemurMedContactGeometry = femurMedmobod.getBody().updDecoration(0);
				decFemurMedContactGeometry.setOpacity(1);
				decFemurMedContactGeometry.setColor(Gray);

				// Tibia transformation
				const Transform& X_BM = tibiaMobod.getOutboardFrame(state); // M frame in B
				const Transform& X_GB = tibiaMobod.getBodyTransform(state); // B in Ground
				const Transform& X_PF = tibiaMobod.getInboardFrame(state);
				Transform X_GM = X_GB*X_BM; // M frame in Ground
				// rotate 
				//Rotation& newRot = X_GM.updR();
				//Rotation parentRot = X_PF.R();
				//newRot.operator*=( parentRot.invert());
				// translate in front of the whole body
				X_GM.setP( X_GM.operator+=( Vec3(0.3,0,0)).p());
				// set new transform
				decTibiaContactGeometry.setTransform( X_GM);

				// Medial Femur Transformation
				const Transform& X_BM_medFemur = femurMedmobod.getOutboardFrame(state); // M frame in B
				const Transform& X_GB_medFemur = femurMedmobod.getBodyTransform(state); // B in Ground
				const Transform& X_PF_medFemur = femurMedmobod.getInboardFrame(state);
				Transform X_GM_medFemur = X_GB_medFemur*X_BM_medFemur; // M frame in Ground
				// rotate 
				//Rotation& newRot_medFemur = X_GM_medFemur.updR();
				//Rotation parentRot_medFemur = X_PF_medFemur.R();
				//newRot_medFemur.operator*=(parentRot_medFemur).operator*=(Rotation(1.57079, CoordinateAxis::ZCoordinateAxis()));
				//newRot_medFemur.setRotationFromAngleAboutZ(1.570796326794897);
				// translate in front of the whole body
				X_GM_medFemur.setP(X_GM_medFemur.operator+=(Vec3(0.3, 0.1, 0)).p());
				// set new transform
				decFemurMedContactGeometry.setTransform(X_GM_medFemur);

				// Lateral Femur Transformation
				const Transform& X_BM_latFemur = femurLatmobod.getOutboardFrame(state); // M frame in B
				const Transform& X_GB_latFemur = femurLatmobod.getBodyTransform(state); // B in Ground
				const Transform& X_PF_latFemur = femurLatmobod.getInboardFrame(state);
				Transform X_GM_latFemur = X_GB_latFemur*X_BM_latFemur; // M frame in Ground
				// rotate 
				//Rotation& newRot_latFemur = X_GM_latFemur.updR();
				//Rotation parentRot_latFemur = X_PF_latFemur.R();
				//newRot_latFemur.operator*=(parentRot_latFemur).operator*=(Rotation(1.57079, CoordinateAxis::ZCoordinateAxis()));
				//newRot_latFemur.setRotationFromAngleAboutZ(1.570796326794897);
				// translate in front of the whole body
				X_GM_latFemur.setP(X_GM_latFemur.operator+=(Vec3(0.3, 0.1, 0)).p());
				// set new transform
				decFemurLatContactGeometry.setTransform(X_GM_latFemur);

				ContactPatch patch;
				const bool found = m_compliant.calcContactPatchDetailsById(state,id,patch);
				//cout << "patch for id" << id << " found=" << found << endl;
				//cout << "resultant=" << patch.getContactForce() << endl;
				//cout << "num details=" << patch.getNumDetails() << endl;
				for (int k=0; k < patch.getNumDetails(); ++k) {
					const ContactDetail& detail = patch.getContactDetail(k);
					//const Real peakPressure = detail.getPeakPressure();		
					const Vec3 cp = detail.getContactPoint();
					Vec3 newcp = Vec3(cp);

					// transform point to attach tibia surface
					Transform cpToTibiaTransf = Transform(newcp);
					cpToTibiaTransf.setP(cpToTibiaTransf.operator+=( Vec3(0.3,0,0)).p());

					DecorativeSphere decCpToTibia;
					decCpToTibia.setScale(0.0005);
					decCpToTibia.setTransform(cpToTibiaTransf);
					decCpToTibia.setColor(Red);

					// transform point to attach femur surface
					Transform cpToFemurTransf = Transform(newcp);
					//Rotation& newRotCpToFemur = cpToFemurTransf.updR();
					//newRotCpToFemur.setRotationFromAngleAboutZ(1.570796326794897);
					//cpToFemurTransf.set(X_GM_latFemur.R(), X_GM_latFemur.p());
					//newRotCpToFemur.operator*=(parentRot_latFemur);
					//cpToFemurTransf.setP( X_PF_latFemur.p());
					//newRotCpToFemur.setRotationFromAngleAboutZ(1.570796326794897);
					cpToFemurTransf.setP(cpToFemurTransf.operator+=(Vec3(0.3, 0.1, 0)).p());

					DecorativeSphere decCpToFemur;
					decCpToFemur.setScale(0.0005);
					decCpToFemur.setTransform(cpToFemurTransf);
					decCpToFemur.setColor(Red);

					geometry.push_back(decCpToTibia);
					geometry.push_back(decCpToFemur);
					if (k == 0)
					{
						geometry.push_back(decTibiaContactGeometry);
						geometry.push_back(decFemurLatContactGeometry);
						geometry.push_back(decFemurMedContactGeometry);
					}
				}
			}
        }		
    }
 MyTorqueLimitedMotor
    (const MobilizedBody& mobod, MobilizerUIndex whichU, 
     Real gain, Real torqueLimit)
 :   m_matter(mobod.getMatterSubsystem()), m_mobod(mobod), m_whichU(whichU), 
     m_torqueGain(gain), m_torqueLimit(torqueLimit) 
 {   assert(gain >= 0 && torqueLimit >= 0); }
 // Constructor takes two bodies and the desired separation distance
 // between their body frame origins. Tell the base class that this
 // constraint generates 1 holonomic (position level), 0 nonholonomic
 // (velocity level), and 0 acceleration-only constraint equations.
 ExampleConstraint(MobilizedBody& b1, MobilizedBody& b2, Real distance) 
 :   Implementation(b1.updMatterSubsystem(), 1, 0, 0), distance(distance) {
     body1 = addConstrainedBody(b1);
     body2 = addConstrainedBody(b2);
 }
Esempio n. 20
0
Force::ConstantTorqueImpl::ConstantTorqueImpl(const MobilizedBody& body, const Vec3& torque) :
        matter(body.getMatterSubsystem()), body(body.getMobilizedBodyIndex()), torque(torque) {
}
Esempio n. 21
0
Force::TwoPointLinearSpringImpl::TwoPointLinearSpringImpl(const MobilizedBody& body1, const Vec3& station1,
        const MobilizedBody& body2, const Vec3& station2, Real k, Real x0) : matter(body1.getMatterSubsystem()),
        body1(body1.getMobilizedBodyIndex()), station1(station1),
        body2(body2.getMobilizedBodyIndex()), station2(station2), k(k), x0(x0) {
}
Esempio n. 22
0
Force::ConstantForceImpl::ConstantForceImpl(const MobilizedBody& body, const Vec3& station, const Vec3& force) :
        matter(body.getMatterSubsystem()), body(body.getMobilizedBodyIndex()), station(station), force(force) {
}
Esempio n. 23
0
Force::TwoPointLinearDamperImpl::TwoPointLinearDamperImpl(const MobilizedBody& body1, const Vec3& station1,
        const MobilizedBody& body2, const Vec3& station2, Real damping) : matter(body1.getMatterSubsystem()),
        body1(body1.getMobilizedBodyIndex()), station1(station1),
        body2(body2.getMobilizedBodyIndex()), station2(station2), damping(damping) {
}
Esempio n. 24
0
/* Calculate the equivalent spatial force, FB_G, acting on a mobilized body specified 
   by index acting at its mobilizer frame B, expressed in ground.  */
SimTK::SpatialVec Joint::calcEquivalentSpatialForceForMobilizedBody(const SimTK::State &s, 
	const SimTK::MobilizedBodyIndex mbx, const SimTK::Vector &mobilityForces) const
{
	// Get the mobilized body
	const SimTK::MobilizedBody mbd    = getModel().getMatterSubsystem().getMobilizedBody(mbx);
	const SimTK::UIndex        ustart = mbd.getFirstUIndex(s);
	const int                  nu     = mbd.getNumU(s);

	const SimTK::MobilizedBody ground = getModel().getMatterSubsystem().getGround();

    if (nu == 0) // No mobility forces (weld joint?).
        return SimTK::SpatialVec(SimTK::Vec3(0), SimTK::Vec3(0));

	// Construct the H (joint jacobian, joint transition) matrrix for this mobilizer
	SimTK::Matrix transposeH_PB_w(nu, 3);
	SimTK::Matrix transposeH_PB_v(nu, 3);
	// from individual columns
	SimTK::SpatialVec Hcol;
	
	// To obtain the joint Jacobian, H_PB (H_FM in Simbody) need to be realized to at least position
	_model->getMultibodySystem().realize(s, SimTK::Stage::Position);

	SimTK::Vector f(nu, 0.0);
	for(int i =0; i<nu; ++i){
		f[i] = mobilityForces[ustart + i];
		// Get the H matrix for this Joint by constructing it from the operator H*u
		Hcol = mbd.getH_FMCol(s, SimTK::MobilizerUIndex(i));
		const SimTK::Vector hcolw(Hcol[0]);
		const SimTK::Vector hcolv(Hcol[1]);

		transposeH_PB_w[i] = ~hcolw;
		transposeH_PB_v[i] = ~hcolv;
	}

	// Spatial force and torque vectors
	SimTK::Vector Fv(3, 0.0), Fw(3, 0.0);

	// Solve the pseudoinverse problem of Fv = pinv(~H_PB_G_v)*f;
	SimTK::FactorQTZ pinvForce(transposeH_PB_v);

	//if rank = 0, body force cannot contribute to the mobility force
	if(pinvForce.getRank() > 0)
		pinvForce.solve(f, Fv);
	
	// Now solve the pseudoinverse for torque for any unaccounted f: Fw = pinv(~H_PB_G_w)*(f - ~H_PB_G_v*Fv);
	SimTK::FactorQTZ pinvTorq(transposeH_PB_w);

	//if rank = 0, body torque cannot contribute to the mobility force
	if(pinvTorq.getRank() > 0)
		pinvTorq.solve(f, Fw);
	
	// Now we have two solution with either the body force Fv or body torque accounting for some or all of f
	SimTK::Vector fv =  transposeH_PB_v*Fv;
	SimTK::Vector fw =  transposeH_PB_w*Fw; 

	// which to choose? Choose the more effective as fx.norm/Fx.norm
	if(fv.norm() > SimTK::SignificantReal){ // if body force can contributes at all
		// if body torque can contribute too and it is more effective
		if(fw.norm() > SimTK::SignificantReal){
			if (fw.norm()/Fw.norm() > fv.norm()/Fv.norm() ){ 
				// account for f using torque, Fw, so compute Fv with remainder
				pinvForce.solve(f-fw, Fv);		
			}else{
				// account for f using force, Fv, first and Fw from remainder
				pinvTorq.solve(f-fv, Fw);
			}
		}
		// else no torque contribution and Fw should be zero
	}
	// no force contribution but have a torque
	else if(fw.norm() > SimTK::SignificantReal){
		// just Fw
	}
	else{
		// should be the case where gen force is zero.
		assert(f.norm() < SimTK::SignificantReal);
	}

	// The spatial forces above are expresseded in the joint frame of the parent
	// Transform from parent joint frame, P into the parent body frame, Po
	const SimTK::Rotation R_PPo = (mbd.getInboardFrame(s).R());

	// Re-express forces in ground, first by describing force in the parent, Po, 
	// frame instead of joint frame
	SimTK::Vec3 vecFw = R_PPo*SimTK::Vec3::getAs(&Fw[0]);
	SimTK::Vec3 vecFv = R_PPo*SimTK::Vec3::getAs(&Fv[0]);

	//Force Acting on joint frame, B,  in child body expressed in Parent body, Po
	SimTK::SpatialVec FB_Po(vecFw, vecFv);

	const MobilizedBody parent = mbd.getParentMobilizedBody();
	// to apply spatial forces on bodies they must be expressed in ground
	vecFw = parent.expressVectorInAnotherBodyFrame(s, FB_Po[0], ground);
	vecFv = parent.expressVectorInAnotherBodyFrame(s, FB_Po[1], ground);

	// Package resulting torque and force as a spatial vec
	SimTK::SpatialVec FB_G(vecFw, vecFv);

	return FB_G;
}