Simbody  3.7
SimTK::ImpulseSolver Class Referenceabstract

This is the abstract base class for impulse solvers, which solve an important subproblem of the contact and impact equations. More...

+ Inheritance diagram for SimTK::ImpulseSolver:


struct  BoundedRT
struct  ConstraintLtdFrictionRT
struct  StateLtdFrictionRT
struct  UncondRT
struct  UniContactRT
struct  UniSpeedRT

Public Types

enum  ContactType {
  TypeNA =-1,
  Observing =0,
  Known =1,
  Participating =2
enum  UniCond {
  UniNA =-1,
  UniOff =0,
  UniActive =1,
  UniKnown =2
enum  FricCond {
  FricNA =-1,
  FricOff =0,
  Sliding =1,
  Impending =2,
  Rolling =3
enum  BndCond {
  BndNA =-1,
  SlipLow =0,
  ImpendLow =1,
  Engaged =2,
  ImpendHigh =3,
  SlipHigh =4

Public Member Functions

 ImpulseSolver (Real roll2slipTransitionSpeed, Real convergenceTol, int maxIters)
virtual ~ImpulseSolver ()
void setMaxRollingSpeed (Real roll2slipTransitionSpeed)
Real getMaxRollingSpeed () const
void setConvergenceTol (Real tol)
Real getConvergenceTol () const
void setMaxIterations (int maxIts)
int getMaxIterations () const
void clearStats () const
void clearStats (int phase) const
virtual bool solve (int phase, const Array_< MultiplierIndex > &participating, const Matrix &A, const Vector &D, const Array_< MultiplierIndex > &expanding, Vector &piExpand, Vector &verrStart, Vector &verrApplied, Vector &pi, Array_< UncondRT > &unconditional, Array_< UniContactRT > &uniContact, Array_< UniSpeedRT > &uniSpeed, Array_< BoundedRT > &bounded, Array_< ConstraintLtdFrictionRT > &consLtdFriction, Array_< StateLtdFrictionRT > &stateLtdFriction) const =0
 Solve. More...
virtual bool solveBilateral (const Array_< MultiplierIndex > &participating, const Matrix &A, const Vector &D, const Vector &rhs, Vector &pi) const =0
 Solve a set of bilateral (unconditional) constraints for the impulse necessary to enforce them. More...

Static Public Member Functions

static const char * getContactTypeName (ContactType ct)
static const char * getUniCondName (UniCond uc)
static const char * getFricCondName (FricCond fc)
static const char * getBndCondName (BndCond bc)
static void dumpUniContacts (const String &msg, const Array_< UniContactRT > &uniContacts)

Static Public Attributes

static const int MaxNumPhases = 3

Protected Attributes

Real m_maxRollingTangVel
Real m_convergenceTol
int m_maxIters
long long m_nSolves [MaxNumPhases]
long long m_nIters [MaxNumPhases]
long long m_nFail [MaxNumPhases]
long long m_nBilateralSolves
long long m_nBilateralIters
long long m_nBilateralFail

Detailed Description

This is the abstract base class for impulse solvers, which solve an important subproblem of the contact and impact equations.

Impact problem:

    M  du    + ~G (pi+piE) = 0
    G (u+du) -  D (pi+piE) = b - verrNewton

where verrNewton is constraint space velocity error due to Newton restitution (not used for Poisson restitution). Moving knowns to the right:

    M  du    + ~G pi = -~G piE
    G  du    -  D pi = b - G u - verrNewton + D piE

Substituting 2nd eqn into first gives this impact subproblem:

    [A+D] pi = verr0 + verrNewton + verrExpand
    where verr0 = Gu-b, verrExpand = -[A+D]piE, and A=G M\ ~G.

Contact problem:

    M du + ~G pi  = h f
    G du -  D pi  = b - G u

Substituting gives this contact subproblem:

    [A+D] pi = verr0 + verrApplied
    where verrApplied = h G M\ f.

The form of the problems is the same, with different RHS and no expansion impulse given for contact. The impulse solver thus solves this system of equations and inequalities:

    [A+D] (piExpand + piUnknown) = verrStart + verrApplied
    where verrStart = verr0 + verrNewton

subject to several inequalities and replacement of friction rows by sliding or impending slip equations for the unknown impulse piUnknown. piExpand is the given Poisson expansion impulse, non-zero only for expanding unilateral normal contacts, with piExpand_z[k]<=0 for each unilateral contact k. A is an mXm symmetric positive semidefinite matrix, D a diagonal matrix with nonnegative elements, pi=piExpand+piUnknown and rhs are m-vectors. We write pi this way because friction limits depend on pi, not just piUnknown. We require piExpand_z<=0 for unilateral normal contacts z.

Similarly, we must separate verrStart and verrApplied, because verrStart contains the actual constraint-space velocities, especially sliding, which we need in order to determine sliding direction and contact status (rolling or sliding). verrApplied just represents what the applied forces would do if there were no constraints; the constraints will react to that so that the actual velocity changes will be much different.

For each "sliding step", we classify frictional contacts based on the current contents of verrStart, then solve:

    [A+D] piUnknown = verrStart + verrApplied - [A+D]*piExpand 
    with inequalities
    piUnknown_z <= 0
    sqrt(piUnknown_x^2+piUnknown_y^2) <= -mu*pi_z
    where pi=piUnknown+piExpand

We then choose a fraction s of this sliding step to accept, with 0<s<=1, then update

    verrStart   += s*(verrApplied - [A+D]*pi)
    piExpand    -= s*piExpand
    verrApplied -= s*verrApplied

If s < 1 then we are not done. In that case we have removed some of the verr and used up some of the expansion impulse. Return to do another sliding step until we take one where s==1.

We return piUnknown and the updated verrStart which would be zero if all contacts were active and rolling.

There are often multiple solutions for piUnknown; consult the documentation for particular ImpulseSolver implementations to determine which solution is returned. Possibilities include: any solution (PGS), and the least squares solution (PLUS).

Member Enumeration Documentation

◆ ContactType


◆ UniCond


◆ FricCond


◆ BndCond


Constructor & Destructor Documentation

◆ ImpulseSolver()

SimTK::ImpulseSolver::ImpulseSolver ( Real  roll2slipTransitionSpeed,
Real  convergenceTol,
int  maxIters 

◆ ~ImpulseSolver()

virtual SimTK::ImpulseSolver::~ImpulseSolver ( )

Member Function Documentation

◆ setMaxRollingSpeed()

void SimTK::ImpulseSolver::setMaxRollingSpeed ( Real  roll2slipTransitionSpeed)

◆ getMaxRollingSpeed()

Real SimTK::ImpulseSolver::getMaxRollingSpeed ( ) const

◆ setConvergenceTol()

void SimTK::ImpulseSolver::setConvergenceTol ( Real  tol)

◆ getConvergenceTol()

Real SimTK::ImpulseSolver::getConvergenceTol ( ) const

◆ setMaxIterations()

void SimTK::ImpulseSolver::setMaxIterations ( int  maxIts)

◆ getMaxIterations()

int SimTK::ImpulseSolver::getMaxIterations ( ) const

◆ clearStats() [1/2]

void SimTK::ImpulseSolver::clearStats ( ) const

◆ clearStats() [2/2]

void SimTK::ImpulseSolver::clearStats ( int  phase) const

◆ solve()

virtual bool SimTK::ImpulseSolver::solve ( int  phase,
const Array_< MultiplierIndex > &  participating,
const Matrix A,
const Vector D,
const Array_< MultiplierIndex > &  expanding,
Vector piExpand,
Vector verrStart,
Vector verrApplied,
Vector pi,
Array_< UncondRT > &  unconditional,
Array_< UniContactRT > &  uniContact,
Array_< UniSpeedRT > &  uniSpeed,
Array_< BoundedRT > &  bounded,
Array_< ConstraintLtdFrictionRT > &  consLtdFriction,
Array_< StateLtdFrictionRT > &  stateLtdFriction 
) const
pure virtual

◆ solveBilateral()

virtual bool SimTK::ImpulseSolver::solveBilateral ( const Array_< MultiplierIndex > &  participating,
const Matrix A,
const Vector D,
const Vector rhs,
Vector pi 
) const
pure virtual

Solve a set of bilateral (unconditional) constraints for the impulse necessary to enforce them.

This can be used for projecting a set of violated active constraints onto their manifold. This just solves the linear system

    P*(A+D)*~P P*pi = P*rhs 
            Pbar*pi = 0

where P is a pXm "participation" matrix such that P(i,j)=1 if constraint j is the i'th active constraint, zero otherwise, and Pbar is the "nonparticipation" matrix such that Pbar(i,j)=1 if constraint j is the i'th inactive constraint, zero otherwise. A is mXm symmetric, positive semidefinite, but may be rank deficient. D is an mXm diagonal matrix with only nonnegative elements. The returned solution pi (mX1) should ideally be the solution of minimum 2-norm ||pi|| if the system is underdetermined, or the solution that minimizes the 2-norm of the error ||(A+D)pi-rhs|| (participating part only) if the solution is overdetermined and inconsistent. However, concrete ImpulseSolvers are free to return a different solution provide their behavior is well documented. The method used should be qualitatively similar to that used by the solve() method for the same concrete ImpulseSolver. For example, if solve() uses an iterative method then this should also do so.

Implemented in SimTK::PGSImpulseSolver, and SimTK::PLUSImpulseSolver.

◆ getContactTypeName()

static const char* SimTK::ImpulseSolver::getContactTypeName ( ContactType  ct)

◆ getUniCondName()

static const char* SimTK::ImpulseSolver::getUniCondName ( UniCond  uc)

◆ getFricCondName()

static const char* SimTK::ImpulseSolver::getFricCondName ( FricCond  fc)

◆ getBndCondName()

static const char* SimTK::ImpulseSolver::getBndCondName ( BndCond  bc)

◆ dumpUniContacts()

static void SimTK::ImpulseSolver::dumpUniContacts ( const String msg,
const Array_< UniContactRT > &  uniContacts 

Member Data Documentation

◆ MaxNumPhases

const int SimTK::ImpulseSolver::MaxNumPhases = 3

◆ m_maxRollingTangVel

Real SimTK::ImpulseSolver::m_maxRollingTangVel

◆ m_convergenceTol

Real SimTK::ImpulseSolver::m_convergenceTol

◆ m_maxIters

int SimTK::ImpulseSolver::m_maxIters

◆ m_nSolves

long long SimTK::ImpulseSolver::m_nSolves[MaxNumPhases]

◆ m_nIters

long long SimTK::ImpulseSolver::m_nIters[MaxNumPhases]

◆ m_nFail

long long SimTK::ImpulseSolver::m_nFail[MaxNumPhases]

◆ m_nBilateralSolves

long long SimTK::ImpulseSolver::m_nBilateralSolves

◆ m_nBilateralIters

long long SimTK::ImpulseSolver::m_nBilateralIters

◆ m_nBilateralFail

long long SimTK::ImpulseSolver::m_nBilateralFail

The documentation for this class was generated from the following file: