pagoda.cooper.World¶
-
class
pagoda.cooper.
World
(dt=0.016666666666666666, max_angular_speed=20)[source]¶ Simulate a physics world that includes an articulated skeleton model.
The “cooper” method, originally described by Cooper & Ballard (2012 Proc. Motion in Games), uses a forward physics simulator (here, the Open Dynamics Engine; ODE) to compute inverse motion quantities like angles and torques using motion-capture data and a structured, articulated model of the human skeleton. The prerequisites for this method are:
- Record some motion-capture data from a human. This is expected to result in the locations, in world coordinates, of several motion-capture markers at regularly-spaced intervals over time.
- Construct a simulated skeleton that matches the size and shape of the human to some reasonable degree of accuracy. The more accurate the skeleton, the more accurate the resulting measurements.
In broad strokes, the cooper method proceeds in two stages:
Inverse Kinematics
. The motion-capture data are attached to the simulated skeleton using ball joints. These ball joints are configured so that their constraints (namely, placing both anchor points of the joint at the same location in space) are allowed to slip; ODE implements this slippage using a spring dynamics, which provides a natural mechanism for the articulated skeleton to interpolate the marker data as well as possible.At each frame during the first pass, the motion-capture markers are placed at the appropriate location in space, and the attached articulated skeleton “snaps” toward the markers using its inertia (from the motion in preceding frames) as well as the spring constraints provided by the marker joint slippage.
At each frame of this process, the articulated skeleton can be queried to obtain joint angles for each degree of freedom. In addition, the markers can be queried to find their constraint slippage.
Inverse Dynamics
. The marker constraints are removed, and the joint angles computed in the first pass are used to constrain the skeleton’s movements.At each frame during the second pass, the joints in the skeleton attempt to follow the angles computed in the first pass; a PID controller is used to convert the angular error value into a target angular velocity for each joint.
The torques that ODE computes to solve this forward angle-following problem are returned as a result of the second pass.
In general, the cooper model is a useful way of getting a physics simulator, a model of a human skeleton, and some motion-capture data to interact smoothly. Particularly useful for almost any simulations of human motion are the
settle_to_markers()
andfollow_markers()
methods.Methods
__init__
([dt, max_angular_speed])are_connected
(body_a, body_b)Determine whether the given bodies are currently connected. create_body
(shape[, name])Create a new body. follow_markers
([start, end, states])Iterate over a set of marker data, dragging its skeleton along. forward_dynamics
(torques[, start, states])Move the body according to a set of torque data. get_body
(key)Get a body by key. get_body_states
()Return the complete state of all bodies in the world. get_joint
(key)Get a joint by key. inverse_dynamics
(angles[, start, end, ...])Follow a set of angle data, yielding dynamic joint torques. inverse_kinematics
([start, end, states, ...])Follow a set of marker data, yielding kinematic joint angles. join
(shape, body_a[, body_b, name])Create a new joint that connects two bodies together. load_markers
(filename, attachments[, max_frames])Load marker data and attachment preferences into the model. load_skeleton
(filename[, pid_params])Create and configure a skeleton in our model. move_next_to
(body_a, body_b, offset_a, offset_b)Move one body to be near another one. needs_reset
()Return True iff the world needs to be reset. on_collision
(args, geom_a, geom_b)Callback function for the collide() method. on_key_press
(key, modifiers, keymap)Handle an otherwise unhandled keypress event (from a GUI). reset
()Reset the automatic process that gets called by step()
.set_body_states
(states)Set the states of some bodies in the world. settle_to_markers
([frame_no, max_distance, ...])Settle the skeleton to our marker data at a specific frame. step
([substeps])Advance the physics world by one step. Attributes
bodies
Sequence of all bodies in the world, sorted by name. cfm
Current global CFM value. erp
Current global ERP value. gravity
Current gravity vector in the world. joints
Sequence of all joints in the world, sorted by name. -
follow_markers
(start=0, end=1e+100, states=None)[source]¶ Iterate over a set of marker data, dragging its skeleton along.
Parameters: start : int, optional
Start following marker data after this frame. Defaults to 0.
end : int, optional
Stop following marker data after this frame. Defaults to the end of the marker data.
states : list of body states, optional
If given, set the states of the skeleton bodies to these values before starting to follow the marker data.
-
forward_dynamics
(torques, start=0, states=None)[source]¶ Move the body according to a set of torque data.
-
inverse_dynamics
(angles, start=0, end=1e+100, states=None, max_force=100)[source]¶ Follow a set of angle data, yielding dynamic joint torques.
Parameters: angles : ndarray (num-frames x num-dofs)
Follow angle data provided by this array of angle values.
start : int, optional
Start following angle data after this frame. Defaults to the start of the angle data.
end : int, optional
Stop following angle data after this frame. Defaults to the end of the angle data.
states : list of body states, optional
If given, set the states of the skeleton bodies to these values before starting to follow the marker data.
max_force : float, optional
Allow each degree of freedom in the skeleton to exert at most this force when attempting to follow the given joint angles. Defaults to 100N. Setting this value to be large results in more accurate following but can cause oscillations in the PID controllers, resulting in noisy torques.
Returns: torques : sequence of torque frames
Returns a generator of joint torque data for the skeleton. One set of joint torques will be generated for each frame of angle data between start and end.
-
inverse_kinematics
(start=0, end=1e+100, states=None, max_force=20)[source]¶ Follow a set of marker data, yielding kinematic joint angles.
Parameters: start : int, optional
Start following marker data after this frame. Defaults to 0.
end : int, optional
Stop following marker data after this frame. Defaults to the end of the marker data.
states : list of body states, optional
If given, set the states of the skeleton bodies to these values before starting to follow the marker data.
max_force : float, optional
Allow each degree of freedom in the skeleton to exert at most this force when attempting to maintain its equilibrium position. This defaults to 20N. Set this value higher to simulate a stiff skeleton while following marker data.
Returns: angles : sequence of angle frames
Returns a generator of joint angle data for the skeleton. One set of joint angles will be generated for each frame of marker data between start and end.
-
load_markers
(filename, attachments, max_frames=1e+100)[source]¶ Load marker data and attachment preferences into the model.
Parameters: filename : str
The name of a file containing marker data. This currently needs to be either a .C3D or a .CSV file. CSV files must adhere to a fairly strict column naming convention; see
Markers.load_csv()
for more information.attachments : str
The name of a text file specifying how markers are attached to skeleton bodies.
max_frames : number, optional
Only read in this many frames of marker data. By default, the entire data file is read into memory.
Returns: markers :
Markers
Returns a markers object containing loaded marker data as well as skeleton attachment configuration.
-
load_skeleton
(filename, pid_params=None)[source]¶ Create and configure a skeleton in our model.
Parameters: filename : str
The name of a file containing skeleton configuration data.
pid_params : dict, optional
If given, use this dictionary to set the PID controller parameters on each joint in the skeleton. See
pagoda.skeleton.pid()
for more information.
-
reset
()[source]¶ Reset the automatic process that gets called by
step()
.By default this follows whatever marker data is loaded into our model.
Provide an override for this method to customize the default behavior of the
step()
method.
-
settle_to_markers
(frame_no=0, max_distance=0.05, max_iters=300, states=None)[source]¶ Settle the skeleton to our marker data at a specific frame.
Parameters: frame_no : int, optional
Settle the skeleton to marker data at this frame. Defaults to 0.
max_distance : float, optional
The settling process will stop when the mean marker distance falls below this threshold. Defaults to 0.1m (10cm). Setting this too small prevents the settling process from finishing (it will loop indefinitely), and setting it too large prevents the skeleton from settling to a stable state near the markers.
max_iters : int, optional
Attempt to settle markers for at most this many iterations. Defaults to 1000.
states : list of body states, optional
If given, set the bodies in our skeleton to these kinematic states before starting the settling process.