TWiki > Rise Web>RisePlatform>RiSEPlatformAlanCodeComments (16 Feb 2007, AlanAsbeck)
Stuff written by Alan about how the RiSE code works. This is in no particular order as of yet.

What it calls when you run the Supervisor: SupervisorFunctionCalls

What it calls when you run the Operator: OperatorFunctionCalls

#### Wing Offset changes and force:

From measurements on the actual robot doing wing offset changes to get the robot to squeeze in on some boards, we get that to get 1.0 Newtons of force change, you need a wing angle change of about 2-3 degrees. For leg0, it seemed to reliably have changes of 2.8-3.1 degrees/Newton. For leg1, it had values of ~2 degrees/Newton. I'm not sure about the other legs or what caused it to have different values for legs 0 and 1. But this does mean that if we want to have a 3N squeezing force, it will take about 10 degrees of wing offset change to make it ungrip or grip the tree with the feet starting from a position at the surface of the tree.

This was done with the standard GaitRunner motor gains of kp=20, kd=2.

If you make the legs go up very rapidly (zero the wing offset when it is at -200 degrees or so), then it took a change of 23.5 degrees to get it to go from 3.4N to 0. This took 0.09 seconds.

If you just make the wing move through the air, you get the following: the leg hit the surface somewhere around the bottom of the actual wing position. #### Assorted files:

StateProxy.cc: This file appears to be an interface to access all of the RiSE motor commands. It provides the Log Accessors for all of the wing, crank angles and motor torques and that stuff. I think it just makes a local copy of all the Hip, Leg (motor) stuff for the Log Accessors and the information is not used for any other purpose.

HipWriter.cc does most of the actual computation about writing torques to motors and stuff like that.

GaitRunnerModule.cc does the actual running of the module, at least for modules of class Gait (some modules are of class Module). It does this in its 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:

1. 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.
2. Then you calibrate the robot. This puts the wings at +pi/2 and cranks at __.
3. 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[].
4. 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/risebus12/stuccogaits.rc
CVS:    Demo/Operator/Makefile Demo/Operator/RiSEModes.cfg
CVS:    Demo/Operator/RiSEPanel.cfg Demo/Supervisor/supervisor.cc
CVS:    RobotCode/Behaviors/include/modules/GaitClasses.hh
CVS:    RobotCode/Behaviors/modes/Makefile
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.multiply( bTa.rotation(), aVa );
//   bVa.multiply( bTa.rotation(), aVa );
//   bVa.subtract( bVa, bVb );
//   bVa.subtract( bVa, bVb );
//
//   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).multiply( inverseGlobalFrame.rotation(), globalforce ); // forces
//       (*force).multiply( inverseGlobalFrame.rotation(), globalforce ); // torques
//
//     }

```

-- AlanAsbeck - 07 Jul 2006

Copyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback