MotionSequenceEngine Class Reference#include <MotionSequenceEngine.h>
Inheritance diagram for MotionSequenceEngine:
[legend]List of all members.
Detailed Description
A handy class for storing a sequence of keyframed movements.
Each outputs is handled independently. It's easy to add keyframes which modify all of the outputs, but since each output is tracked individually, OutputCmd's with 0 weight can be used to not affect other motions. For instance, if you want to pan the head left to right while moving the right leg up and down several times, you won't have to specify the intermediary position of the head in its motion at each of the leg motion keyframes.
Be aware that the 0 time frame will be replaced on a call to play() with the current body posture from state. However, this only applies to outputs which have a non-zero weighted frame defined at some point. The weights, of the 0 time frame will remain unchanged. These weights are initially set to 0, so that it's possible to 'fade in' the first frame of the motion sequence from whereever the body happens to be (or already doing)
To fade out at the end, set a frame with 0 weight for everything. Otherwise it will simply die suddenly. When a joint reaches its last keyframe, if hold is set (the default) it will hold its last value until the MotionSequence is reset or stopped. If hold is false, then the joint is treated as 0 weight once it reaches its last frame.
Currently, MotionSequenceEngine is intended mainly for building, not editing. It's easy to add keyframes, but hard/impossible to delete them.
The MotionSequenceEngine base class is an abstract class so that you can create memory efficient motion sequences and simply refer to them by the common base class instead of having to worry about the actual size allocated in the template, MotionSequenceMC.
- See also:
- MotionSequenceEngine::SizeSmall, MotionSequenceEngine::SizeMedium, MotionSequenceEngine::SizeLarge, MotionSequenceEngine::SizeXLarge,
The file format used is as follows: ('<' and '>' are not meant literally)
- First line: '
#MSq' - Followed by any series of:
- '
advanceTime time-delta' - moves playhead forward, in milliseconds (synonym for delay) - '
delay time-delta' - moves playhead forward, in milliseconds (synonym for advanceTime) - '
setTime time' - sets play time to specified value, in ms - 'outputname
value [weight]' - sets the specified output to the value - assumes 1 for weight; you can view the list of valid joint names in the outputNames array within the RobotInfo extension namespace for your model. (e.g. ERS210Info::outputNames[]) - '
load filename' - file can be a posture or another motion sequence (if MS, leaves playhead at end of the motion sequence); see setPose() and overlayMotion() - '
loadExplicit filename' - file must be a posture, sets position for all outputs, including zero-weighted ones; see setExplicitPose() - '
degrees' - all following values will be interpreted as degrees [default] - '
radians' - all following values will be interpreted as radians - '
#comment' - a comment line
- Last line: '
#END'
Lines beginning with '#' are ignored as comments. Be aware if you load the file and then save it again, these comments will be lost.
Example 1: This motion sequence will straighten out the head, panning from right to left.
#MSq
degrees
# Straighten head
advanceTime 50
NECK:tilt 15
NECK:nod 0
# Pan right
advanceTime 850
NECK:pan~ -45
# Pan left
advanceTime 900
NECK:pan~ 45
NECK:tilt 15
NECK:nod 0
#END
|
This graph illustrates the motion of the tilt and pan joints in example 1:
Notice how the joint will move from wherever it is initally to the first keyframe for that joint. Specifying the tilt joint a second time at the end of the motion forces the tilt joint to be held at that position throughout the motion, regardless of the hold setting at the time the sequence is run.
Example 2: This example will straighten the head and the tail, pan the head left to right, and then pan the tail left to right.
#MSq
degrees
# Bring head and tail to neural positions
advanceTime 50
NECK:pan~ 0
NECK:tilt 0
TAIL:pan~ 0
TAIL:tilt 0
# Pan left
advanceTime 1000
NECK:pan~ 90
# Pan right
advanceTime 1000
NECK:pan~ -90
# Center head
# Update tail time index
advanceTime 500
NECK:pan~ 0
# Note this respecification of TAIL:pan~ at 0 -- see graph below
TAIL:pan~ 0
# Wag left
advanceTime 500
TAIL:pan~ 90
# Wag right
advanceTime 500
TAIL:pan~ -90
#END
|
These graphs illustrate the motion of the pan joint for the head and the tail:
The head's motion should be straightforward. The thing to note in the tail's graph is why the second TAIL:pan~ 0 is necessary at time 2550. If it were not specified, the tail would slowly move to the left over the course of the head's movement. We want it to stay still until the head is done, so it must be respecified at the same position to hold it at that value in the intervening time.
After loading a motion sequence, the playtime is left at the end. This is to make it easy to append/overlay motion sequences. However, the playhead will be reset to the beginning on the first call to updateOutputs() if isPlaying() returns true.
You can also create a motion sequence dynamically at run time:
By default, playing is true. Thus, when you add a MotionSequenceMC to the MotionManager, it will begin executing automatically. If you do not want this behavior, simply call pause() before adding the sequence.
When the sequence reaches the end, isAlive() will return false. If the motion was added with MotionManager::addPrunableMotion, the motion sequence will then autoprune itself from the MotionManager. However, you can either call MotionManager::addPersistentMotion() to add it, or call setAutoPrune(false), if you want to retain the same instantiation between executions.
- See also:
- PostureEngine for information on the posture files
David Touretzky's "Postures and Motion Sequences" Chapter
CMU's Cognitive Robotics posture slides
- Todo:
- We should also have an insertMotion()
Definition at line 185 of file MotionSequenceEngine.h.
|
Public Member Functions |
|
| MotionSequenceEngine () |
| | constructor, will start playing immediately
|
|
virtual | ~MotionSequenceEngine () |
| | destructor
|
|
virtual int | updateOutputs () |
| | similar to the MotionCommand::updateOutputs, although this isn't a motion command, and doesn't make any calls on MotionManager - merely updates lasttime, expects subclasses to do the work of sending new commands to the system
|
|
|
virtual unsigned int | getBinSize () const |
| | inherited, returns the size used to save the sequence
|
|
virtual unsigned int | loadBuffer (const char buf[], unsigned int len) |
| | inherited, doesn't clear before loading - call clear yourself if you want to reset, otherwise it will overlay. Leaves playtime at end of load.
|
|
virtual unsigned int | saveBuffer (char buf[], unsigned int len) const |
| | inherited, saves the motion sequence - will save a flat file - doesn't remember references to other files which were loaded
|
|
virtual unsigned int | loadFile (const char filename[]) |
| | inherited, doesn't clear before loading - call clear yourself if you want to reset, otherwise it will overlay. Leaves playtime at end of load.
|
|
virtual unsigned int | saveFile (const char filename[]) const |
| | inherited, saves the motion sequence - will save a flat file - doesn't remember references to other files which were loaded
|
|
void | setSaveDegrees () |
| | will store angles as degrees on future saves
|
|
bool | isSaveDegrees () const |
| | returns true if will store angles as degrees on future saves
|
|
void | setSaveRadians () |
| | will store angles as radians on future saves
|
|
bool | isSaveRadians () const |
| | returns true if will store angles as degrees on future saves
|
|
|
virtual void | clear ()=0 |
| | empties out the sequence (constant time operation - faster than a series of pops)
|
|
void | setTime (unsigned int x) |
| | set the time for both playback and editing (in milliseconds)
|
|
unsigned int | advanceTime (unsigned int x) |
| | advance the play/edit index by x milliseconds, and then returns the new getTime()
|
|
void | setOutputCmd (unsigned int i, const OutputCmd &cmd) |
| | will insert a keyframe for the given output, or change an existing one
|
|
const OutputCmd & | getOutputCmd (unsigned int i) |
| | gets the value of output i at the playhead
|
|
void | setPose (const PostureEngine &pose) |
| | calls setOutputCmd for all non-zero weighted OutputCmds in pose (if you wish to set from a file, use loadFile)
|
|
void | setExplicitPose (const PostureEngine &pose) |
| | calls setOutputCmd on each of the OutputCmds in pose, even if they are zero-weight (can be used to fade joints in/out with other conflicting motions)
|
|
PostureEngine | getPose () |
| | returns the set of OutputCmd's at the current playhead as a PostureEngine
|
|
void | getPose (PostureEngine &pose) |
| | stores the set of OutputCmd's at the current playhead into the specified PostureEngine
|
|
void | overlayPose (const PostureEngine &pose) __attribute__((__deprecated__)) |
| | deprecated, use setPose instead (what setPose used to do is now setExplicitPose)
|
|
unsigned int | overlayMotion (const std::string &msFile) |
| | loads msFile from disk and calls overlayMotion(const MotionSequenceEngine&) with it, returns the duration of msFile (0 if there was an error)
|
| void | overlayMotion (const MotionSequenceEngine &ms) |
| | applies each keyframe of ms to this, leaves playhead at the end (in other words, advances playhead to end of ms)
|
|
void | compress () |
| | compresses the sequence by eliminating sequences of moves which are identical
|
|
virtual unsigned int | getMaxFrames () const =0 |
| | returns the maximum number of key frames (Move's) which can be stored, determined by the instantiating MotionSequenceMC's template parameter
|
|
virtual unsigned int | getUsedFrames () const =0 |
| | returns the number of used key frames (Move's) which have been stored by the instantiation MotionSequenceEngine subclass
|
|
void | makeSafe (const float vels[NumOutputs], float margin) |
| | will insert time into the motion where needed to keep the joint velocities at or below the speeds given in vels * margin
|
|
|
bool | isPlaying () |
|
void | play () |
| | returns true if currently playing restarts playback from beginning
|
|
void | pause () |
| | pauses playback until another call to play() or resume()
|
|
void | resume () |
| | begins playback from the current playtime
|
|
unsigned int | getTime () const |
| | returns the current position of the playback (in milliseconds), see setTime()
|
|
unsigned int | getEndTime () const |
| | returns the length of the motion sequence (in milliseconds)
|
|
void | setSpeed (float x) |
| | sets the playback speed (e.g. 1=regular, 0.5=half speed, -1=backwards)
|
|
float | getSpeed () const |
| | returns the playback speed
|
|
virtual void | setHold (bool h=true) |
| | Sets hold - if this is set to false, it will allow a persistent motion to behave the same as a pruned motion, without being pruned.
|
|
virtual bool | getHold () |
| | return hold
|
Protected Types |
|
typedef unsigned short | Move_idx_t |
| | type for indexes to move structures in subclass's storage
|
Protected Member Functions |
|
virtual Move & | getKeyFrame (Move_idx_t x)=0 |
| | returns the Move struct corresponding to x in the subclass's actual data structure
|
|
virtual const Move & | getKeyFrame (Move_idx_t x) const =0 |
| | returns the Move struct corresponding to x in the subclass's actual data structure
|
|
virtual Move_idx_t | newKeyFrame ()=0 |
| | causes subclass to create a new Move structure, returns its index
|
|
virtual void | eraseKeyFrame (Move_idx_t x)=0 |
| | causes subclass to mark the corresponding Move structure as free
|
|
void | calcOutput (OutputCmd &ans, unsigned int t, const Move &prev, const Move &next) const |
| | Does the actual calculation of position information. Perhaps replace with a Bezier or spline or something?
|
|
virtual bool | setRange (unsigned int t, Move_idx_t &prev, Move_idx_t &next) const =0 |
| | Sets prev and next to the appropriate values for the given time and output index, return true if there was a change.
|
|
unsigned int | setNextFrameTime (Move_idx_t p[NumOutputs], Move_idx_t n[NumOutputs]) const |
| | sets playtime to next time for which any output has a keyframe, -1 if none exists
|
Static Protected Member Functions |
|
static unsigned int | readWord (const char buf[], const char *const buflen, char word[], const unsigned int wordlen) |
| | reads a line from a file, parsing it into variables, returns ending position
|
|
static unsigned int | getOutputIndex (const char name[], unsigned int i) |
| | returns the index for the output named in the string or NumOutputs if not found, begins search through RobotInfo::outputName's at index i
|
Protected Attributes |
|
Move_idx_t | starts [NumOutputs] |
| | the beginning frame for each output animation
|
|
Move_idx_t | prevs [NumOutputs] |
| | the previous frame (the starttime for this frame will always be less than or equal to playtime)
|
|
Move_idx_t | nexts [NumOutputs] |
| | the upcoming frame (the starttime for this frame will always be greater than playtime)
|
|
OutputCmd | curs [NumOutputs] |
| | merely a cache of current values (if computed, see curstamps)
|
|
unsigned int | curstamps [NumOutputs] |
| | timestamp of corresponding value in curs
|
|
unsigned int | playtime |
| | the current time of playback, 0 is start of sequence
|
|
unsigned int | lasttime |
| | the time of the last update
|
|
unsigned int | endtime |
| | max of moves's Move::starttime's
|
|
float | playspeed |
| | multiplies the difference between current time and starttime, negative will cause play backwards
|
|
bool | playing |
| | true if playing, false if paused
|
|
bool | hold |
| | if set to true, the posture will be kept active; otherwise joints will be marked unused after each posture is achieved (as if the posture was pruned); set through setHold()
|
|
float | loadSaveMode |
| | 1 to use radians, M_PI/180 for degrees during a save
|
Static Protected Attributes |
|
static Move_idx_t | invalid_move = (MotionSequenceEngine::Move_idx_t)-1 |
| | used to mark the ends of the Move linked lists
|
Classes |
| struct | Move |
| | This struct holds all the information needed about a frame for a particular output. More...
|
Member Function Documentation
applies each keyframe of ms to this, leaves playhead at the end (in other words, advances playhead to end of ms)
- Todo:
- should better handle conflicts with keyframes in original motion
This is not a particularly well implemented function -- it will interleave ms's keyframes with any pre-existing ones, but will clobber frames which coincide with ms's own. Probably will not give the desired effect when the motion is actually overlaying something, but it will work for basic usage cases.
Definition at line 398 of file MotionSequenceEngine.cc.
The documentation for this class was generated from the following files:
|