# Class ContactSim

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 barely prevent 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

• ParameterString named `EXTRA_ACCEL`, see setExtraAccel

See also the ImpulseSim super class for additional Parameters.

# Background and References

See explanations at:

The algorithm used here is based on these papers:

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 close to the edge of the other body, as specified by `getDistanceTol()`.

• the bodies must be moving very slowly relative 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

``````a = A f + b
``````

where

• `a =` vector of accelerations
• `A =` matrix describing how the `j`-th contact force affects the acceleration of the `i`-th contact 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:

``````a1     a11  a12  a13   0    0     f1     b1
a2     a21  a22  a23   0    0     f2     b2
a3  =  a31  a32  a33  a34   0  *  f3  +  b3
a4      0    0   a43  a44  a45    f4     b4
a5      0    0    0   a54  a55    f5     b5
``````

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

``````a1 = a11*f1 + a12*f2 + a13*f3 + 0*f4 + 0*f5 + b1
``````

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:

``````a >= 0
f >= 0
a.f = 0
``````

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 separates

• No 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 forces to 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 did not find 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.

## Properties

bods_: RigidBody[] = []

The RigidBodys in this simulation.

collisionAccuracy_: 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.

#### Type declaration

• (c, t): void

#### Returns void

computeForces_: ComputeForces

'C' for ContactSim

contactCount_: number = 0

number of recent contacts, for debugging

contactDepth_: number = 0

sum of depth of recent contacts, for debugging

debugPaint_: 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

debugPrintTime_: number = 0

time when last printed number of contacts

extraAccelTimeStep_: 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.

extra_accel_: ExtraAccel = ExtraAccel.VELOCITY_AND_DISTANCE_JOINTS

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`

forceHistoryIndex_: number = 0

for debugging

forceHistory_: number[] = ...

for debugging

forceLaws_: ForceLaw[] = []

The ForceLaws in this simulation.

maxForce_: number = 0

the maximum force calculated between contacts. For testing.

numContacts_: number = 0

gives current max size of contact subset, for debugging

showForces_: boolean = false

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

simList_: SimList = ...

The SimList holds SimObjects so they can be made visible.

simRNG_: Random = ...

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

simRect_: null | DoubleRect = null

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

varsList_: VarsList

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

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.

DEBUG_IMPULSE: false = false

Show the impulse applied at each collision.

ELASTICITY_SET: string = 'ELASTICITY_SET'

Name of event broadcast from setElasticity.

SHOW_CONTACTS: false = false

When `true`, write to debug console detail on all contacts found

SHOW_NUM_CONTACTS: false = false

When `true`, write to debug console number of contacts found

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.

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.

TINY_IMPULSE: 1e-12 = 1E-12

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

## Methods

• 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

• 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

• ##### connector: Connector

the Connector to add

• ##### `Optional`follow: null | Connector

add new Connector into list after this Connector; if null then add at front of list; if undefined, add at end of list

#### Throws

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

• 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

• 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

#### Throws

if adding a second DampingLaw or GravityLaw

• 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

• Adds the Parameter to the list of this Subject's available Parameters.

#### Parameters

• ##### parameter: Parameter

the Parameter to add

#### Throws

if a Parameter with the same name already exists.

• 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

• 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

• 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

• 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

#### Throws

if there is no Parameter with the given name

• #### Parameters

• ##### vars: number[]

the current array of state variables (input)

• ##### change: number[]

array of change rates for each variable (output)

#### Returns void

• 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.

#### Returns number[]

• 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

• 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: number

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

#### Returns void

• Creates a ConcreteLine 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

• ##### pa: Vector

starting point of the line

• ##### pb: Vector

ending point of the line

• ##### `Optional`expireTime: number

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

#### Returns void

• 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.

• 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

• Returns string showing current variables of each RigidBody, for debugging.

#### Returns string

string showing current variables of each RigidBody, for debugging.

• 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.

• 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)

• Returns distance tolerance used to determine if an object is in contact with another object

#### Returns number

distance tolerance used to determine if an object is in contact with another object

• 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

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

#### Returns number

the approximate length of a time step

• Returns the maximum force calculated between contacts.

#### Returns number

• For debugging, returns the number of contacts in the biggest subset of contacts that are all interrelated.

#### Returns number

number of contacts in the biggest subset of contacts that are all interrelated

• Returns the Parameter with the given name.

#### Parameters

• ##### name: string

the language-independent or English name of the Parameter

#### Returns Parameter

the Parameter with the given name

#### Throws

if there is no Parameter with the given name

• 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

• 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

• 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

• 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

• Returns velocity tolerance used to determine if an object is in contact with another object

#### Returns number

velocity tolerance used to determine if an object is in contact with another object

• 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: CollisionTotals

CollisionTotals object to update with number of collisions handled

#### Returns boolean

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

• 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`

• 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

• 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

• Removes the Connector from the list of active Connectors. If the Connector is also a SimObject, then removes it from the SimList.

#### Parameters

• ##### connector: Connector

the Connector to remove

#### Returns void

• 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

• Removes imminent collisions from the given set of contacts/collisions.

#### Parameters

• ##### contactsFound: RigidBodyCollision[]

the set of contacts/collisions to modify

#### Returns 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

• Removes the Parameter from the list of this Subject's available Parameters.

#### Parameters

• ##### parameter: Parameter

the Parameter to remove

#### Returns void

• 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

• 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

#### Throws

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

• 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

• Sets the collision handling method to use,

#### Parameters

• ##### value: CollisionHandling

the collision handling method to use

#### Returns void

• For debugging, specify a function that will paint canvases, so that you can see the simulation while stepping thru with debugger.

#### Parameters

• ##### fn: null | (() => void)

function that will paint canvases

#### Returns void

• Sets distance tolerance to use to determine if an object is in contact with another object

#### Parameters

• ##### value: number

distance tolerance to use to determine if an object is in contact with another object

#### Returns 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.

#### Throws

if there are no RigidBodys

• 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

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

#### Parameters

• ##### value: number

the approximate length of a time step

#### Returns void

• 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

• 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

• Sets whether to add Forces to the SimList so they can be seen.

#### Parameters

• ##### value: boolean

whether to add Forces to the SimList so they can be seen

#### Returns 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

• Sets velocity tolerance to use to determine if an object is in contact with another object

#### Parameters

• ##### value: number

velocity tolerance to use to determine if an object is in contact with another object

#### Returns void

• 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.

• 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.

#### Returns Float64Array[]

Generated using TypeDoc