GaitRunner::update() loop. In the loop, it calls the updateClock() function for the module, and sends the commands to the legs. See code below. The correctTarget() call adds in the wing_offset and wing_diff from the GUI.
// update the gait
_gait->updateClock(&_clock,&command);
// output each leg's command to the robot
for (int i=0; i < GAIT_NUMLEGS; i++) {
// add in any manual offset angles
correctTarget(i, &(command.leg_command[i].target));
// send command to hip
_hiphw->setHipGain(i, &(command.leg_command[i].gain));
_hiphw->setHipTarget(i, &(command.leg_command[i].target));
}
Overall flow when you start a gait:
- When you start the supervisor on the robot, it executes the ::initialize() function in your module. This function reads in all the .rc files typically.
- Then you calibrate the robot. This puts the wings at +pi/2 and cranks at __.
- Next you switch to your mode and gait. Then, we hit "Launch" by pushing the Start button on the joystick. When this happens, it executes ::start(const Gait::clock_state_t *clock), and executes ::updateClock(const Gait::clock_state_t *clock, Gait::gait_command_t *command) ONCE. ::start(..) should do your variable initializations. At the end of all of this stuff, since we executed updateClock() once there will be values in command->leg_command[i].target.pos[].
- Then, you actually start the gait by pushing the big green "Go" arrow. When you do this, it does this "Startup Transition" using TransitionClasses.cc which is a module (in the usual directory of modules). This StartupTransition moves the legs from their current position to the position that is held in the command->target position after updateClock() is run once. So, you'd better make the target positions correct after the first updateClock() execution!
Stuff you have to do when you make a new module or mode:
CVS: ----------------------------------------------------------------------
CVS: Enter Log. Lines beginning with `CVS:' are removed automatically
CVS:
CVS: Committing in .
CVS:
CVS: Modified Files:
CVS: Demo/Config/robots/arachi/generate_links.sh
CVS: Demo/Config/robots/risebus12/stuccogaits.rc
CVS: Demo/Config/robots/risebus12/gaits/quad_state.rc
CVS: Demo/Operator/Makefile Demo/Operator/RiSEModes.cfg
CVS: Demo/Operator/RiSEPanel.cfg Demo/Supervisor/supervisor.cc
CVS: RobotCode/Behaviors/include/modules/ForceQuadState.hh
CVS: RobotCode/Behaviors/include/modules/GaitClasses.hh
CVS: RobotCode/Behaviors/modes/Makefile
CVS: RobotCode/Behaviors/modules/ForceQuadState.cc
CVS: Added Files:
CVS: Demo/Operator/StateMode.acc
CVS: RobotCode/Behaviors/include/StateModeStructs.hh
CVS: RobotCode/Behaviors/include/modes/StateMode.hh
CVS: RobotCode/Behaviors/modes/StateMode.cc
CVS: RobotCode/Behaviors/modes/StateMode.mod
CVS: ----------------------------------------------------------------------
Code related forces in Arachi:
/////// Functions we might need to call to get the force in the leg's home
/////// coord system:
// I think we just need to implement localForce() in Object.hh.
//
// From DeObject.h:
// virtual DeFrame* frameHome() { return &homeFrame_; }
// DeFrame& homeFrame() { return(homeFrame_); }
//
// Sample usage in Object.hh:
//
// This method return the total force (anf torque) acting on the
// object relative to the inertial ("global") world frame at the
// "current" time.
// void globalForce ( DeVector6 *force ) {
// _object->forceExternal( force );
// };
// void localForce ( DeVector6 *force ) {
// // TODO: Fix this, this is just a placeholder.
// _object->force.get(*force); // Added by Alan, this just returns the global Force..
// //_object->forceExternal( force );
// }
//
// In doing _object->force.get(*force) above we call the following from DeForce.h:
// void get(DeVector6& force);
// //!< \internal get 6x1 spacial vector that is the accumulation of the force
// // properties for an object
//
// From Contact.hh:
// This method calculates a frame transformation between Object A
// and Object B (the objects in contact). It is normally assumed
// that Object A is the "foot" and Object B is the "wall". The frame
// that is returned is Object A's Frame described in Object B's frame.
// DeFrame pose( void );
//
// From Contact.cc:
// DeFrame Contact::pose( void ) {
// DeFrame bFa;
//
// // Get frames relating A and B to global and compute
// // Frame relating A to B
// DeFrame gFa = _objectA->globalFrame();
// DeFrame gFb = _objectB->globalFrame();
//
// bFa.inversedMultiply( gFb, gFa );
// return bFa;
// }
//
// Sample usage in OrientationContact.cc:
// DeVector3 axis; DeFloat angle, relangle;
// pose().rotation().get( axis, angle );
//
//
// From Contact.hh:
// /** This method returns the relative translational and angular
// velocity of object A wrt to object B in a 6-space vector. */
// DeVector6 velocity( void );
//
// Implementation in Contact.cc:
// Note that a DeVector6 consists of two 3x1 vectors.
// spatial vector representing translational part and rotational part
// DeVector6 Contact::velocity( void ) {
// DeVector6 aVa, bVb, bVa;
// DeTransform bTa;
//
// aVa = _objectA->getDeObject()->velocity();
// bVb = _objectB->getDeObject()->velocity();
//
// bTa.set( pose() );
// bVa[0].multiply( bTa.rotation(), aVa[0] );
// bVa[1].multiply( bTa.rotation(), aVa[1] );
// bVa[0].subtract( bVa[0], bVb[0] );
// bVa[1].subtract( bVa[1], bVb[1] );
//
// return bVa;
// }
//
// From Object.hh:
// This method return the frame of the object relative to the
// inertial ("global") world frame at the "current" time. */
// const DeFrame & globalFrame( void ) { return _object->globalFrame( ); };
//
// From DeFrame.h:
// DE_MATH_API void inverse(const DeFrame& f);
// //! this = t
// DeFrame Contact::hometocurrentpose( void ) {
// DeFrame hFgFa;
//
//
// // Compute Frame relating A currently to its home frame
// // Notation: gFa = global Frame for A
// // hFa = home Frame for A
// DeFrame gFa = _objectA->globalFrame();
// DeFrame hFa = _objectA->homeFrame();
//
// hFgFa.inversedMultiply( hFa, gFa );
// return hFgFa;
// }
// // Now our globalForce function:
// void globalForce ( DeVector6 *force ) {
// DeVector6 * localforce;
// _object->forceExternal( localforce );
//
// DeFrame * globalFrame = globalFrame(); // Current frame of the object
//
// inverse(globalFrame); // Compute the inverse because we want the
// // forces in the global frame ?
// // Also I think this is the wrong syntax to compute the inverse..
// // Note that (if we are indeed needing to take the inverse) then you just
// // need to take the inverse of the rotational part of the frame, which corresponds
// // to the transpose. So you can just use <object>.inversedMultiply() which will do that
// // at the same time as multiplying it, instead of making this inverse object and stuff
// // like I did above.
//
// DeTransform inverseGlobalFrame;
// inverseGlobalFrame.set( globalFrame ); // Note globalFrame has been inverted
//
// // Now multiply the local force by this transformation so it's in the
// // object's global frame:
// (*force[0]).multiply( inverseGlobalFrame.rotation(), globalforce[0] ); // forces
// (*force[1]).multiply( inverseGlobalFrame.rotation(), globalforce[1] ); // torques
//
// }
-- AlanAsbeck - 07 Jul 2006