- ImpulseSim
- ContactSim

bods_
collisionAccuracy_
collisionFunction_
computeForces_
contactCount_
contactDepth_
debugPaint_
debugPrintTime_
extraAccelTimeStep_
extra_accel_
forceHistoryIndex_
forceHistory_
forceLaws_
maxForce_
numContacts_
showForces_
simList_
simRNG_
simRect_
varsList_
COLLISIONS_DISABLED
DEBUG_IMPULSE
ELASTICITY_SET
SHOW_CONTACTS
SHOW_NUM_CONTACTS
SMALL_IMPULSE
SUBSET_COLLISIONS
TINY_IMPULSE

addBody
addConnector
addConnectors
addForceLaw
addObserver
addParameter
alignConnectors
applyContactForce
applyForce
broadcast
broadcastParameter
calcContactForces
calculate_b_vector
cleanSlate
clearForceLaws
debugCircle
debugLine
evaluate
findCollisions
formatVars
getBodies
getBody
getBroadcast
getClassName
getCollisionAccuracy
getCollisionHandling
getConnectors
getDistanceTol
getEnergyInfo
getExtraAccel
getExtraAccelTimeStep
getForceLaws
getMaxForce
getName
getNumContacts
getObservers
getPEOffset
getParameter
getParameterBoolean
getParameterNumber
getParameterString
getParameters
getRandomSeed
getShowCollisions
getShowForces
getSimList
getSimRect
getTime
getVarsList
getVelocityTol
handleCollisions
makeCollisionMatrix
modifyObjects
myPrint
removeBody
removeConnector
removeForceLaw
removeNonContacts
removeObserver
removeParameter
reset
restoreState
saveInitialState
saveState
setBroadcast
setCollisionAccuracy
setCollisionFunction
setCollisionHandling
setDebugPaint
setDistanceTol
setElasticity
setExtraAccel
setExtraAccelTimeStep
setPEOffset
setRandomSeed
setShowCollisions
setShowForces
setSimRect
setTerminal
setVelocityTol
toString
toStringShort
toString_
calculate_a_matrix

- new
Contact (opt_name?): ContactSimSim #### Parameters

`Optional`

opt_name: stringname of this Subject

#### Returns ContactSim

`Protected`

bods_The RigidBodys in this simulation.

`Protected`

collisioncollisionAccuracy_ : number = 0.6

How close in space we need to be to a collision, to decide to handle it, as a percentage of the targetGap = distanceTol/2.

collisionFunction_ : null | ((c, t) => void) = null

Function to print collisions, or null to turn off printing collisions.

- (c, t): void
#### Parameters

#### Returns void

`Private`

compute'C' for ContactSim

`Private`

contactcontactCount_ : number = 0

number of recent contacts, for debugging

`Private`

contactcontactDepth_ : number = 0

sum of depth of recent contacts, for debugging

`Protected`

debugdebugPaint_ : null | (() => void) = null

Function to paint canvases, for debugging. If defined, this will be called within
`moveObjects()`

so you can see the simulation state after each
time step (you will need to arrange your debugger to pause after
each invocation of debugPaint_ to see the state).

- (): void
#### Returns void

`Private`

debugdebugPrintTime_ : number = 0

time when last printed number of contacts

`Private`

extraextraAccelTimeStep_ : number = 0.025

The approximate length of a time step, used to find extra acceleration needed to keep contact points at the proper distance apart.

`Private`

extra_the method to use for calculating extra acceleration added to
eliminate small amount of remaining velocity at a contact or joint. The option
`ExtraAccel.VELOCITY_AND_DISTANCE`

reduces both the distance and velocity at a
contact to zero.

NOTE June 26 2014: previously the default was `ExtraAccel.VELOCITY`

Sept 5 2016: previous default was `ExtraAccel.VELOCITY_AND_DISTANCE`

`Private`

forceforceHistoryIndex_ : number = 0

for debugging

`Private`

forceforceHistory_ : number[] = ...

for debugging

`Protected`

forceThe ForceLaws in this simulation.

`Private`

maxmaxForce_ : number = 0

the maximum force calculated between contacts. For testing.

`Private`

numnumContacts_ : number = 0

gives current max size of contact subset, for debugging

`Protected`

showshowForces_ : boolean = false

Whether to add Forces to the SimList so they can be seen.

`Protected`

simThe SimList holds SimObjects so they can be made visible.

`Protected`

simRNG_The pseudo random number generator, used in collision handling and computing forces.

`Protected`

simSuggested size for the SimView. This is mainly for tests to communicate with TestViewerApp.

`Protected`

varsThe variables that determine the state of the simulation; there are six variables for each RigidBody, plus some others for time, energy, etc.

`Static`

`Readonly`

COLLISIONS_COLLISIONS_DISABLED : false = false

For debugging, this allows code to look for collisions, but does not actually return them. This allows to debug code for finding nearest point between objects.

`Static`

`Readonly`

DEBUG_DEBUG_IMPULSE : false = false

Show the impulse applied at each collision.

`Static`

ELASTICITY_ELASTICITY_SET : string = 'ELASTICITY_SET'

Name of event broadcast from setElasticity.

`Static`

`Readonly`

SHOW_SHOW_CONTACTS : false = false

When `true`

, write to debug console detail on all contacts found

`Static`

`Readonly`

SHOW_SHOW_NUM_CONTACTS : false = false

When `true`

, write to debug console number of contacts found

`Static`

`Readonly`

SMALL_SMALL_IMPULSE : 0.0001 = 1E-4

Impulse smaller than this is not marked as a discontinuous change in the velocity variables of the objects colliding.

`Static`

SUBSET_SUBSET_COLLISIONS : boolean = true

Find subsets of related contacts to solve each subset separately for contact forces.
This feature is useful for cases where there are a lot of contacts that are in separate
groups (two piles) because the matrices being solved are smaller. The ComputeForces
algorithm is `O(n^4)`

. For example suppose there are 40 contact points. The cost of
`40^4 = 2,560,000`

is far greater than `20^4 + 20^4 = 320,000`

. There is some overhead
to finding the subsets, so this can lose time when there is just a big single pile.

`Static`

`Readonly`

TINY_TINY_IMPULSE : 1e-12 = 1E-12

Impulse smaller than this is regarded as insignificant at various points in the collision handling algorithm.

- add
Body (body): void Add the RigidBody to the simulation and SimList, and add a set of 6 variables for the RigidBody to the VarsList.

Using FunctionVariable's ensures that the variables on the VarsList have the same values as the RigidBody's (because the FunctionVariables retrieve and store their values in the RigidBody's). There is no need for a separate step to coordinate between the VarsList and the RigidBody's, they are automatically in sync.

#### Parameters

##### body: RigidBody

RigidBody to add to the simulation

#### Returns void

- add
Connector (connector, follow?): void Adds a Connector to the list of active Connectors and to the SimList. The RigidBodys of the Connector must already have been added to this ContactSim, unless it is a Scrim. Note that the order of the list of Connectors is significant, see alignConnectors.

#### Parameters

#### Returns void

#### Throws

if RigidBodys of the Connector have not been added to this ContactSim

- add
Connectors (connectors): void Adds the set of Connectors. Note that the ordering of the Connectors is important because the Connectors are aligned in list order.

#### Parameters

##### connectors: Connector[]

set of Connectors to add

#### Returns void

- add
Force (forceLaw): voidLaw Adds the ForceLaw to the list of ForceLaws operating in this simulation, if it is not already on the list.

#### Parameters

##### forceLaw: ForceLaw

the ForceLaw to add

#### Returns void

#### Throws

if adding a second DampingLaw or GravityLaw

- add
Observer (observer): void Adds the given Observer to this Subject's list of Observers, so that the Observer will be notified of changes in this Subject. An Observer may call

`Subject.addObserver`

during its`observe`

method.#### Parameters

##### observer: Observer

the Observer to add

#### Returns void

- add
Parameter (parameter): void Adds the Parameter to the list of this Subject's available Parameters.

#### Parameters

##### parameter: Parameter

the Parameter to add

#### Returns void

#### Throws

if a Parameter with the same name already exists.

- align
Connectors (): void Aligns all Connectors. This is generally done only during set up of initial conditions of the simulation, or whenever a Connector is being created.

Note that the order of the bodies within a Joint is significant because

`Joint.align()`

usually moves the second body to align with first body. Also, the ordering within the list of Connectors is significant because the Connectors are aligned in list order.#### Returns void

`Private`

apply- apply
Contact (c, f, change): voidForce Applies a normal force at the contact point. Result is modification of the rigid body accelerations in the change vector. Also the Force objects are added to the SimList for display purposes when the 'show forces' flag is on.

The impact point(s) given in the contact only affect the angular acceleration of the objects, not the linear acceleration. Curiously, the impact point can be anywhere along the line normal to the impact point with the same result. Because the angular acceleration changes by the cross product of the force and the vector from center of mass to impact point:

`R x F`

. If you change`R`

by adding a multiple`n`

of`F`

there is no change:`(R + n F) x F = R x F + n F x F = R x F + 0`

. This is why it doesn't matter which side of the gap that we assign the impact point for the collision.We use

`R`

vector here, not`U`

vector. The force is applied at the point of contact, not at the center of the circle for a circular edge. The`U`

vector is used for calculating the velocity of the gap distance -- which went into the`b`

-vector, and therefore determined the amount of force. The`U`

vector is also used for calculating the`A`

matrix. We could use the`U`

vector here, but it would give the same result because`U = R + n F`

, see the section*Equivalence of Using R or U Vector For Normal Velocity*in RigidBodyCollision.We entirely skip making (and therefore displaying) the forces for a fixed (infinite mass) body. The reason is that those forces won't affect the simulation because the fixed body cannot move. We could let those forces thru if desired.

#### Parameters

##### c: RigidBodyCollision

the contact point where the force is to be applied

##### f: number

the magnitude of the normal force

##### change: number[]

vector of rigid body accelerations

#### Returns void

`Protected`

apply- apply
Force (change, force): void Applies the Force by modifying the array representing rate of change of each variable. The Force specifies which RigidBody it works on so we can figure out which variable rates to modify. If showForces_ is

`true`

, adds the Force to the SimList with an immediate expiration time.#### Parameters

##### change: number[]

vector of rigid body accelerations

##### force: Force

the Force to be applied

#### Returns void

- broadcast(evt): void
Notifies all Observers that this Subject has changed by calling observe on each Observer.

An Observer may call addObserver or removeObserver during its

`observe`

method.#### Parameters

##### evt: SubjectEvent

a SubjectEvent with information relating to the change

#### Returns void

- broadcast
Parameter (name): void Notifies all Observers that the Parameter with the given name has changed by calling observe on each Observer.

#### Parameters

##### name: string

the language-independent or English name of the Parameter that has changed

#### Returns void

#### Throws

if there is no Parameter with the given name

`Private`

calc- calc
Contact (vars, change, subset): voidForces #### Parameters

##### vars: number[]

the current array of state variables (input)

##### change: number[]

array of change rates for each variable (output)

##### subset: RigidBodyCollision[]

#### Returns void

`Private`

calculate_- calculate_
b_ (contacts, change, vars): number[]vector Calculates the

`b`

vector which specifies how external forces (like gravity, thrust, etc) affect acceleration of contact points.See Calculate the

`b`

Vector in the document about ContactSim math.## Old Notes -- Do Not Trust

(Sept 2015: don't trust these old notes!)

New extra acceleration calculation (March 2, 2012). See note below from Nov 2014 about a modification of this calculation.

`let x be the joint gap. xâ€™ = v, xâ€™â€™ = a. Integrating: xâ€™ = a t + v_0; x = a t^2/2 + v_0 t + x_0 ideally we find accel that both stops velocity and brings the gap to zero: 0 = a h^2/2 + v_0 h + x_0 0 = a h + v_0 we canâ€™t satisfy both those equations, but we can maybe find something in the middle? we know h, need to find a. a = -(v_0 h + x_0)2/h^2 a = -v_0/h what is the average of these? -(2 v_0 h + x_0) /h^2 (note that we put the opposite of this into b vector)`

I tested the relationship between the time step

`h`

and the divisor`q`

used in finding the extra acceleration`a`

, where`a = v / q`

. (This was October 2011). I found that instability occurs when`h > 2 q`

for Runge Kutta solver, and when`h > q`

for modified Euler solver. This makes sense because RK averages 4 sub-steps and in a sense the time step used is actually`h/2`

. Whereas modified Euler averages 2 sub-steps that are`h`

apart. It also makes sense because the integral above is over a single time step`h`

, so if you are integrating over significantly longer time then you would overshoot and the velocity would be reduced too much.Extra acceleration and reusing collisions: It would make more sense to take the velocity at the start of the RK step and use that starting velocity value to calculate an extra acceleration that is used for all the sub-steps of the RK step. Then you would wind up reducing the velocity to zero over that time step. Instead, what we do currently is recalculate the extra acceleration in each sub-step, based on the current simulation state (velocity) in that sub-step. This seems to be less effective in reducing the velocity -- it takes more steps to get to zero velocity. However, I tried an experiment (October 2011) that didn't work out so well. I tried to reuse the collisions, so that the same collision is used for all the RK sub-steps and so have the same velocity used in each sub-step. The results were inconsistent, and re-using the collisions has other effects.

Note about joints: from doing a quick test with DoublePendulumCompareBuilder it seems that you can get almost as good results for joints by turning off the 'generate tiny collisions at each step' code in CollisionSim and turning on the 'extra acceleration to eliminate velocity' code here for joints. This might be useful if you want to avoid the extra work in each step for handling those tiny collisions. As long as we do the 'tiny collisions for joints', we ensure that velocity at joints is zero, and therefore don't need to do the "extra acceleration to eliminate velocity" kluge for joints.

#### Parameters

##### contacts: RigidBodyCollision[]

##### change: number[]

##### vars: number[]

#### Returns number[]

- clean
Slate (): void Removes all RigidBodys, ForceLaws, most Variables, and clears the SimList. This is used in applications to build a new configuration of RigidBodys. This should give essentially the same state that you would get from making a new RigidBodySim, except for parameters (like gravity) that may have been changed.

The alternative is to create a new RigidBodySim; that would be 'cleaner' but then you must unhook the old RigidBodySim from all the various user controls and graph and such, and hook up the new one.

#### Returns void

- debug
Circle (name, center, radius, expireTime?): void Creates a PointMass which is displayed as a circle, and adds it to the SimList, for debugging only. The expiration time on temporary SimObjects is set to 'now', so that they are removed right away during the next call to advance().

#### Parameters

##### name: string

name of the SimObject that is created

##### center: GenericVector

center of the circle

##### radius: number

radius of the circle

`Optional`

expireTime: numberthe time when the DisplayObject will be removed; the default expireTime is 'now'.

#### Returns void

- evaluate(vars, change, timeStep): null | object
Defines the differential equations of this ODESim; for an input set of variables, returns the current rate of change for each variable (the first derivative of each variable with respect to time).

The

`timeStep`

is the time since the state variables were last fully calculated, which can be and often is zero. The current time can be regarded as`getTime() + timeStep`

. The input variables correspond to the Simulation state at that time. Note that`timeStep`

is different from the time step used to advance the Simulation (as in AdvanceStrategy.advance). The`timeStep`

is typically used when finding collisions in CollisionSim.findCollisions.#### Parameters

##### vars: number[]

the current array of state variables (input), corresponding to the state at

`getTime() + timeStep`

##### change: number[]

array of change rates for each variable (output), all values are zero on entry.

##### timeStep: number

the current time step (might be zero)

#### Returns null | object

`null`

if the evaluation succeeds, otherwise an object relating to the error that occurred. The`change`

array contains the output results.

- find
Collisions (collisions, vars, stepSize): void Finds collisions based on the passed in state variables. Can rely on modifyObjects having been called prior, with this set of state variables. Uses the state saved by saveState as the 'before' state for comparison.

The list of collisions that are passed in can potentially have collisions from the near future that were found previously. The CollisionSim should avoid adding collisions that are duplicates of those already on the list.

#### Parameters

##### collisions: RigidBodyCollision[]

the list of collisions to add to

##### vars: number[]

the current array of state variables

##### stepSize: number

the size of the current time step, in seconds

#### Returns void

- get
Body (numOrName): RigidBody Returns a RigidBody in this simulation by specifying its name or index in the list of RigidBodys.

#### Parameters

##### numOrName: string | number

index in list of RigidBodys or name of the RigidBody (either the English or language-independent version of the name)

#### Returns RigidBody

the RigidBody with the given name or at the given position in the list of RigidBodys

#### Throws

if requesting a non-existing body.

`Protected`

get- get
Broadcast (): boolean Returns whether broadcasting is enabled for this Subject. See setBroadcast.

#### Returns boolean

whether broadcasting is enabled for this Subject

- get
Collision (): numberAccuracy Returns the collision distance accuracy, a fraction between zero and one; when the collision distance is within

`accuracy * targetGap`

of the target gap distance, then the collision is considered close enough to handle (apply an impulse).#### Returns number

the collision accuracy, a fraction between 0 (exclusive) and 1 (inclusive)

- get
Collision (): CollisionHandlingHandling Returns the collision handling method being used.

#### Returns CollisionHandling

the collision handling method being used

- get
Energy (): EnergyInfoInfo Returns the current EnergyInfo for this system.

#### Returns EnergyInfo

an EnergyInfo object representing the current energy of this system.

- get
Extra (): ExtraAccelAccel Returns the method to use for calculating extra acceleration added to eliminate small amount of remaining velocity at a contact.

#### Returns ExtraAccel

the method to use for calculating extra acceleration

- get
Parameter (name): ParameterBooleanBoolean Returns the ParameterBoolean with the given name.

#### Parameters

##### name: string

the language-independent or English name of the ParameterBoolean

#### Returns ParameterBoolean

the ParameterBoolean with the given name

#### Throws

if there is no ParameterBoolean with the given name

- get
Parameter (name): ParameterNumberNumber Returns the ParameterNumber with the given name.

#### Parameters

##### name: string

the language-independent or English name of the ParameterNumber

#### Returns ParameterNumber

the ParameterNumber with the given name

#### Throws

if there is no ParameterNumber with the given name

- get
Parameter (name): ParameterStringString Returns the ParameterString with the given name.

#### Parameters

##### name: string

the language-independent or English name of the ParameterString

#### Returns ParameterString

the ParameterString with the given name

#### Throws

if there is no ParameterString with the given name

- get
Random (): numberSeed Returns the seed of the pseudo random number generator (RNG) used in this simulation. The RNG is used during collision handling and contact force calculation. To get reproducible results, set this seed at the start of a simulation, and the RNG will then always give the same sequence of random numbers.

#### Returns number

the seed of the pseudo random number generator

- get
Sim (): null | DoubleRectRect Returns the suggested size for the SimView. This is mainly for tests to communicate with test/TestViewerApp.TestViewerApp.

#### Returns null | DoubleRect

suggested size for the SimView

- handle
Collisions (rbcs, opt_totals?): boolean Adjusts the simulation state based on the given Collisions. For example, this might reverse the velocities of objects colliding against a wall. The simulation state is contained in the

`vars`

array of state variables from getVarsList.Note that these Collisions will typically be from the very near future; CollisionAdvance backs up to just before the moment of collision before handling Collisions.

#### Parameters

##### rbcs: RigidBodyCollision[]

the list of current collisions

`Optional`

opt_totals: CollisionTotalsCollisionTotals object to update with number of collisions handled

#### Returns boolean

true if was able to handle the collision, changing state of simulation.

`Protected`

make- make
Collision (collisions): Float64Array[]Matrix Returns a matrix where the

`(i, j)`

th entry is how much the relative normal velocity at collision`i`

will change from a unit impulse being applied at collision`j`

.**TO DO**it is a symmetric matrix, so we could save time by only calculating upper triangle and then copying to lower triangle.**TO DO**this is the same as ContactSim.calculate_a_matrix, so we need to use just one of these (duplicate code currently). March 2012.#### Parameters

##### collisions: RigidBodyCollision[]

list of RigidBodyCollisions

#### Returns Float64Array[]

matrix that tells how much impulse at collision point

`i`

affects relative normal velocity at collision point`j`

- my
Print (message, ...colors): void Prints the message to console, preceded by the current simulation time. Draws the time in green, the message in black; you can add colors in the message by adding more '%c' symbols in the message string and pass additional colors.

#### Parameters

##### message: string

message to print, optionally with '%c' where color changes are desired

`Rest`

...colors: string[]CSS color or background strings, to change the color in the message at points in the message marked by the string '%c'

#### Returns void

- remove
Body (body): void Removes the RigidBody from the simulation, and any Connectors that were attached to it.

#### Parameters

##### body: RigidBody

RigidBodys to remove from the simulation

#### Returns void

- remove
Force (forceLaw): booleanLaw Removes the ForceLaw from the list of ForceLaws operating in this simulation.

#### Parameters

##### forceLaw: ForceLaw

the ForceLaw to remove

#### Returns boolean

whether the ForceLaw was removed

`Private`

remove- remove
Non (contactsFound): voidContacts Removes imminent collisions from the given set of contacts/collisions.

#### Parameters

##### contactsFound: RigidBodyCollision[]

the set of contacts/collisions to modify

#### Returns void

- remove
Observer (observer): void Removes the Observer from this Subject's list of Observers. An Observer may call

`removeObserver`

during its`observe`

method.#### Parameters

##### observer: Observer

the Observer to detach from list of Observers

#### Returns void

- remove
Parameter (parameter): void Removes the Parameter from the list of this Subject's available Parameters.

#### Parameters

##### parameter: Parameter

the Parameter to remove

#### Returns void

- reset(): void
Sets the Simulation back to its initial conditions, see saveInitialState, and calls modifyObjects. Broadcasts event named 'RESET'.

#### Returns void

- restore
State (): void Restores the Simulation state that was saved with saveState.

#### Returns void

- save
Initial (): voidState Saves the current variables and time as the initial state, so that this initial state can be restored with reset. Broadcasts event named 'INITIAL_STATE_SAVED'.

#### Returns void

- save
State (): void Saves the current state of the Simulation, so that we can back up to this state later on. The state is defined mainly by the set of Simulation variables, see getVarsList, but can include other data. This state is typically used for collision detection as the

*before collision*state, see CollisionSim.findCollisions.#### Returns void

`Protected`

set- set
Broadcast (value): boolean Sets whether this Subject will broadcast events, typically used to temporarily disable broadcasting. Intended to be used in situations where a subclass overrides a method that broadcasts an event. This allows the subclass to prevent the superclass broadcasting that event, so that the subclass can broadcast the event when the method is completed.

#### Parameters

##### value: boolean

whether this Subject should broadcast events

#### Returns boolean

the previous value

- set
Collision (value): voidAccuracy Sets the collision distance accuracy, a fraction between zero and one; when the collision distance is within

`accuracy * targetGap`

of the target gap distance, then the collision is considered close enough to handle (apply an impulse).#### Parameters

##### value: number

how close in distance to be in order to handle a collision

#### Returns void

#### Throws

if value is out of the range 0 to 1, or is exactly zero

- set
Collision (f): voidFunction Sets a function for printing collisions. The function is called for each collision that occurs. The function takes two variables: a RigidBodyCollision and a Terminal. This can be defined from within the Terminal by the user. Here is an example function (FastBallApp is a good place to try it).

`sim.setCollisionFunction(function(c,t) {`

const s = c.getDetectedTime().toFixed(2)+"\t"

+c.getImpulse().toFixed(2)+"\t"

+c.getPrimaryBody().getName()+"\t"

+c.getNormalBody().getName();

t.println(s);

})#### Parameters

##### f: null | ((c, t) => void)

the function to print collisions, or null to turn off printing collisions

#### Returns void

- set
Collision (value): voidHandling Sets the collision handling method to use,

#### Parameters

##### value: CollisionHandling

the collision handling method to use

#### Returns void

- set
Elasticity (value): void Sets the elasticity of all RigidBodys to this value. Elasticity is used when calculating collisions; a value of 1.0 means perfectly elastic where the kinetic energy after collision is the same as before (extremely bouncy), while a value of 0 means no elasticity (no bounce).

Broadcasts an 'ELASTICITY_SET' event.

#### Parameters

##### value: number

elasticity to set on all RigidBodys, a number from 0 to 1.

#### Returns void

#### Throws

if there are no RigidBodys

- set
Extra (value): voidAccel Sets the method to use for calculating extra acceleration added to eliminate small amount of remaining velocity at a contact.

#### Parameters

##### value: ExtraAccel

the method to use for calculating extra acceleration

#### Returns void

- set
Random (value): voidSeed Sets the seed of the pseudo random number generator (RNG) used in this simulation. The RNG is used during collision handling and contact force calculation. To get reproducible results, set this seed at the start of a simulation, and the RNG will then always give the same sequence of random numbers.

#### Parameters

##### value: number

the seed of the pseudo random number generator

#### Returns void

- set
Show (value): voidCollisions Sets whether to show collisions visually. Note that setShowForces will also change whether to show collisions.

#### Parameters

##### value: boolean

whether to show collisions visually.

#### Returns void

- set
Sim (rect): voidRect Sets the suggested size for the SimView. This is mainly for tests to communicate with test/TestViewerApp.TestViewerApp.

#### Parameters

##### rect: null | DoubleRect

the suggested size for the SimView

#### Returns void

- set
Terminal (terminal): void Sets the Terminal object that this simulation can print data into.

#### Parameters

##### terminal: null | Terminal

the Terminal object that this simulation can print data into.

#### Returns void

- to
String (): stringShort Returns a minimal string representation of this object, usually giving just identity information like the class name and name of the object.

For an object whose main purpose is to represent another Printable object, it is recommended to include the result of calling

`toStringShort`

on that other object. For example, calling`toStringShort()`

on a DisplayShape might return something like this:`DisplayShape{polygon:Polygon{'chain3'}}`

#### Returns string

a minimal string representation of this object.

`Static`

`Private`

calculate_- calculate_
a_ (contacts): Float64Array[]matrix Calculates the

`A`

matrix which specifies how contact points react to contact forces. Returns a matrix where the`(i, j)`

th entry is how much the relative normal acceleration at contact`i`

will change from a unit force being applied at contact`j`

.See Calculate the

`A`

Matrix in the document about ContactSim math.**TO DO**it is a symmetric matrix, so we could save time by only calculating upper triangle and then copying to lower triangle.**TO DO**(March 2012) this is the same as ImpulseSim.makeCollisionMatrix, so we need to use just one of these (duplicate code currently). The ImpulseSim version is nicer in how it uses the 'influence' subroutine. However, that version doesn't use the U vector, so need to figure out whether they should both use U vector or not.#### Parameters

##### contacts: RigidBodyCollision[]

#### Returns Float64Array[]

Generated using TypeDoc

Physics engine for rigid bodies with contact forces to allow resting contact. The contact forces prevent the bodies from interpenetrating when they are in resting contact. Resting contact means the bodies are not colliding, but have edges and corners that are in continuous contact and exerting force on each other.

The overall idea is to calculate the exact amount of force needed to

just barelyprevent the objects from penetrating. These contact forces are calculated in the evaluate method, which is called by the DiffEqSolver at the request of the AdvanceStrategy to advance the state of the simulation.## Parameters Created

`EXTRA_ACCEL`

, see setExtraAccelSee also the ImpulseSim super class for additional Parameters.

## Background and References

See explanations at:

2D Physics Engine Overview

The math and physics underlying RigidBodySim, ImpulseSim and ContactSim are described on the myPhysicsLab website.

ContactSim Math has more details about the math.

The algorithm used here is based on these papers:

David Baraff, Fast Contact Force Computation for Nonpenetrating Rigid Bodies. Computer Graphics Proceedings, Annual Conference Series, 1994; pages 23-34.

David Baraff, An Introduction to Physically Based Modeling: Rigid Body Simulation IIâ€”Nonpenetration Constraints Siggraph '97 Course Notes.

See also the list of David Baraff's papers.

See the paper Curved Edge Physics paper by Erik Neumann for modifications to contact forces when curved edges are involved.

## Find External Forces

Within

`evaluate()`

we first let the super-class apply the external forces to the RigidBody objects. The external forces include things like gravity, thrust, springs, damping. The external forces result in accelerations of the bodies, so at this point many of the bodies would start to penetrate into each other if we did not find contact forces to prevent that.## Find Contacts

Next in

`evaluate()`

we call`findCollisions()`

to find all the contact points, and possibly collisions as well. If we find any actual (penetrating) collisions, then`evaluate()`

returns the set of collisions found, which should then be handled before trying to step forward again, see ImpulseSim.The criteria for finding a contact is:

the corner (or edge) of one body must be

very closeto the edge of the other body, as specified by`getDistanceTol()`

.the bodies must be

moving very slowlyrelative to each other (the normal velocity) at the contact point, as specified by`getVelocityTol()`

.The

`evaluate()`

method optionally finds independent subsets of collisions, because that can make the compute_forces algorithm, which is`O(n^4)`

, run faster in some cases. See the flag SUBSET_COLLISIONS. Collisions are independent when there is no chain of moveable (finite mass) bodies in common between the collisions.## The Matrix Equation for Contact Forces

Now we have the set of contacts and we know the accelerations of the bodies due to external forces. We set up a matrix equation

where

`a =`

vector of accelerations`A =`

matrix describing how the`j`

-th contact force affects the acceleration of the`i`

-thcontact distance(the separation between the bodies)`f =`

vector of contact forces (to be found)`b =`

external forces (gravity, thrust, rubber band, damping)## Set Up the A Matrix

Here is how to set up the

`A`

matrix: For each contact distance`d_i`

, find how the acceleration of that contact distance`d_i''`

is related to the force at the`j`

-th contact point. The force at the`j`

-th contact point is`f_j N_j`

, where`f_j`

is a scalar and`N_j`

is the vector normal. The`a_ij`

entry in the`A`

matrix tells what that relationship is between`f_j`

and`d_i''`

. This`a_ij`

value is dependent only on the current geometry of how the objects are oriented and touching each other.For example, consider Figure 26 of [Baraffs Siggraph 97 Course Notes(../Baraff_Siggraph_97_Course_Notes.pdf) shown above. The figure shows two bodies (B,C) resting on the ground, and a third body (A) resting on top of the other two. There are 5 points of contact among the bodies and the ground. Here is how the matrix equation would look for this situation:

Consider the first contact at

`p1`

which is between the ground and body B. The acceleration of the contact distance at`p1`

is affected by the forces at`p1`

,`p2`

, and`p3`

because all of those forces affect the movement of body B. But the forces at`p4`

and`p5`

have no effect, so their entries are zero in the first row of the`A`

matrix.The first row of the matrix equation can be written out as

That equation says the acceleration of contact distance at point

`p1`

is equal to a certain linear combination of the contact forces`f1`

,`f2`

,`f3`

, plus the acceleration due to the external forces which is`b1`

.The particular values for

`a11, a12, a13`

are dependent on the geometry of the situation: where the forces`f1`

,`f2`

,`f3`

are applied on the body; in what direction do the forces act; where is the center of mass of the body; how the force causes the body to accelerate and spin; where is the point`p1`

is in relation to the center of mass; etc.The third contact at

`p3`

is more complicated because it is affected by any forces acting on body A or body B. These include all the forces except`f5`

. Therefore the third row of the`A`

matrix has four non-zero entries corresponding to the four forces that affect the acceleration at`p3`

.## Constraints On the Solution

Assume we now have the

`b`

vector of external forces and the`A`

matrix of dependencies between contact forces and resulting accelerations of different bodies. We solve for the`f`

vector of contact forces subject to the following constraints:The constraints in words are:

`a >= 0`

we require all the relative normal accelerations (between bodies at contact points) to be either zero (remain in contact) or positive (separating).`f >= 0`

We require contact forces to be zero or positive because they can only push, not pull.`a.f = 0`

The third constraint is a math way of saying that if there is a force, then acceleration is zero OR if there is acceleration (separation), then there is no force.Note that for Joints the constraints are different:

`a == 0`

a Joint always remains in resting contact, it never separatesNo constraint on

`f`

because it can push or pull.## Solving For the Contact Forces

The [Baraff 'Fast Contact Force' paper(../Baraff_Fast_Contact_Force_94.pdf) goes into full detail about the algorithm to solve this constraint problem. Here is a quick summary:

Start by setting all the forces to zero

Add in one force at a time, just enough to maintain the constraints on the points that have been considered so far (ignoring the others), and readjust the other forces as necessary.

Continue adding one force at a time, ignoring points that haven't been considered yet.

Suppose that we are working on adding in the third force after already finding the forces for points 1 and 2. The trick is that we only look at the constraints on the first 3 contact points, we ignore the other contact points and other forces. Once we've found the 3rd force (and rebalanced forces 1 and 2 as needed) we then move on to consider the 4th force.

The last step is to

apply the contact forcesto the bodies, which gives the final set of accelerations that the`evaluate()`

method then returns to the differential equation solver.## Extra Acceleration

The contact forces are calculated so that there is zero acceleration at contact points; but this does not immediately affect the remaining small velocity at a contact point. As a result, objects that are in resting contact will often have some undesirable jittery motion.

One way to deal with this is to request a small amount of additional acceleration which will eliminate that velocity over a few time steps. If the objects are moving towards each other (a small negative velocity) we request a little more acceleration which leads to a little more force being applied there. If the objects are moving apart (a small positive velocity) we request a little less acceleration.

The extra acceleration is added to the

`b`

vector in the private method`calculate_b_vector`

. See ExtraAccel enum for explanations of the various options. See setExtraAccel for how to specify the desired ExtraAccel option.## Intermediate Steps During evaluate()

A DiffEqSolver works by 'averaging' several calculated states for each time step; for example ModifiedEuler averages 2 states, and RungeKutta averages 4 states. The collision detection done in

`evaluate()`

is based on those intermediate states within a step of the DiffEqSolver, so it is arguable whether that state actually ever occurs.This point of view argues for only using the collisions detected between full steps of the DiffEqSolver. However, contacts can come and go during these sub-steps so it seems in practice to be more accurate to find the set of contacts anew in each call to

`evaluate()`

. Also if a penetrating collision is detected we need to stop the process and handle that collision instead, so it is important to do collision detection for that as well.Prior to February 2012, there was an experimental option specified by the flag

`REUSE_COLLISIONS`

for which we didnotfind the collisions anew in the`evaluate()`

method, instead we used the collisions found outside the`evaluate()`

method during`AdvanceStrategy.advance()`

which are based on a complete ODE step. See the git archive.