You should complete the "Writing your first Behavior" guide before doing this since we will use the SampleBehavior class here.
Read through the Doxygen documentation on the MotionCommand class, we will be inheriting from it.
Create a file named SampleMC.h (or whatever you want to call it) in your project directory.
By convention, we've been ending the names of our MotionCommands with MC to make it clear what they are.
Set up the usual C++ boilerplate for a class which
inherits from the MotionCommand class.
The functions are described below.
//-*-c++-*-
#ifndef INCLUDED_SampleMC_h_
#define INCLUDED_SampleMC_h_
#include "Motion/MotionCommand.h"
class SampleMC : public MotionCommand {
public:
// Constructor
SampleMC() : MotionCommand() {}
// Abstract functions:
// These must be defined by every MotionCommand
virtual int updateOutputs() {}
virtual int isDirty() {}
virtual int isAlive() {}
};
#endif
This isn't quite valid yet - several of the required functions have return codes which we are ignoring. But first, a brief description of the functions:
updateOutputs()
is called once per "cycle". It should return the number of
"dirty"
outputs. ("dirty" means outputs which have changed since the last
cycle.) Currently the return value is unused, but in the future
MotionManager may use this information to avoid redundant
calculations. If this would be expensive to calculate precisely,
at least be sure to return a non-zero value if there are any dirty
outputs.
virtual int updateOutputs() {
}
We are using the legs, so a nice way to say that is to use the constants defined in the RobotInfo namespace. Since we're going to be using all of the leg joints, we return NumLegJoints.
isDirty()
is not called at present, but should return the same value as updateJointCmds(). But
just for this example, we'll always return true.
virtual int isDirty() {return true;}
isAlive()
should return true as
long
as the MotionCommand is active. If this returns false and the MotionCommand is
set to autoprune, MotionManager will remove it. This is
handy for "throw away" motion primitives.
virtual int isAlive() {return true;}
Our MotionCommand never really reaches an end
condition, so we'll always return true.
After adding these lines, the MotionCommand should be valid, although it doesn't do anything.
Now lets add SampleMC
to the SampleBehavior.h
so
you can test it out. Not that it will do anything yet, but you
will be able to test incremental changes from now on.
First, include the header file and create a new MotionPtr<SampleMC> member variable, initialize it, and then activate it in DoStart
And that's it! From this point we customize what we
want SampleMC to do that makes it unique.
Note that if your MotionCommand has a definite stopping point and uses isAlive() to reflect this
status, you may instead wish to use addPrunableMotion(), and skip removeMotion(). If you do
this and care to know when the MC has finished, you can listen for the
appropriate deactivate event from motmanEGID.