When we know how to use robot API and access different software modules, we can see how API is written to know how to extend it with our own modules.

head (EMYS) API structure

We will look at EMYS API (Emys.u script) and see how we used urbiscript to create simple movement functions and then combine them to create robot's behaviors.

//simple movement function
function local_head_MoveNeckPitch(pos, time)//function changes neck pitch to new position in desired time
{
  a_NeckPitch.stop | a_NeckPitch: robot.body.neck.pitch.val = (zero_NeckPitch - pos) smooth:time;
  //every joint has its own tag (a_NeckPitch in this case) which assures that only one function at the time is sending new position to joint. Tag is first stopped and them immediately (thanks to | operator) starts with new code, which is assigning new position (given in reference to joint zero position) to the joint. The new joint value changes smoothly thanks to urbiscript trajectory generator - in this case value changes by smooth trajectory (with gentle acceleration and deceleration) in given time.
}|{};
//every move function have also second version in which second parameter is not time of movement but its speed
function local_head_MoveNeckPitchS(pos, speed)
{
  a_NeckPitch.stop | a_NeckPitch: robot.body.neck.pitch.val = (zero_NeckPitch - pos) speed:speed;
  //this time trajectory generator will change joint value with given (constant during whole movement) speed
}|{};
//both functions are added to robot structure, so we can call them: robot.body.neck.pitch.Move(pos, time)
do (robot.body.neck.pitch) { 
  function Move(pos, time)       {call.local_head_MoveNeckPitch(pos, time);    };  
  function MoveSpeed(pos, speed)     {call.local_head_MoveNeckPitchS(pos, speed);    };  
  };
//Example of more complex behavior is expressing emotions, e.g disgust
function local_head_ExpDisgust(intensity,time,lock) {
  if (intensity>10) intensity=10;
    if (intensity<0) intensity=0;
    if (lock) {//true means that only one function can move joints at the time
      h_tagg_discs.freeze;//each group of joints(neck, discs, eyes) has its own tag, which is paused during function execution
        h_tagg_eyes.freeze;
    };
  //expressing emotion involves most of EMYS joints - thanks to & operator all movements are synchronized
    robot.body.neck.head.disc[up].Move(-0.7*intensity,time)&
    robot.body.neck.head.disc[down].Move(0.41*intensity,time)&
    robot.body.neck.head.eye[right].trans.Move(0,time)&
    robot.body.neck.head.eye[left].trans.Move(0,time)&
    robot.body.neck.head.eye[right].brow.Move(0,time)&
    robot.body.neck.head.eye[left].brow.Move(0,time)&
    robot.body.neck.head.eye[right].lid.Move(2.9*intensity,time)&
    robot.body.neck.head.eye[left].lid.Move(2.9*intensity,time);//last operator is ; so functions ends when movement of all joints is finished
    if (lock) {
       h_tagg_discs.unfreeze;//in the end, tags are resumed, so the other movements (e.g. breathing executed in background) can be executed
        h_tagg_eyes.unfreeze;
    };
  }|{};  

 

 

EMYS and FLASH are Open Source and distributed according to the GPL v2.0 © Rev. 0.8.0, 27.04.2016

FLASH Documentation