SPYSpheres
ZeroRoboticsGameImpl Class Reference

This class defines the hidden game implementation. More...

#include <ZRGameInternal.h>

List of all members.

Classes

struct  Camera
struct  ChallengeInfo
struct  Light
struct  OtherInfo
struct  Picture
struct  PlayerInfo
 (Required) Runs initialization fo the ZR game at the start of a test. More...

Public Member Functions

void init (void)
bool update (float forceTorqueOut[6])
 (Required) Runs an update of the game rules and calls the user function loop().
bool updateGameModeManeuver (float forceTorqueOut[6])
bool updateGameOverManeuver (float forceTorqueOut[6], unsigned char &finalScore)
void updateStates ()
bool enforceBoundaries (float forceTorque[6])
 (Required) Called on every gspControl control cycle.
void limitDirection (state_vector ctrlState, float ctrlControl[6], unsigned int idx, float dir)
 Limits the direction in which the programmed SPHERE can travel and slows down the velocity if it travels in the direction of the limit.
void sendDebug (void)
 (Required) Called on every gspControl control cycle, It should be used to send debug and telemetry information to the ground.
void sendInit (void)
 for Corona SPHERES: sends POI & Solar Flare info to Sat 2 at start of game
void processRXData (default_rfm_packet packet)
 (Required) Processes SPHERES telemetry data
void breakTie ()
void modify2DForceTorque (float forceTorque[6])
void resolveCollision (float zrState[12], float forceTorqueOut[6])
float dist3d (float *pos1, float *pos2) const
bool photoBomb (float zrState[12], float poiLoc[3])
void initItems ()
float randomizeStartingLocs (int itemID, int coord)
bool itemPickUp (int objectNum)
void initCamera ()
void disableCamera ()
void activateCamera ()
void memoryLoss ()
bool isFacingPos (float position[])
bool isFacingOther ()
bool isFacingEarth ()
float takePicImpl ()
 Returns the score value of the picture, or 0 if taking the picture failed.
float picPointsImpl ()
void resetPicsTaken ()
int sphereInSwitchingArea (float position[])
int sphereInMovingArea (float position[])
bool sphereInLight (float position[])
bool sphereInDark (float position[])
void switchLightDirection ()
void initLight ()
void updateLight ()
void initEnergy ()
void updateEnergy ()
bool tryToUseEnergy (float amount)
 ZeroRoboticsGameImpl (ZeroRoboticsAPIImpl &apiImpl)
 Constructor for binding an API implementation.

Static Public Member Functions

static ZeroRoboticsGameImplinstance ()
 Retrieves singleton instance of the game implementation.

Public Attributes

ChallengeInfo challInfo
ZeroRoboticsAPIImpl & apiImpl
 Reference to ZR API instance.
ZeroRoboticsGamegame
 Back pointer to the game instance.

Static Public Attributes

static const state_vector initState
 (Required) Initial state where the satellite is initialized.

Detailed Description

This class defines the hidden game implementation.

Any internal utility functions or game ru//les functsions hould be put here. You may also override any of the standard GSP functions by implementing them here. The functions init(), update(), and sendDebug() are required.

Definition at line 25 of file ZRGameInternal.h.


Constructor & Destructor Documentation

ZeroRoboticsGameImpl::ZeroRoboticsGameImpl ( ZeroRoboticsAPIImpl &  apiImpl)

Constructor for binding an API implementation.

Definition at line 56 of file ZRGameInternal.cpp.


Member Function Documentation

Definition at line 28 of file ZRCamera.cpp.

{
  challInfo.camera.cameraOn = true;
  GAME_TRACE(("[%d] camera ON | ", apiImpl.api->getTime()));
}

Definition at line 21 of file ZRCamera.cpp.

{
  challInfo.camera.cameraOffTime = apiImpl.api->getTime();
  challInfo.camera.cameraOn = false;
  GAME_TRACE(("[%d] camera OFF | ", apiImpl.api->getTime()));
}
float ZeroRoboticsGameImpl::dist3d ( float *  pos1,
float *  pos2 
) const

Definition at line 428 of file ZRGameInternal.cpp.

{
  float tmpVec[3];
  mathVecSubtract(tmpVec,static_cast<float*>(pos1),static_cast<float*>(pos2),3);
  return mathVecMagnitude(tmpVec,3);
}
bool ZeroRoboticsGameImpl::enforceBoundaries ( float  forceTorque[6])

(Required) Called on every gspControl control cycle.

It should be used to send debug and telemetry information to the ground.

Definition at line 383 of file ZRGameInternal.cpp.

{
  state_vector sphState;
  apiImpl.api->getMySphState(sphState);
  bool retValue = false;

  //Run velocity controller to stop motion out of volume
  //Zero out any controls that are leading the user out of the volume
  for (int i=0; i<3; i++)
  {
    if (sphState[POS_X+i] > limits[i])
    {
      limitDirection(sphState, forceTorqueOut, i, 1.0f);
      retValue = true;
    }
    else if (sphState[POS_X+i] < -limits[i])
    {
      limitDirection(sphState, forceTorqueOut, i, -1.0f);
      retValue = true;
    }
  }
  return retValue;
}
void ZeroRoboticsGameImpl::init ( void  )

Definition at line 70 of file ZRGameInternal.cpp.

{
  /*  Game Initialization setup.
  * Then set the locations of the memory packs.
  */

  apiImpl.gameTime = GAME_TIME;
  memset(&challInfo,0,sizeof(ChallengeInfo));   // general clear of challInfo to 0 = false = empty

  // update the state data on challInfo
  updateStates();
  challInfo.me.score = START_SCORE;

  // Lights, Camera, Action!
  initLight();
  initCamera();
  initEnergy();

  initItems();



  // send information to ground and sat2 at the end of init
  sendDebug();

}

Definition at line 33 of file ZREnergy.cpp.

Definition at line 15 of file ZRItems.cpp.

                                    {
  #ifndef ALLIANCE
  for(int i = 0; i<NUM_ITEMS; i++)
  {
    challInfo.me.mpTime[i]    = MP_EMPTY;
    challInfo.other.mpTime[i] = MP_EMPTY;
    for(int j = 0; j<3; j++)
      challInfo.mpLoc[i][j] = ITEM_LOC[i][j];
  }
  #else
  float r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[0][0] = r * 0.25f + 0.05;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[0][1] = r * 0.3f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[0][2] = r * 0.5f;

  challInfo.mpLoc[1][0] = -challInfo.mpLoc[0][0];
  challInfo.mpLoc[1][1] = challInfo.mpLoc[0][1];
  challInfo.mpLoc[1][2] = challInfo.mpLoc[0][2];

  challInfo.mpLoc[2][0] = 0.0f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[2][1] = r * 0.3f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[2][2] = r * 0.5f;

  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[3][0] = r * 0.25f + 0.05f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[3][1] = r * 0.2f + 0.4;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[3][2] = r - 0.5f;

  challInfo.mpLoc[4][0] = -challInfo.mpLoc[3][0];
  challInfo.mpLoc[4][1] = challInfo.mpLoc[3][1];
  challInfo.mpLoc[4][2] = challInfo.mpLoc[3][2];

  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[5][0] = r * 0.25f + 0.05f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[5][1] = r * 0.2f + 0.4;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[5][2] = r - 0.5f;

  challInfo.mpLoc[6][0] = -challInfo.mpLoc[5][0];
  challInfo.mpLoc[6][1] = challInfo.mpLoc[5][1];
  challInfo.mpLoc[6][2] = challInfo.mpLoc[5][2];

  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[7][0] = r * 0.2f + 0.3;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[7][1] = r * 0.3f;
  r = (float) (rand() % 10000) / (10000.0);
  challInfo.mpLoc[7][2] = r * 0.2f - 0.5f;

  challInfo.mpLoc[8][0] = -challInfo.mpLoc[7][0];
  challInfo.mpLoc[8][1] = challInfo.mpLoc[7][1];
  challInfo.mpLoc[8][2] = challInfo.mpLoc[7][2];

  for(int i = 0; i<NUM_ITEMS; i++)
  {
    challInfo.me.mpTime[i]    = MP_EMPTY;
    challInfo.other.mpTime[i] = MP_EMPTY;
    //printf("Item %d at (%f,%f,%f)\n", i, challInfo.mpLoc[i][0], challInfo.mpLoc[i][1], challInfo.mpLoc[i][2]);
  }
  #endif
  challInfo.me.mirrors = STARTING_MIRRORS;
  challInfo.me.mirrorTime = 0;
  challInfo.other.mirrorTime = 0;

}

Definition at line 16 of file ZRLight.cpp.

                                     {
  challInfo.light.direction = 1;
  #ifdef ALLIANCE

    #if (SPHERE_ID == SPHERE1)
      //float s = ((float) rand()) / ((float) RAND_MAX);
      challInfo.light.center = -0.2;  //s * 1.6 - 0.8;
      challInfo.light.nextSwitchTime = -1; // shouldn't be utilized
    #endif

    challInfo.light.greyWidth = LIGHT_GREY_WIDTH*.5;
    challInfo.light.lightWidth = LIGHT_WIDTH;
  #else
    #if (SPHERE_ID == SPHERE1)
      challInfo.light.center = 0.0;
      challInfo.light.nextSwitchTime = ((unsigned int) rand()) % 30 + 30;
    #endif

    challInfo.light.greyWidth = LIGHT_GREY_WIDTH;
  #endif
}

Retrieves singleton instance of the game implementation.

Returns:
The game implementation singleton

Singleton instance of the game implementation

Definition at line 38 of file ZRGameInternal.cpp.

                                                     {
  ///Singleton instance of the game implementation
  static ZeroRoboticsGameImpl gameImplInstance(ZeroRoboticsAPIImpl::instance());
  return gameImplInstance;
}

Definition at line 196 of file ZRCamera.cpp.

                                         {
  float earth [3];
  memcpy(earth, EARTH, 3 * sizeof(float));
  return mathVecInner(&challInfo.me.zrState[ZR_ATT_X], earth, 3) > MAX_FACING_ANGLE;
}

Definition at line 186 of file ZRCamera.cpp.

                                         {
  bool facing = isFacingPos(challInfo.other.zrState);
  //GAME_TRACE(("isFacingOther: facing = %d| ", facing));
  return facing;
}
bool ZeroRoboticsGameImpl::isFacingPos ( float  position[])

Definition at line 174 of file ZRCamera.cpp.

                                                       {
  float relativePos[3];
  mathVecSubtract(relativePos, position, challInfo.me.zrState, 3);
  mathVecNormalize(relativePos, 3);
  //Check if generally pointing at the other satellite (dot product) and
  //if within a small margin of error (to account for noise)
  //after bugfix, increased allowed error to 0.25f from 0.0575f
  // MAX_FACING_ANGLE = 0.968912f is cosf(0.25f)
  bool facing = mathVecInner(&challInfo.me.zrState[ZR_ATT_X], relativePos, 3) > MAX_FACING_ANGLE;
  return facing;
}
bool ZeroRoboticsGameImpl::itemPickUp ( int  objectNum)

Definition at line 135 of file ZRItems.cpp.

{
  /*
  This function will replicate that of the 2013 game's item PickUp function with
  a few minor changes.
  */

  state_vector sphState;
  apiImpl.api->getMySphState(sphState);
  float dist,speed;
  dist = dist3d(sphState, challInfo.mpLoc[mpNum]);
  speed = mathVecMagnitude(&sphState[3],3);           // VEL_X needs to be changed. - 3
  if (speed<MP_SPEED && dist<=MP_RADIUS)
  {
    if (challInfo.me.mpTime[mpNum] == MP_EMPTY && challInfo.other.mpTime[mpNum] == MP_EMPTY){
      challInfo.me.mpTime[mpNum] = apiImpl.api->getTime();
      switch (ITEM_TYPES[mpNum]){
        case ITEM_TYPE_ADD_SCORE : {challInfo.me.score = challInfo.me.score + ITEM_SCORE;
                  GAME_TRACE(("Score item picked up"));
                  break;
              }
        /*case ITEM_TYPE_ADD_MEMORY : {challInfo.camera.memorySize = challInfo.camera.memorySize + ITEM_MEMORY_SIZE;
                  GAME_TRACE(("memory item picked up"));
                  break;} */
        case ITEM_TYPE_ADD_ENERGY: {challInfo.me.energy = challInfo.me.energy + ITEM_ENERGY;
                  if (challInfo.me.energy > MAX_ENERGY) {
                    challInfo.me.energy = MAX_ENERGY;
                  }
                  GAME_TRACE(("energy item picked up"));
                  break;}
        case ITEM_TYPE_MIRROR:{  challInfo.me.mirrors += 1;
                GAME_TRACE(("Mirror picked up"));
                break;
              }
      }
      GAME_TRACE(("score: %f, energy: %f, memorySize: %d", challInfo.me.score, challInfo.me.energy, challInfo.camera.memorySize));




    }
/*
    if (!challInfo.me.acquiringMP[mpNum] && mathVecMagnitude(&sphState[RATE_X],3) <= MAX_START_MP)
    {
      challInfo.me.acquiringMP[mpNum] = true;
      memcpy(challInfo.me.initQuat,&sphState[QUAT_1],4*sizeof(float));
    }
    if (challInfo.me.acquiringMP[mpNum] && fabsf(mathVecInner(challInfo.me.initQuat,&sphState[QUAT_1],4)) < MP_ROTATION_ANGLE)
    {
      challInfo.me.acquiringMP[mpNum] = false;
      //Check for item pickup: item not already picked up by either player,
      //and item conditions have been met
      if (challInfo.me.mpTime[mpNum] == MP_EMPTY && challInfo.other.mpTime[mpNum] == MP_EMPTY)
      {
        //Record pickup time with game time
        challInfo.me.mpTime[mpNum] = apiImpl.api->getTime();
        //challInfo.camera.memorySize++;
        challInfo.me.score = challInfo.me.score + ITEM_SCORE;
        GAME_TRACE(("[%d] picked up item %d | ", apiImpl.api->getTime(), mpNum));
      }
    }
*/
  }
  else
  {
    challInfo.me.acquiringMP[mpNum] = false;
  }
  return false;

  // return true;
}
void ZeroRoboticsGameImpl::limitDirection ( state_vector  ctrlState,
float  ctrlControl[6],
unsigned int  idx,
float  dir 
)

Limits the direction in which the programmed SPHERE can travel and slows down the velocity if it travels in the direction of the limit.

Definition at line 407 of file ZRGameInternal.cpp.

{
  // if command is to move out further in same direction as limit
  if (ctrlControl[idx]*dir >= 0.0f)
  {
    ctrlControl[idx] = -1.0f * OOBgain * ctrlState[VEL_X+idx];  // slow down to get 0 velocity (ignore position)
  }
}

Definition at line 35 of file ZRCamera.cpp.

{
  memset(challInfo.camera.memory,0,CAMERA_MAX_MEMORY*sizeof(Picture));  // erase memory
  challInfo.camera.memoryFilled = 0;                                    // reset counter
  GAME_TRACE(("[%d] memory CLEARED | ", apiImpl.api->getTime()));
}
void ZeroRoboticsGameImpl::modify2DForceTorque ( float  forceTorque[6])

Definition at line 166 of file ZRGameInternal.cpp.

{
  state_vector myState, targetState;
  apiImpl.api->getMySphState(myState);
  memcpy(targetState, myState, sizeof(state_vector));   
  
  targetState[POS_Z] = 0.0f;
  targetState[VEL_Z] = 0.0f;
  targetState[10] = 0.0f;
  targetState[11] = 0.0f;
  targetState[12] = 0.0f;

  float q_sw[4], q_tw[4];
  float axis[3] = {0.0f, 0.0f, -1.0f};
  swingTwistDecomposition(&targetState[QUAT_1], q_sw, q_tw, axis);
  quatToPositive(q_tw);
  memcpy(&targetState[QUAT_1], q_tw, 4*sizeof(float));
  
  state_vector error;
  findStateError(error, myState, targetState);

  float newForces[6] = {0};
  
  ctrlPositionPD(KPpositionPD, KDpositionPD, error, newForces);
  ctrlAttitudeNLPIDwie(KPattitudePID, KIattitudePID, KDattitudePID, 
             KPattitudePID, KIattitudePID, KDattitudePID, 
             KPattitudePID, KIattitudePID, KDattitudePID, 
             1.0f, error, newForces);
  forceTorque[FORCE_Z] = newForces[FORCE_Z];
  forceTorque[TORQUE_X] = newForces[TORQUE_X];
  forceTorque[TORQUE_Y] = newForces[TORQUE_Y];
}
bool ZeroRoboticsGameImpl::photoBomb ( float  zrState[12],
float  poiLoc[3] 
)

Definition at line 79 of file ZRCamera.cpp.

{
  // check if other in light or grey zone, camera is on, the spheres are facing
  bool isCameraOn = challInfo.camera.cameraOn;
  bool isFacingOtherResult = isFacingOther();
  bool isOppNotInDarkZone = !sphereInDark(challInfo.other.zrState);
  bool myMirror = challInfo.me.mirrorTime != 0 && challInfo.me.mirrorTime + ITEM_MIRROR_DURATION > challInfo.currentTime;
  bool otherMirror = challInfo.other.mirrorTime != 0 && challInfo.other.mirrorTime + ITEM_MIRROR_DURATION > challInfo.currentTime;
  float picturePointValue = 0;
  if (isCameraOn && isFacingOtherResult && isOppNotInDarkZone && !myMirror)
  {
    float bet[3], distance;
    mathVecSubtract(bet, challInfo.me.zrState, challInfo.other.zrState, 3);
    distance = mathVecMagnitude(bet, 3);

    if (distance < PHOTO_MIN_DISTANCE) {
      GAME_TRACE(("Not a good shot: too close to the other satellite | "));
      return 0.0;
    }
    picturePointValue = 2.0 + 0.1/(distance - PHOTO_MIN_DISTANCE + 0.1);
    if(otherMirror){
      #ifdef ZR2D
      picturePointValue = 0;
      #else
      picturePointValue = -1*picturePointValue;
      #endif
      GAME_TRACE(("Not a good shot: Opposing mirror active %f|", picturePointValue));
    }

  }
  else if(!isCameraOn){
    GAME_TRACE(("Not a good shot: camera off |"));
  }
  else if(myMirror){
    GAME_TRACE(("Not a good shot: my mirror's in the way |"));
  }
  else if(!isFacingOtherResult) {
        GAME_TRACE(("Not a good shot: not facing the other satellite | "));
    }
  else if(!isOppNotInDarkZone){
    GAME_TRACE(("Not a good shot: opponent in dark zone |"));
  }
  return picturePointValue;
}
void ZeroRoboticsGameImpl::processRXData ( default_rfm_packet  packet)

(Required) Processes SPHERES telemetry data

Definition at line 11 of file ZRCommRoutines.cpp.

{
  if (packet[PKT_CM] == COMM_CMD_DBG_SHORT_SIGNED)
  {
    dbg_short_packet DebugVecShort;
    memcpy(DebugVecShort, &packet[PKT_DATA], sizeof(dbg_short_packet));
    if (ctrlManeuverNumGet() > 2)
    {
      for (int i = 0; i < NUM_ITEMS; i++){
        challInfo.other.mpTime[i] = DebugVecShort[i+1];

      }
      // copy general data during game run
      challInfo.other.mirrorTime = DebugVecShort[14];
      challInfo.other.message = DebugVecShort[15];
    }
    else {
      // initialization data for items
      if (DebugVecShort[0] == 0){
        #if (SPHERE_ID == SPHERE1)
          // get data from SPHERE2
          for (int i = 0; i < NUM_ITEMS - 5; i++){
                  challInfo.mpLoc[i + 5][0] = DebugVecShort[3*i + 1] / 10000.0f;
                  challInfo.mpLoc[i + 5][1] = DebugVecShort[3*i + 2] / 10000.0f;
                  challInfo.mpLoc[i + 5][2] = DebugVecShort[3*i + 3] / 10000.0f;
          }
        #else
          // get data from SPHERE1
          for (int i = 0; i < 5; i++){
                  challInfo.mpLoc[i][0] = DebugVecShort[3*i + 1] / 10000.0f;
                  challInfo.mpLoc[i][1] = DebugVecShort[3*i + 2] / 10000.0f;
                  challInfo.mpLoc[i][2] = DebugVecShort[3*i + 3] / 10000.0f;
          }

        #endif
      }
    }
  }
  else if (packet[PKT_CM] == COMM_CMD_DBG_SHORT_UNSIGNED)
  {
    dbg_ushort_packet DebugVecUShort;
    memcpy(DebugVecUShort, &packet[PKT_DATA], sizeof(dbg_ushort_packet));
      int cmn = ctrlManeuverNumGet();
      // printf("cmn %d\n",cmn);
      // recieve initialization packet (control maneuver 1)
      if (cmn < 3){
        #if (SPHERE_ID == SPHERE2)
          // printf("Init DebugVecShort Received by Sphere 2: %d (should be 0), %d\n", DebugVecShort[0], cmn);
          // make sure its one of our initialization packets, all other debugVecShort[0] are time * 10, so they are larger than 0
          if (DebugVecUShort[0] == 0)
          {
            challInfo.light.nextSwitchTime = (int) DebugVecUShort[1];
          }

        #endif
      }

    //challInfo.other.mpTime[0] = DebugVecUShort[1];
    //challInfo.other.mpTime[1] = DebugVecUShort[2];
  }
  else if (packet[PKT_CM] == COMM_CMD_DBG_FLOAT)
  {
    dbg_float_packet DebugVecFloat;
    memcpy(DebugVecFloat, &packet[PKT_DATA], sizeof(dbg_float_packet));
    int cmn = ctrlManeuverNumGet();
    if (cmn < 3) {
        #if (SPHERE_ID == SPHERE2)
          //printf("Init DebugVecFloat Received by Sphere 2: %f (should be -1), %d\n", DebugVecFloat[0], cmn);
          // make sure its one of our initialization packets. tstep should be nonnegative, I think.
        if (DebugVecFloat[0] == 0.0f)
        {
          challInfo.light.center = DebugVecFloat[1];
          challInfo.light.direction = DebugVecFloat[2];

          return;
        }
        #endif
    }
    challInfo.other.score = DebugVecFloat[1];
    challInfo.other.energy = DebugVecFloat[3];
  }
}
float ZeroRoboticsGameImpl::randomizeStartingLocs ( int  itemID,
int  coord 
)
void ZeroRoboticsGameImpl::resolveCollision ( float  zrState[12],
float  forceTorqueOut[6] 
)

Definition at line 417 of file ZRGameInternal.cpp.

{
  for (int i=0; i<3; i++)
  {
    if (zrState[i] > 0)
      limitDirection(zrState, forceTorqueOut, i, -1.0f);
    else if (zrState[i] < 0)
      limitDirection(zrState, forceTorqueOut, i, 1.0f);
  }
}

(Required) Called on every gspControl control cycle, It should be used to send debug and telemetry information to the ground.

Definition at line 94 of file ZRCommRoutines.cpp.

{
  dbg_short_packet  DebugVecShort; // short[16]
  dbg_ushort_packet DebugVecUShort; // ushort[16]
  dbg_float_packet  DebugVecFloat; // float[8]
  unsigned int tstep;

  // send debug after estimator convergence
  if (ctrlManeuverNumGet() < 3)
  {
    sendInit();
  }
  if (ctrlManeuverNumGet() > 1)
  {
    // normal game packages
    tstep = apiImpl.api->getTime();

    if (!tstep) return;   // only send starting with time 1, since time 0 can cause problems with initialization

    // initialize all packets to 0
    memset(DebugVecShort,  0, sizeof(dbg_short_packet));
    memset(DebugVecUShort, 0, sizeof(dbg_ushort_packet));
    memset(DebugVecFloat,  0, sizeof(dbg_float_packet));

    // debug short: POIs currently visible, other sat message, flare status
    DebugVecShort[0]  = (short)(tstep*10);            //Timestamp
    DebugVecShort[13] = game->getMirrorTimeRemaining();
    DebugVecShort[14] = challInfo.me.mirrorTime;

    //items
    for (int i = 0; i < NUM_ITEMS; i++){
      DebugVecShort[i + 1] = (unsigned short) challInfo.me.mpTime[i];
    }

    DebugVecShort[15] = challInfo.me.message;                   //message sent between players

    // unsigned short debug packet: status of game variables, known flare times
    DebugVecUShort[0] = (unsigned short)(tstep*10); //Timestamp


    DebugVecUShort[7] = (unsigned short) (sphereInLight(challInfo.me.zrState));
    DebugVecUShort[7] <<= 1;
    DebugVecUShort[7] += (unsigned short) (sphereInDark(challInfo.me.zrState));

    DebugVecUShort[8] = (challInfo.light.direction > 0);
    DebugVecUShort[9] = (unsigned short) (challInfo.camera.tookPicture);
    DebugVecUShort[10] = (unsigned short) (challInfo.camera.uploadedPictures);
    DebugVecUShort[11] = (unsigned short) (challInfo.camera.cameraOn);
    DebugVecUShort[13] = (unsigned short) (challInfo.camera.memorySize);
    DebugVecUShort[14] = (unsigned short) (challInfo.camera.memoryFilled);

    //Float debug packet: score, fuel, forces
    DebugVecFloat[0] = (float)tstep;
    DebugVecFloat[1] = game->getScore();
    DebugVecFloat[2] = game->getFuelRemaining() / ((double)PROP_ALLOWED_SECONDS);
    DebugVecFloat[3] = challInfo.me.energy;
    DebugVecFloat[4] = challInfo.light.center;

    memcpy(&DebugVecFloat[5], challInfo.me.userForces, 3*sizeof(float)); //Forces for reference

    //Send packets to other SPHERES/ground/sim; do not modify below this line
    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_SHORT_SIGNED, (unsigned char *) DebugVecShort,0);
    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_FLOAT, (unsigned char *) DebugVecFloat,0);
    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_SHORT_UNSIGNED, (unsigned char *) DebugVecUShort,0);

  #ifdef ZRSIMULATION
    apiImpl.ZRUserDbgVec[0] = (float)tstep;
    commSendPacket(COMM_CHANNEL_STL, GROUND, sysIdentityGet(), COMM_CMD_DBG_ZRUSER, (unsigned char *) apiImpl.ZRUserDbgVec,0);
  #endif
  }
}

for Corona SPHERES: sends POI & Solar Flare info to Sat 2 at start of game

Definition at line 166 of file ZRCommRoutines.cpp.

{
  #if (SPHERE_ID == SPHERE1)
      dbg_short_packet DebugVecShort;
      dbg_ushort_packet DebugVecUShort;
      dbg_float_packet DebugVecFloat;

    // sends light information to second satellite
    memset(DebugVecShort,  0, sizeof(dbg_short_packet));    // initialize packets to 0
    memset(DebugVecUShort,  0, sizeof(dbg_ushort_packet));
    memset(DebugVecFloat,  0, sizeof(dbg_float_packet));

    DebugVecShort[0] = 0;

    int upTo = 5;
    if (NUM_ITEMS < upTo) {
      upTo = NUM_ITEMS;
    }

    for (int i = 0; i < upTo; i++) {
      DebugVecShort[3*i + 1] = 10000 * challInfo.mpLoc[i][0];
      DebugVecShort[3*i + 2] = 10000 * challInfo.mpLoc[i][1];
      DebugVecShort[3*i + 3] = 10000 * challInfo.mpLoc[i][2];
    }

    DebugVecUShort[0] = 0;
    DebugVecUShort[1] = (short)0 + (challInfo.light.nextSwitchTime);

    #ifdef ALLIANCE
      DebugVecUShort[2] = 3;
    #else
      #ifdef ZR3D
        DebugVecUShort[2] = 2;
      #else
        #ifdef ZR2D
          DebugVecUShort[2] = 1;
        #else
          DebugVecUShort[2] = 0;
        #endif
      #endif
    #endif

    DebugVecUShort[3] = NUM_ITEMS;

    for (int i = 0; i < NUM_ITEMS; i++)
    {
      DebugVecUShort[4 + i] = ITEM_TYPES[i];
    }

      DebugVecFloat[0] = 0.0f;
      DebugVecFloat[1] = challInfo.light.center;
      DebugVecFloat[2] = challInfo.light.direction;

    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_SHORT_SIGNED, (unsigned char *) DebugVecShort,0);
    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_SHORT_UNSIGNED, (unsigned char *) DebugVecUShort,0);
    commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_FLOAT, (unsigned char *) DebugVecFloat,0);
  #endif
  #if (SPHERE_ID == SPHERE2)
      dbg_short_packet DebugVecShort;
      DebugVecShort[0] = 0;

      for (int i = 0; i < NUM_ITEMS - 5; i++)
      {
        DebugVecShort[3*i + 1] = 10000 * challInfo.mpLoc[i+5][0];
        DebugVecShort[3*i + 2] = 10000 * challInfo.mpLoc[i+5][1];
        DebugVecShort[3*i + 3] = 10000 * challInfo.mpLoc[i+5][2];
      }

      commSendPacket(COMM_CHANNEL_STL, BROADCAST, 0, COMM_CMD_DBG_SHORT_SIGNED, (unsigned char *) DebugVecShort,0);
  #endif
}
bool ZeroRoboticsGameImpl::sphereInDark ( float  position[])

Definition at line 103 of file ZRLight.cpp.

                                                        {
  #ifdef ALLIANCE
  return sphereInMovingArea(position) == -1;
  #else
  return sphereInSwitchingArea(position) == -1;
  #endif
}
bool ZeroRoboticsGameImpl::sphereInLight ( float  position[])

Definition at line 95 of file ZRLight.cpp.

                                                         {
  #ifdef ALLIANCE
  return sphereInMovingArea(position) == 1;
  #else
  return sphereInSwitchingArea(position) == 1;
  #endif
}
int ZeroRoboticsGameImpl::sphereInMovingArea ( float  position[])

Definition at line 71 of file ZRLight.cpp.

{

  float interface = challInfo.light.center; // Start of Light Zone
  float outerface = interface + challInfo.light.lightWidth; // End of light zone
  if(outerface > ZONE_pY)
    outerface -= 2*ZONE_pY; // Wraparound
  float halfWidth = challInfo.light.greyWidth*.5; // Grey width on either side
  if ((interface - halfWidth <= position[1] && interface + halfWidth >= position[1]) || // In the first grey zone
      (outerface - halfWidth <= position[1] && outerface + halfWidth >= position[1]) || // In the second gray zone
      (position[0] >= ZONE_pX || position[1] >= ZONE_pY || position[2] >= ZONE_pZ) || // Out of bounds positive
      (position[0] <= ZONE_nX || position[1] <= ZONE_nY || position[2] <= ZONE_nZ)) // Out of bounds negatively
  {
    return 0; // Gray 
  }
  else if ((outerface > position[1] && (interface < position[1] || outerface < interface)) || // before the end of the light zone and Either after the beginning or the end has wrapped around
          (interface < position[1] && outerface < interface))  // or it's after the beginning and the end has wrapped
  {
    return 1; //Light
  }

  return -1; // Dark
}

Definition at line 61 of file ZRLight.cpp.

                                                                {
  float center = challInfo.light.center;
  float diff = position[1] - center;
  diff *= challInfo.light.direction; // adjust for light direction

  if (diff > -challInfo.light.greyWidth/2 && diff < challInfo.light.greyWidth/2) return 0;
  if (diff < 0) return -1;
  return 1;
}

Definition at line 57 of file ZRLight.cpp.

Returns the score value of the picture, or 0 if taking the picture failed.

Definition at line 128 of file ZRCamera.cpp.

{

  challInfo.me.score += 0.01f;
  GAME_TRACE(("[%d] attempting to take picture... ", challInfo.currentTime));

  bool enoughSpace = challInfo.camera.memoryFilled < challInfo.camera.memorySize;


  // uses the energy even if the picture can't be taken
  // (if not enough space or not facing other sphere)
  bool usedEnergy = tryToUseEnergy(ENERGY_COST_TAKE_PICTURE);

  float pictureValue = picPointsImpl();

  if(enoughSpace && usedEnergy && pictureValue != 0)     // check if it can take a picture
  {
    challInfo.camera.tookPicture = true;
    // apply score modifiers etc
    challInfo.me.score += 0.1f;         // Very small value. Subject to change.
    challInfo.camera.memory[challInfo.camera.memoryFilled].picStored = true;

    challInfo.camera.memory[challInfo.camera.memoryFilled].value = pictureValue;
    // End of scoring

    challInfo.camera.memory[challInfo.camera.memoryFilled].round = 1;


    challInfo.camera.memoryFilled++;


    GAME_TRACE(("[%d] took picture (round %d) valued %4.2f points | ", apiImpl.api->getTime(), challInfo.camera.memory[challInfo.camera.memoryFilled-1].round, challInfo.camera.memory[challInfo.camera.memoryFilled-1].value));

  }
   else if(!enoughSpace && pictureValue != 0 ){
    GAME_TRACE(("Failed to take a picture: memory filled up | "));
  }
   else if(!usedEnergy && pictureValue != 0 ){
    GAME_TRACE(("Failed to take a picture: not enough energy | "));
  }

  disableCamera();

  return pictureValue;
}
bool ZeroRoboticsGameImpl::tryToUseEnergy ( float  amount)

Definition at line 17 of file ZREnergy.cpp.

{
  if (amount < 0) {
    GAME_TRACE(("DEV: trying to use negative energy. Check for bugs. | "));
    return false;
  }

  if (amount > challInfo.me.energy) {
    // GAME_TRACE(("Not enough energy to perform the action. | "));
    return false;
  }

  challInfo.me.energy -= amount;
  return true;
}
bool ZeroRoboticsGameImpl::update ( float  forceTorqueOut[6])

(Required) Runs an update of the game rules and calls the user function loop().

The return value for this function indicates if the forceTorqueOut vector should be mixed into thruster firings. The function should return 0 if the user does not activate any ZR API movement commands or implements their own thruster firing logic.

Here we update player's scores

/param forceTorqueOut forces and torques to be mixed into thruster firings /return return 1 if forceTorqueOut should be mixed into thruster firings and 0 otherwise

Definition at line 110 of file ZRGameInternal.cpp.

                                                         {
  updateStates();
  updateLight();
  updateEnergy();

  // empty the userForces array
  memset(challInfo.me.userForces,0,sizeof(float)*6);

  // declare a static finalResult variable
  // updateGameOverManuever will change it
  static unsigned char finalResult = 0;

  unsigned char useForces = false;

  // maneuver 3 = game mode
  // maneuver 202 = end game (get final score)
  // maneuver 204 = terminate

  switch (ctrlManeuverNumGet())
  {

    case 3:
      useForces = updateGameModeManeuver(forceTorqueOut);
      break;

    //------End main game code------//

    case 202: // Endgame scenario
      useForces = updateGameOverManeuver(forceTorqueOut, finalResult);
      break;

    case 203: // terminate test after determining final score
      {
        ctrlTestTerminate(finalResult);
      }
      break;
  }

  //Store user forces for sending to ground
  memcpy(challInfo.me.userForces, forceTorqueOut, sizeof(float)*6);

#ifdef ZR2D
  memset(&challInfo.me.userForces[2], 0, sizeof(float)*3);
#endif

  //Send Telemetry
  sendDebug();

  return useForces;

}
bool ZeroRoboticsGameImpl::updateGameModeManeuver ( float  forceTorqueOut[6])

Definition at line 231 of file ZRGameInternal.cpp.

                                                                         {
  float collisionInfo[2];

  // get state-of-health of other satellite (mainly for end of test)
  comm_payload_soh soh_partner;
  #if (SPHERE_ID == SPHERE1)
    commBackgroundSOHGet(SPHERE2, &soh_partner);
  #else
    commBackgroundSOHGet(SPHERE1, &soh_partner);
  #endif

  // determine current speed of satellite, use to determine collision avoidance motion
  float speed = mathVecMagnitude(&challInfo.me.sphState[3],3);

  unsigned char useForces = false;

  // if camera was used (so it can't be used again for 3 seconds), check when to enable it again
  if((!challInfo.camera.cameraOn) && ((challInfo.currentTime - challInfo.camera.cameraOffTime) > DISABLE_CAMERA_TIME))
  {
    activateCamera();
  }

  // Run user's "loop" function.  apiImpl is used because we are accessing
  // a private part of the API containing a pointer to the user's API
  apiImpl.zruser->loop();

  //Check if items are being picked up
  for (int i = 0; i < NUM_ITEMS; i++)
    itemPickUp(i);

  useForces = useForces || apiImpl.getForceTorque(forceTorqueOut);
  
  prop_time tent_times;
  #ifdef ZRFLATFLOOR
    ctrlMixWLoc(&tent_times, forceTorqueOut, challInfo.me.sphState, 10, 40.0f, FORCE_FRAME_INERTIAL);
  #else
    ctrlMixWLoc(&tent_times, forceTorqueOut, challInfo.me.sphState, 10, 20.0f, FORCE_FRAME_INERTIAL);
  #endif

  float tent_time_sum = 0;
  for (int i = 0; i < 12; i++) {
    tent_time_sum += tent_times.off_time[i]-tent_times.on_time[i];
  }

  //Check for fuel or energy out at this point
  if((game->getFuelRemaining() <= 0.0f || game->getEnergy() <= tent_time_sum * ENERGY_COST_THRUSTERS))
  {
    memset(forceTorqueOut,0,6*sizeof(float));   // anything the user has commanded is ignored, only firings would be from out-of-bounds or collission avoidance
    useForces = false;  // assume there will be no firings
  }

  //Enforce boundaries of the game
  if (enforceBoundaries(forceTorqueOut))
  {
    //challInfo.me.fuelUsed += OFFSIDES_PENALTY;
    GAME_TRACE(("[%d] out of bounds penalty | ", apiImpl.api->getTime()));
    useForces = true;
  }

  //Collision avoidance
  //check to see that its speed is not neglible.
  if (speed > 0.01f) {
    challInfo.me.collisionActive = ctrlAvoidWithOverride(challInfo.me.sphState,&challInfo.other.sphState,1,forceTorqueOut,collisionInfo,3);
  }

  //------Thruster control------//
    // Run standard mixer to get fuel consumption
  prop_time times;
  ctrlMixWLoc(&times, forceTorqueOut, challInfo.me.sphState, 10, 20.0f, FORCE_FRAME_INERTIAL);

  //Tally fuel and energy used for firing thrusters
  for (int i=0; i<12; i++)
  {
    float thrusterTime = times.off_time[i]-times.on_time[i];

    challInfo.me.fuelUsed += thrusterTime / 1000.0f;

    tryToUseEnergy(thrusterTime * ENERGY_COST_THRUSTERS);


    //Protect against NAN or INF hacking
    if (challInfo.me.fuelUsed < 0.0f)
    {
      DEBUG(("WARNING: invalid forces/torques applied to satellite at t=%d. Fuel will be set to 0. Check your code for errors.\n", challInfo.currentTime));
      challInfo.me.fuelUsed = PROP_ALLOWED_SECONDS;
    }
  }
  
  #ifdef ZR2D
    modify2DForceTorque(forceTorqueOut);
    useForces = true;
  #endif

  //------Game end conditions------//
  if (challInfo.currentTime >= (MAX_GAME_TIME))
    ctrlManeuverNumSet(202);

  return useForces;
}
bool ZeroRoboticsGameImpl::updateGameOverManeuver ( float  forceTorqueOut[6],
unsigned char &  finalScore 
)

Definition at line 331 of file ZRGameInternal.cpp.

                                                                                                     {
  unsigned char useForces = false;
  int result;

  float collisionInfo[2];

  // get state-of-health of other satellite (mainly for end of test)
  comm_payload_soh soh_partner;
  #if (SPHERE_ID == SPHERE1)
    commBackgroundSOHGet(SPHERE2, &soh_partner);
  #else
    commBackgroundSOHGet(SPHERE1, &soh_partner);
  #endif

  float myScore;
  float otherScore;

  myScore = game->getScore();
  otherScore = game->getOtherScore();

  useForces = ctrlAvoidWithOverride(challInfo.me.sphState, &challInfo.other.sphState, 1, forceTorqueOut, collisionInfo, 3) > 0;
  useForces = useForces || enforceBoundaries(forceTorqueOut);

  // break ties by making a tiny change based on the random state
  if (myScore == otherScore)
  {
    challInfo.me.score  -= (0.01f * sqrtf((challInfo.me.zrState[0]*challInfo.me.zrState[0])
      +(challInfo.me.zrState[1]*challInfo.me.zrState[1])+(challInfo.me.zrState[2]*challInfo.me.zrState[2])));
    GAME_TRACE (("Tie Breaker (%12.10f = %12.10f), new score = %12.10f | ", myScore, otherScore, challInfo.me.score));
  }

  // get final score
  if ((soh_partner.last_test_result || (soh_partner.maneuver_number > 200) || (NUM_SPHERES == 1)))
  {
    result = 10*floorf(myScore);
    if (result < 10) result = 10;
    if (result > 220) result = 220;
    if (myScore > otherScore)
      result += 10;
    finalResult = (result + apiImpl.getTeamId() + 1);
    useForces = false;
  }

  // terminate after we find the final result & timeout (4s)
  if (finalResult && (ctrlManeuverTimeGet() > 4000))
  {
    GAME_TRACE (("GAME ENDED! Final Score Float: %10.8f / Integer: %d | Test Result %d | ", myScore, result, finalResult));
    ctrlManeuverTerminate();
  }
  return useForces;
}

Definition at line 38 of file ZRLight.cpp.

Definition at line 97 of file ZRGameInternal.cpp.

                                        {
  apiImpl.api->getMyZRState(challInfo.me.zrState);
  apiImpl.api->getOtherZRState(challInfo.other.zrState);

  apiImpl.api->getMySphState(challInfo.me.sphState);
  apiImpl.api->getOtherSphState(challInfo.other.sphState);

  challInfo.currentTime = apiImpl.api->getTime();

  challInfo.camera.tookPicture = false;
  challInfo.camera.uploadedPictures = false;
}

Member Data Documentation

ZeroRoboticsAPIImpl& ZeroRoboticsGameImpl::apiImpl

Reference to ZR API instance.

Definition at line 224 of file ZRGameInternal.h.

Back pointer to the game instance.

Definition at line 227 of file ZRGameInternal.h.

const state_vector ZeroRoboticsGameImpl::initState [static]

(Required) Initial state where the satellite is initialized.

Definition at line 162 of file ZRGameInternal.h.


The documentation for this class was generated from the following files: