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