MovementControllerI.C

00001 #include "Robots/SeaBeeIII/MovementControllerI.H"
00002 
00003 #include "Component/ModelParam.H"
00004 #include "Component/ModelOptionDef.H"
00005 
00006 
00007 #ifndef MOVEMENTCONTROLLERI_C
00008 #define MOVEMENTCONTROLLERI_C
00009 
00010 // max speed sub can go
00011 #define MAX_SPEED              50.0
00012 
00013 // pose error must be below GATE_POSE_ERR_THRESH
00014 // in order to sleep for fwd gate time
00015 #define GATE_POSE_ERR_THRESH   10
00016 
00017 // quick hack to calculate barbwire position based on
00018 // percentage of img dims
00019 #define IMG_WIDTH              320.0
00020 #define IMG_HEIGHT             240.0
00021 
00022 // minimum diff needed between current pose and last pose
00023 // in order for beestem  message to be sent out
00024 #define MIN_POSE_DIFF         3.0
00025 
00026 /* Intialize Command-line parameters */
00027 const ModelOptionCateg MOC_SeaBeeIIIMovementController = {
00028     MOC_SORTPRI_3, "SeaBeeIII Movement Controller Related Options" };
00029 
00030 const ModelOptionDef OPT_GateFwdTime =
00031 { MODOPT_ARG(float), "GateFwdTime", &MOC_SeaBeeIIIMovementController, OPTEXP_CORE,
00032   "How long, in seconds, the SeaBeeIII should go forward to go through the gate.",
00033    "gate-time", '\0', "<float>", "40.0" };
00034 
00035 const ModelOptionDef OPT_GateDepth =
00036 { MODOPT_ARG(float), "GateDepth", &MOC_SeaBeeIIIMovementController, OPTEXP_CORE,
00037   "How deep the SeaBeeIII should go in order to pass underneath the gate.",
00038    "gate-depth", '\0', "<float>", "85.0" };
00039 
00040 const ModelOptionDef OPT_SaliencyHeadingCorrScale =
00041 { MODOPT_ARG(float), "SaliencyHeadingCorrScale", &MOC_SeaBeeIIIMovementController, OPTEXP_CORE,
00042   "The rate at which the SeaBeeIII should correct heading based on target point input",
00043   "headingcorr-scale", '\0', "<float>", "125.0" };
00044 
00045 const ModelOptionDef OPT_SaliencyDepthCorrScale =
00046 { MODOPT_ARG(float), "SaliencyDepthCorrScale", &MOC_SeaBeeIIIMovementController, OPTEXP_CORE,
00047   "The rate at which the SeaBeeIII should correct depth based on target point input",
00048   "depthcorr-scale", '\0', "<float>", "100.0" };
00049 
00050 const ModelOptionDef OPT_SpeedCorrScale =
00051 { MODOPT_ARG(float), "SpeedCorrScale", &MOC_SeaBeeIIIMovementController, OPTEXP_CORE,
00052   "The rate at which the SeaBeeIII should correct speed based on target point input",
00053   "speedcorr-scale", '\0', "<float>", "1.0" };
00054 
00055 // ######################################################################
00056 MovementControllerI::MovementControllerI(int id, OptionManager& mgr,
00057                 const std::string& descrName, const std::string& tagName) :
00058   RobotBrainComponent(mgr, descrName, tagName),
00059   itsGateFwdTime(&OPT_GateFwdTime, this, 0),
00060   itsGateDepth(&OPT_GateDepth, this, 0),
00061   itsSaliencyHeadingCorrScale(&OPT_SaliencyHeadingCorrScale, this, 0),
00062   itsSaliencyDepthCorrScale(&OPT_SaliencyDepthCorrScale, this, 0),
00063   itsSpeedCorrScale(&OPT_SpeedCorrScale, this, 0),
00064   itsCurrentState(STATE_INIT),
00065   itsKillSwitchState(1),
00066   itsPoseError(-1.0),
00067   itsLastCompositeHeading(0.0),
00068   itsLastCompositeDepth(0.0),
00069   itsLastSpeed(0.0),
00070   isInit(false),
00071   itsDiveVal(-1),
00072   itsDiveCount(0),
00073   itsHeadingVal(-1),
00074   itsPIDEnabled(false),
00075   itsSpeedEnabled(false)
00076 {
00077   // initialize SensorVotes
00078   initSensorVotes();
00079 
00080   // variables so we know which of the four paths we are following
00081   checker_path_follow_1 = 0;
00082   checker_path_follow_2 = 0;
00083   checker_path_follow_3 = 0;
00084 }
00085 
00086 // ######################################################################
00087 MovementControllerI::~MovementControllerI()
00088 {
00089 
00090 }
00091 
00092 // ######################################################################
00093 void MovementControllerI::registerTopics()
00094 {
00095   registerPublisher("BeeStemConfigTopic");
00096   registerPublisher("MovementControllerMessageTopic");
00097   registerSubscription("SeaBeePositionMessageTopic");
00098   registerSubscription("SeaBeeStateConditionMessageTopic");
00099   registerSubscription("XBox360RemoteControlMessageTopic");
00100   registerSubscription("BeeStemMessageTopic");
00101   registerSubscription("SalientPointMessageTopic");
00102   registerSubscription("VisionRectangleMessageTopic");
00103   registerSubscription("StraightEdgeMessageTopic");
00104 }
00105 
00106 // ######################################################################
00107 void MovementControllerI::initSensorVotes()
00108 {
00109   SensorVote path;
00110   path.type = PATH;
00111   path.heading.val = 0.0;
00112   path.heading.weight = 0.0;
00113   path.heading.decay = 0.0;
00114   path.init = false;
00115 
00116   SensorVote saliency;
00117   saliency.type = SALIENCY;
00118   saliency.heading.val = 0.0;
00119   saliency.heading.weight = 0.0;
00120   saliency.heading.decay = 0.0;
00121   saliency.init = false;
00122 
00123   SensorVote pinger;
00124   pinger.type = PINGER;
00125   pinger.heading.val = 0.0;
00126   pinger.heading.weight = 0.0;
00127   pinger.heading.decay = 0.0;
00128   pinger.init = false;
00129 
00130   SensorVote barbwire;
00131   barbwire.type = BARBWIRE;
00132   barbwire.heading.val = 0.0;
00133   barbwire.heading.weight = 0.0;
00134   barbwire.heading.decay = 0.0;
00135   barbwire.init = false;
00136 
00137   itsSensorVotes.push_back(path);
00138   itsSensorVotes.push_back(saliency);
00139   itsSensorVotes.push_back(pinger);
00140   itsSensorVotes.push_back(barbwire);
00141 }
00142 
00143 // ######################################################################
00144 void MovementControllerI::enablePID()
00145 {
00146   RobotSimEvents::BeeStemConfigMessagePtr msg = new RobotSimEvents::BeeStemConfigMessage;
00147   msg->desiredHeading = 0.0;
00148   msg->desiredDepth = 0.0;
00149   msg->desiredSpeed = 0.0;
00150   msg->updateDesiredValue = 0;
00151 
00152   msg->headingK = 0.0;
00153   msg->headingP = 0.0;
00154   msg->headingI = 0.0;
00155   msg->headingD = 0.0;
00156   msg->updateHeadingPID = false;
00157 
00158   msg->depthK = 0.0;
00159   msg->depthP = 0.0;
00160   msg->depthI = 0.0;
00161   msg->depthD = 0.0;
00162   msg->updateDepthPID = false;
00163 
00164   msg->enablePID = 1;
00165   msg->enableVal = 1;
00166 
00167   this->publish("BeeStemConfigTopic", msg);
00168 }
00169 
00170 // ######################################################################
00171 void MovementControllerI::disablePID()
00172 {
00173   set_speed(0);
00174   RobotSimEvents::BeeStemConfigMessagePtr msg = new RobotSimEvents::BeeStemConfigMessage;
00175   msg->desiredHeading = 0.0;
00176   msg->desiredDepth = 0.0;
00177   msg->desiredSpeed = 0.0;
00178   msg->updateDesiredValue = 0;
00179 
00180   msg->headingK = 0.0;
00181   msg->headingP = 0.0;
00182   msg->headingI = 0.0;
00183   msg->headingD = 0.0;
00184   msg->updateHeadingPID = false;
00185 
00186   msg->depthK = 0.0;
00187   msg->depthP = 0.0;
00188   msg->depthI = 0.0;
00189   msg->depthD = 0.0;
00190   msg->updateDepthPID = false;
00191 
00192   msg->enablePID = 1;
00193   msg->enableVal = 0;
00194   this->publish("BeeStemConfigTopic", msg);
00195 
00196 }
00197 
00198 void MovementControllerI::evolve()
00199 {
00200   its_current_pose_mutex.lock();
00201 
00202   // If this is the first evolve() loop, disable PID
00203   if(!isInit)
00204     {
00205       disablePID();
00206       itsPIDEnabled = false;
00207       isInit = true;
00208     }
00209 
00210   // If the kill switch is active and pid is enabled,
00211   // disable pid and reset the sub's state
00212   if(itsKillSwitchState == 1 && itsPIDEnabled)
00213     {
00214       itsPIDEnabled = false;
00215       disablePID();
00216 
00217       itsDiveVal = -1;
00218       itsHeadingVal = -1;
00219       itsCurrentState = STATE_INIT;
00220     }
00221 
00222   // If the kill switch is active, perform the movement control function
00223   // based on the sub's current state.
00224   if(itsKillSwitchState == 0)
00225     {
00226       switch(itsCurrentState)
00227         {
00228         case STATE_INIT:
00229           state_init();
00230           break;
00231         case STATE_DO_GATE:
00232           state_do_gate();
00233           break;
00234         case STATE_FIND_FLARE:
00235           state_find_flare();
00236           break;
00237         case STATE_DO_FLARE:
00238           state_do_flare();
00239           break;
00240         case STATE_FIND_BARBWIRE:
00241           state_find_barbwire();
00242           break;
00243         case STATE_DO_BARBWIRE:
00244           state_do_barbwire();
00245           break;
00246         case STATE_FIND_BOMBING:
00247           state_find_bombing();
00248           break;
00249         case STATE_DO_BOMBING:
00250           state_do_bombing();
00251           break;
00252         case STATE_FIND_BRIEFCASE:
00253           state_find_briefcase();
00254           break;
00255         case STATE_DO_BRIEFCASE:
00256           state_do_briefcase();
00257           break;
00258         case STATE_PATH_FOLLOW:
00259           state_path_follow();
00260           break;
00261         }
00262     }
00263   else
00264     LINFO("Waiting for kill switch...");
00265 
00266 
00267   // Check whether any of our SensorVotes has been init (i.e. a val has been set)
00268   bool votesInit = false;
00269 
00270   for(uint i = 0; i < itsSensorVotes.size(); i++)
00271     {
00272       if(itsSensorVotes[i].init)
00273         votesInit = true;
00274     }
00275 
00276 
00277   // If at least one val has been set and the kill switch is off
00278   if(votesInit && itsKillSwitchState == 0)
00279     {
00280       // Decay the weights of all SensorVotes
00281       for(uint i = 0; i < itsSensorVotes.size(); i++)
00282         {
00283           SensorVote sv = itsSensorVotes[i];
00284 
00285           if(sv.heading.decay >= 0.0 && sv.heading.decay <= 1.0)
00286             sv.heading.weight *= 1.0 - sv.heading.decay;
00287 
00288           if(sv.depth.decay >= 0.0 && sv.depth.decay <= 1.0)
00289             sv.depth.weight *= 1.0 - sv.depth.decay;
00290 
00291           itsSensorVotes[i] = sv;
00292         }
00293 
00294       // Calculate the composite heading and depth based on the SensorPose
00295       // values and weights of our SensorVotes
00296       float compositeHeading = 0.0;
00297       int totalHeadingWeight = 0;
00298       float compositeDepth = 0.0;
00299       float totalDepthWeight = 0.0;
00300 
00301       for(uint i = 0; i < itsSensorVotes.size(); i++)
00302         {
00303           SensorVote sv = itsSensorVotes[i];
00304 
00305           compositeHeading += sv.heading.val * sv.heading.weight;
00306           totalHeadingWeight += sv.heading.weight;
00307 
00308           compositeDepth += sv.depth.val * sv.depth.weight;
00309           totalDepthWeight += sv.depth.weight;
00310         }
00311 
00312       // If at lease one heading weight is set,
00313       // calculate final heading and send it to BeeStemI
00314       if(totalHeadingWeight != 0.0)
00315         {
00316 
00317           compositeHeading /= totalHeadingWeight;
00318 
00319           // make sure current heading differs from last heading by MIN_POSE_DIFF
00320           if(abs(itsLastCompositeHeading - compositeHeading) > MIN_POSE_DIFF)
00321             set_heading(compositeHeading);
00322         }
00323 
00324       // If at lease one depth weight is set,
00325       // calculate final depth and send it to BeeStemI
00326       if(totalDepthWeight != 0.0)
00327         {
00328           compositeDepth /= totalDepthWeight;
00329 
00330           // make sure current depth differs from last depth by MIN_POSE_DIFF
00331           if(abs(itsLastCompositeDepth - compositeDepth) > MIN_POSE_DIFF)
00332             set_depth(compositeDepth);
00333         }
00334 
00335 
00336       // Calculate the speed we should be going based on heading and depth error
00337       int headingErr = compositeHeading - its_current_heading;
00338       int depthErr = compositeDepth - its_current_ex_pressure;
00339 
00340       itsPoseError = sqrt((float)(headingErr*headingErr + depthErr*depthErr));
00341 
00342       float speedCorr = itsPoseError * itsSpeedCorrScale.getVal();
00343 
00344       // Make sure correction doesn't go above max speed
00345       if(speedCorr > MAX_SPEED)
00346         speedCorr = MAX_SPEED;
00347 
00348       // If setting speed is enabled, send corrected speed to BeeStemI
00349       if(itsSpeedEnabled)
00350         set_speed(MAX_SPEED - speedCorr);
00351 
00352       itsLastCompositeHeading = compositeHeading;
00353       itsLastCompositeDepth = compositeDepth;
00354       itsLastSpeed = MAX_SPEED - speedCorr;
00355 
00356       // Send out MovementControllerMessage to display in GUI
00357       RobotSimEvents::MovementControllerMessagePtr msg = new RobotSimEvents::MovementControllerMessage;
00358 
00359       for(uint i = 0; i < itsSensorVotes.size(); i++)
00360         {
00361           ImageIceMod::SensorVote sv = ImageIceMod::SensorVote();
00362           sv.type = (ImageIceMod::SensorType)i;
00363           sv.heading.val = itsSensorVotes[i].heading.val;
00364           sv.heading.weight = itsSensorVotes[i].heading.weight;
00365           sv.heading.decay = itsSensorVotes[i].heading.decay;
00366 
00367           sv.depth.val = itsSensorVotes[i].depth.val;
00368           sv.depth.weight = itsSensorVotes[i].depth.weight;
00369           sv.depth.decay = itsSensorVotes[i].depth.decay;
00370 
00371           msg->votes.push_back(sv);
00372         }
00373 
00374       msg->compositeHeading = compositeHeading;
00375       msg->compositeDepth = compositeDepth;
00376 
00377       this->publish("MovementControllerMessageTopic",msg);
00378     }
00379 
00380   its_current_pose_mutex.unlock();
00381 
00382   // Sleep on each loop to prevent MovementController from overloading BeeStemI with messages
00383   usleep(100000);
00384 }
00385 
00386 // ######################################################################
00387 void MovementControllerI::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg,
00388                 const Ice::Current&)
00389 {
00390   if(eMsg->ice_isA("::RobotSimEvents::SeaBeePositionMessage"))
00391     {
00392       RobotSimEvents::SeaBeePositionMessagePtr msg = RobotSimEvents::SeaBeePositionMessagePtr::dynamicCast(eMsg);
00393       printf("Got A Position Message! x: %f y: %f ori: %f y_var: %f x_var: %f", msg->x, msg->y, msg->orientation, msg->xVar, msg->yVar);
00394     }
00395 
00396   else if(eMsg->ice_isA("::RobotSimEvents::XBox360RemoteControlMessage"))
00397     {
00398       RobotSimEvents::JoyStickControlMessagePtr msg = RobotSimEvents::JoyStickControlMessagePtr::dynamicCast(eMsg);
00399       printf("Got A XBox Message! Axis: %d AxisVal: %d Button: %d ButtonVal: %d", msg->axis, msg->axisVal, msg->button, msg->butVal);
00400     }
00401 
00402   else if(eMsg->ice_isA("::RobotSimEvents::SeaBeeStateConditionMessage"))
00403     {
00404       RobotSimEvents::SeaBeeStateConditionMessagePtr msg = RobotSimEvents::SeaBeeStateConditionMessagePtr::dynamicCast(eMsg);
00405 
00406       // Message: Start over
00407       if (msg->StartOver==1)
00408         {
00409           itsCurrentState = STATE_INIT;
00410           checker_path_follow_1 = 0;
00411           checker_path_follow_2 = 0;
00412           checker_path_follow_3 = 0;
00413           printf("\nGOT MESSAGE: Starting Over\n");
00414         }
00415       // Message: Gate Done
00416       else if (msg->GateDone==1)
00417         {
00418           itsCurrentState = STATE_PATH_FOLLOW;
00419           checker_path_follow_1 = 0;
00420           checker_path_follow_2 = 0;
00421           checker_path_follow_3 = 0;
00422           printf("\nGOT MESSAGE: Gate Done... Starting Path Follow\n");
00423         }
00424       // Message: Flare Done
00425       else if (msg->FlareDone==1)
00426         {
00427           itsCurrentState = STATE_PATH_FOLLOW;
00428           checker_path_follow_1 = 1;
00429           checker_path_follow_2 = 0;
00430           checker_path_follow_3 = 0;
00431           printf("\nGOT MESSAGE: Flare Done... Starting Path Follow\n");
00432         }
00433       // Message: Barbwire Done
00434       else if (msg->BarbwireDone==1)
00435         {
00436           itsCurrentState = STATE_PATH_FOLLOW;
00437           checker_path_follow_1 = 1;
00438           checker_path_follow_2 = 1;
00439           checker_path_follow_3 = 0;
00440           printf("\nGOT MESSAGE: Barbwire Done... Starting Path Follow\n");
00441         }
00442       // Message: Bombing Run Done
00443       else if (msg->BombingRunDone==1)
00444         {
00445           itsCurrentState = STATE_PATH_FOLLOW;
00446           checker_path_follow_1 = 1;
00447           checker_path_follow_2 = 1;
00448           checker_path_follow_3 = 1;
00449           printf("\nGOT MESSAGE: Bombing Done... Starting Path Follow\n");
00450         }
00451       // Message: Briefcase Found
00452       else if (msg->BriefcaseFound==1)
00453         {
00454           itsCurrentState = STATE_DO_BRIEFCASE;
00455           checker_path_follow_1 = 1;
00456           checker_path_follow_2 = 1;
00457           checker_path_follow_3 = 1;
00458           printf("\nGOT MESSAGE: Briefcase Found... Doing Briefcase\n");
00459         }
00460     }
00461   else if(eMsg->ice_isA("::RobotSimEvents::BeeStemMessage"))
00462     {
00463 
00464       RobotSimEvents::BeeStemMessagePtr msg = RobotSimEvents::BeeStemMessagePtr::dynamicCast(eMsg);
00465       its_current_pose_mutex.lock();
00466 
00467       its_current_heading = msg->compassHeading;
00468       its_current_ex_pressure = msg->externalPressure;
00469       its_current_int_pressure = msg->internalPressure;
00470       itsKillSwitchState = msg->killSwitch;
00471 
00472       if(itsKillSwitchState)
00473         itsCurrentState =  STATE_INIT;
00474 
00475       its_current_pose_mutex.unlock();
00476     }
00477   else if(eMsg->ice_isA("::RobotSimEvents::SalientPointMessage"))
00478     {
00479       RobotSimEvents::SalientPointMessagePtr msg = RobotSimEvents::SalientPointMessagePtr::dynamicCast(eMsg);
00480 
00481       SensorVote saliency = itsSensorVotes[SALIENCY];
00482 
00483       its_current_pose_mutex.lock();
00484 
00485       // if we haven't set a saliency heading yet, set one
00486       if(!saliency.init)
00487         {
00488           saliency.heading.val = ((msg->x - 0.5) * itsSaliencyHeadingCorrScale.getVal()) + its_current_heading;
00489           saliency.depth.val = ((msg->y - 0.5) * itsSaliencyDepthCorrScale.getVal()) + its_current_ex_pressure;
00490           saliency.init = true;
00491         }
00492       // otherwise, add the new salient point heading into
00493       // the running average
00494       else
00495         {
00496 
00497           saliency.heading.val =
00498             (0.0 * ( saliency.heading.val ) +
00499              1.0 * ((msg->x - 0.5) * itsSaliencyHeadingCorrScale.getVal()
00500                    + its_current_heading));
00501 
00502           saliency.heading.val = (int)(saliency.heading.val) % 360;
00503 
00504           if(saliency.heading.val < 0)
00505             saliency.heading.val += 360.0;
00506 
00507           saliency.depth.val =
00508             (.6 * ( saliency.depth.val ) +
00509              .4 * ((msg->y - 0.5) * itsSaliencyDepthCorrScale.getVal())
00510              + its_current_ex_pressure);
00511 
00512         }
00513 
00514       itsSensorVotes[SALIENCY] = saliency;
00515       its_current_pose_mutex.unlock();
00516     }
00517   else if(eMsg->ice_isA("::RobotSimEvents::StraightEdgeMessage"))
00518     {
00519       RobotSimEvents::StraightEdgeMessagePtr msg =
00520         RobotSimEvents::StraightEdgeMessagePtr::dynamicCast(eMsg);
00521       its_current_pose_mutex.lock();
00522 
00523       // don't override the path if we are trying to go through the gate
00524       if(itsCurrentState != STATE_INIT && itsCurrentState != STATE_DO_GATE)
00525         {
00526           SensorVote path = itsSensorVotes[PATH];
00527 
00528           LINFO("Setting path heading weight");
00529           path.heading.val = msg->line.angle + its_current_heading;
00530           path.heading.weight = 2.0;
00531           itsSensorVotes[PATH] = path;
00532         }
00533 
00534 
00535 
00536       its_current_pose_mutex.unlock();
00537 
00538     }
00539   else if(eMsg->ice_isA("::RobotSimEvents::VisionRectangleMessage"))
00540     {
00541       RobotSimEvents::VisionRectangleMessagePtr msg = RobotSimEvents::VisionRectangleMessagePtr::dynamicCast(eMsg);
00542 
00543       its_current_pose_mutex.lock();
00544 
00545       if(msg->isFwdCamera)
00546         {
00547           SensorVote barbwire = itsSensorVotes[BARBWIRE];
00548 
00549           for(uint i = 0; i < msg->quads.size(); i++)
00550             {
00551               // if we haven't set a barbwire heading, set one
00552               if(!barbwire.init)
00553                 {
00554                   barbwire.heading.val = ((((float)(msg->quads[i].center.i)/IMG_WIDTH) - 0.5) *
00555                                           itsSaliencyHeadingCorrScale.getVal()) + its_current_heading;
00556                   barbwire.depth.val = ((((float)(msg->quads[i].center.j)/IMG_HEIGHT) - 0.5) *
00557                                         itsSaliencyDepthCorrScale.getVal()) + its_current_ex_pressure;
00558                   barbwire.init = true;
00559                 }
00560               //otherwise, add it to running average
00561               else
00562                 {
00563                   barbwire.heading.val =
00564                     .8 * ( barbwire.heading.val ) +
00565                     .2 * (((msg->quads[i].center.i/IMG_WIDTH) - 0.5) *
00566                           itsSaliencyHeadingCorrScale.getVal()) + its_current_heading;
00567 
00568                   barbwire.depth.val =
00569                     .8 * ( barbwire.depth.val ) +
00570                     .2 * (((msg->quads[i].center.j/IMG_HEIGHT) - 0.5) *
00571                           itsSaliencyDepthCorrScale.getVal()) + its_current_ex_pressure;
00572                 }
00573 
00574               barbwire.heading.weight = 1.0;
00575             }
00576 
00577           itsSensorVotes[BARBWIRE] = barbwire;
00578         }
00579       else
00580         {
00581           SensorVote path = itsSensorVotes[PATH];
00582 
00583           // don't override the path if we are trying to go through the gate
00584           if(itsCurrentState != STATE_INIT && itsCurrentState != STATE_DO_GATE)
00585             {
00586               for(uint i = 0; i < msg->quads.size(); i++)
00587                 {
00588                   // if we haven't set a path heading, set one
00589                   if(!path.init)
00590                     {
00591                       path.heading.val = its_current_heading + msg->quads[i].angle;
00592                       path.init = true;
00593                     }
00594                   //otherwise, add it to running average
00595                   else
00596                     {
00597                       path.heading.val += its_current_heading + msg->quads[i].angle;
00598                       path.heading.val /= 2;
00599                     }
00600 
00601                   path.heading.weight = 1.0;
00602                 }
00603             }
00604 
00605           itsSensorVotes[PATH] = path;
00606         }
00607 
00608       its_current_pose_mutex.unlock();
00609     }
00610 }
00611 
00612 // ######################################################################
00613 void MovementControllerI::state_init()
00614 {
00615 
00616   // First stage of dive, should only happen once
00617   if(itsDiveVal == -1 && itsDiveCount < 4)
00618     {
00619       LINFO("Doing initial dive");
00620 
00621       // Give diver 5 seconds to point sub at gate
00622       its_current_pose_mutex.unlock();
00623       sleep(5);
00624       its_current_pose_mutex.lock();
00625 
00626       // Make sure other SensorVotes do not have weights
00627       // before going through gate
00628       itsSensorVotes[SALIENCY].heading.weight = 0.0;
00629       itsSensorVotes[SALIENCY].depth.weight = 0.0;
00630 
00631       itsSensorVotes[PINGER].heading.weight = 0.0;
00632       itsSensorVotes[PINGER].depth.weight = 0.0;
00633 
00634       itsSensorVotes[BARBWIRE].heading.weight = 0.0;
00635       itsSensorVotes[BARBWIRE].depth.weight = 0.0;
00636 
00637       // Set our desired heading to our current heading
00638       // and set a heading weight
00639       itsHeadingVal = its_current_heading;
00640       itsSensorVotes[PATH].heading.val = itsHeadingVal;
00641       itsSensorVotes[PATH].heading.weight = 1.0;
00642 
00643 
00644       // Set our desired depth to a fourth of itsGateDepth.
00645       // This is done because we are diving in 4 stages.
00646       // Also set a depth weight.
00647       itsDiveVal = its_current_ex_pressure + itsGateDepth.getVal() / 4;
00648       itsSensorVotes[PATH].depth.val = itsDiveVal;
00649       itsSensorVotes[PATH].depth.weight = 1.0;
00650 
00651       // Increment the dive stage we are on
00652       itsDiveCount++;
00653 
00654       // Indicate that PATH SensorVote vals have been set
00655       itsSensorVotes[PATH].init = true;
00656 
00657       // Enable PID
00658       enablePID();
00659 
00660     }
00661   // Dive States 2 through 4
00662   else if(itsDiveVal != -1 &&
00663           abs(itsDiveVal - its_current_ex_pressure) <= 4 && itsDiveCount < 4)
00664     {
00665       // Add an additional fourth of itsGateDepth to our desired depth
00666       itsDiveVal = its_current_ex_pressure + itsGateDepth.getVal() / 4;
00667       itsSensorVotes[PATH].depth.val = itsDiveVal;
00668       itsSensorVotes[PATH].depth.weight = 1.0;
00669 
00670       // increment the dive state
00671       itsDiveCount++;
00672 
00673       LINFO("Diving stage %d", itsDiveCount);
00674 
00675       LINFO("itsDiveVal: %d, itsErr: %d", itsDiveVal, abs(itsDiveVal - its_current_ex_pressure));
00676     }
00677   // After going through all 4 stages of diving, go forward through the gate
00678   else if(itsDiveVal != -1 &&
00679           abs(itsDiveVal - its_current_ex_pressure) <= 4 && itsDiveCount >= 4)
00680     {
00681       itsCurrentState = STATE_DO_GATE;
00682 
00683       LINFO("State Init -> State Do Gate");
00684     }
00685 }
00686 
00687 
00688 // ######################################################################
00689 void MovementControllerI::state_do_gate()
00690 {
00691   LINFO("Moving towards gate...");
00692 
00693   // Set speed to MAX_SPEED
00694   set_speed(MAX_SPEED);
00695   its_current_pose_mutex.unlock();
00696   // Sleep for itsGateFwdTime
00697   sleep(itsGateFwdTime.getVal());
00698   its_current_pose_mutex.lock();
00699 
00700   LINFO("Finished going through gate...");
00701 
00702   // Start following saliency to go towards flare
00703   itsCurrentState = STATE_DO_FLARE;
00704 }
00705 
00706 // ######################################################################
00707 void MovementControllerI::state_find_flare()
00708 {
00709   printf("\n. . . Looking for Flare . . .\n");
00710 
00711         /*
00712 
00713                  looking for flare code
00714 
00715          */
00716 
00717         sleep(2);
00718         printf("\n. . . Found Flare . . .\n");
00719         itsCurrentState = STATE_DO_FLARE;
00720 
00721 }
00722 
00723 // ######################################################################
00724 void MovementControllerI::state_do_flare()
00725 {
00726   LINFO("Doing Flare...");
00727 
00728   // Enable speed based on heading and depth error
00729   if(!itsSpeedEnabled)
00730     itsSpeedEnabled = true;
00731 
00732   // Set SALIENCY SensorVote's heading weight to 1.0
00733   // so that we begin to follow saliency
00734   itsSensorVotes[SALIENCY].heading.weight = 1.0;
00735 
00736   // Decay the weight we place on PATH SensorVote's heading
00737   itsSensorVotes[PATH].heading.decay = 0.005;
00738   LINFO("heading weight: %f",itsSensorVotes[PATH].heading.weight);
00739 }
00740 
00741 // ######################################################################
00742 void MovementControllerI::state_find_barbwire()
00743 {
00744         printf("\n. . . Looking for Barbwire . . .\n");
00745 
00746         /*
00747 
00748                  keep going straight
00749                  until the barbwire comes into view
00750 
00751          */
00752 
00753         sleep(2);
00754         printf("\n. . . Found Barbwire . . .\n");
00755         itsCurrentState = STATE_DO_BARBWIRE;
00756 }
00757 
00758 // ######################################################################
00759 void MovementControllerI::state_do_barbwire()
00760 {
00761         printf("\n. . . Doing Barbwire . . .\n");
00762 
00763         /*
00764                  keep going until the green bar is xxx size
00765                  across the screen
00766                  make sure we are aligned properly
00767                  then go downwards, and then go forward for
00768                  xxx time
00769          */
00770 
00771         sleep(2);
00772         printf("\n. . . Finished Barbwire . . .\n");
00773         itsCurrentState = STATE_PATH_FOLLOW;
00774 }
00775 
00776 // ######################################################################
00777 void MovementControllerI::state_find_bombing()
00778 {
00779         printf("\n. . . Looking for Bombing Run . . .\n");
00780 
00781         /*
00782                  look at compass and make sure we are not going
00783                  towards the machine gun nest
00784                  keep going straight until sam's module
00785                  finds the boxes
00786          */
00787 
00788         sleep(2);
00789                 printf("\n. . . Found Bombing Run . . .\n");
00790         itsCurrentState = STATE_DO_BOMBING;
00791 }
00792 
00793 // ######################################################################
00794 void MovementControllerI::state_do_bombing()
00795 {
00796         printf("\n. . . Doing Bombing Run . . .\n");
00797 
00798         /*
00799                  keep going forward
00800                  make sure that we are xxx depth above the bottom
00801                  or the boxes are in the bottom of the screen
00802                  keep going until the boxes are recognized on
00803                  the bottom camera
00804                  drop bombs
00805          */
00806 
00807         sleep(2);
00808         printf("\n. . . Finished Bombing Run . . .\n");
00809         itsCurrentState = STATE_PATH_FOLLOW;
00810 }
00811 
00812 // ######################################################################
00813 void MovementControllerI::state_find_briefcase()
00814 {
00815         printf("\n. . . Looking for Briefcase . . .\n");
00816 
00817         /*
00818                  follow pinger
00819          */
00820         sleep(2);
00821         printf("\n. . . Found Briefcase . . .\n");
00822         itsCurrentState = STATE_DO_BRIEFCASE;
00823 }
00824 
00825 // ######################################################################
00826 void MovementControllerI::state_do_briefcase()
00827 {
00828         printf("\n. . . Doing Briefcase . . .\n");
00829 
00830         /*
00831                  once pinger has gotten us close enough
00832                  keep going in that direction until we can see it
00833                  keep going over it until bottom camera can see it
00834                  hop across it and pick it up
00835                  surface straight up
00836          */
00837         sleep(2);
00838         printf("\n. . . Finished Briefcase . . .\n");
00839         exit(0);
00840 }
00841 
00842 // ######################################################################
00843 void MovementControllerI::state_path_follow()
00844 {
00845   /*  its_current_pose_mutex.lock();
00846   for(uint i = 0; i < itsQuads.size(); i++)
00847     {
00848       set_heading(its_current_heading + itsQuads[i].angle);
00849       //      set_speed(PATH_SPEED);
00850 
00851       its_current_pose_mutex.unlock();
00852       sleep(PATH_SLEEP_TIME);
00853       its_current_pose_mutex.lock();
00854     }
00855   itsQuads.clear();
00856   its_current_pose_mutex.unlock();
00857 
00858   if(checker_path_follow_1 == 0)
00859     {
00860       // comment this out for now so we keep
00861       // executing this block every time we find a path
00862       //checker_path_follow_1 = 1;
00863       printf("\n. . . Following Orange Path (1st) . . .\n");
00864 
00865 
00866 
00867       printf("\n. . . Finished Orange Path (1st) . . .\n");
00868       itsCurrentState = STATE_FIND_FLARE;
00869     }
00870   else if(checker_path_follow_1 == 1 && checker_path_follow_2 == 0)
00871     {
00872       checker_path_follow_2 = 1;
00873       printf("\n. . . Following Orange Path (2nd) . . .\n");
00874       sleep(2);
00875       printf("\n. . . Finished Orange Path (2nd) . . .\n");
00876       itsCurrentState = STATE_FIND_BARBWIRE;
00877     }
00878   else if(checker_path_follow_2 == 1 && checker_path_follow_3 == 0)
00879     {
00880       checker_path_follow_3 = 1;
00881       printf("\n. . . Following Orange Path (3rd) . . .\n");
00882       sleep(2);
00883       printf("\n. . . Finished Orange Path (3rd) . . .\n");
00884       itsCurrentState = STATE_FIND_BOMBING;
00885         }
00886   else if(checker_path_follow_3 == 1)
00887     {
00888       printf("\n. . . Following Orange Path (4th) . . .\n");
00889       sleep(2);
00890       printf("\n. . . Finished Orange Path (4th) . . .\n");
00891       itsCurrentState = STATE_FIND_BRIEFCASE;
00892     }
00893 
00894 
00895 
00896     Path follow code here
00897 
00898   */
00899 }
00900 
00901 // ######################################################################
00902 void MovementControllerI::set_depth(int depth)
00903 {
00904         RobotSimEvents::BeeStemConfigMessagePtr msg = new RobotSimEvents::BeeStemConfigMessage;
00905 
00906   msg->headingK = 0.0;
00907   msg->headingP = 0.0;
00908   msg->headingI = 0.0;
00909   msg->headingD = 0.0;
00910   msg->updateHeadingPID = false;
00911   msg->depthK = 0.0;
00912   msg->depthP = 0.0;
00913   msg->depthI = 0.0;
00914   msg->depthD = 0.0;
00915   msg->updateDepthPID = false;
00916   msg->enablePID = 0;
00917   msg->enableVal = 0;
00918 
00919   msg->updateDesiredValue = 2;
00920   msg->desiredDepth = depth;
00921   this->publish("BeeStemConfigTopic", msg);
00922 }
00923 
00924 void MovementControllerI::set_speed(int speed)
00925 {
00926   // make sure we don't go too fast
00927   if(speed > MAX_SPEED)
00928     speed = MAX_SPEED;
00929 
00930   RobotSimEvents::BeeStemConfigMessagePtr msg = new RobotSimEvents::BeeStemConfigMessage;
00931 
00932   msg->headingK = 0.0;
00933   msg->headingP = 0.0;
00934   msg->headingI = 0.0;
00935   msg->headingD = 0.0;
00936   msg->updateHeadingPID = false;
00937   msg->depthK = 0.0;
00938   msg->depthP = 0.0;
00939   msg->depthI = 0.0;
00940   msg->depthD = 0.0;
00941   msg->updateDepthPID = false;
00942   msg->enablePID = 0;
00943   msg->enableVal = 0;
00944 
00945   msg->updateDesiredValue = 3;
00946   msg->desiredSpeed = speed;
00947 
00948   this->publish("BeeStemConfigTopic", msg);
00949 }
00950 
00951 void MovementControllerI::set_heading(int heading)
00952 {
00953   RobotSimEvents::BeeStemConfigMessagePtr msg = new RobotSimEvents::BeeStemConfigMessage;
00954 
00955   msg->headingK = 0.0;
00956   msg->headingP = 0.0;
00957   msg->headingI = 0.0;
00958   msg->headingD = 0.0;
00959   msg->updateHeadingPID = false;
00960   msg->depthK = 0.0;
00961   msg->depthP = 0.0;
00962   msg->depthI = 0.0;
00963   msg->depthD = 0.0;
00964   msg->updateDepthPID = false;
00965   msg->enablePID = 0;
00966   msg->enableVal = 0;
00967 
00968   msg->updateDesiredValue = 1;
00969   msg->desiredHeading = heading;
00970   this->publish("BeeStemConfigTopic", msg);
00971 }
00972 
00973 #endif
Generated on Sun May 8 08:41:38 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3