00001 /*!@file SeaBee/SubController.C Control motors and pid */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/SeaBee/SubController.C $ 00035 // $Id: SubController.C 10794 2009-02-08 06:21:09Z itti $ 00036 // 00037 00038 #include "SeaBee/SubController.H" 00039 #include "Component/ModelOptionDef.H" 00040 #include "Devices/DeviceOpts.H" 00041 #include "Util/Assert.H" 00042 #include "Image/DrawOps.H" 00043 00044 #define CMD_DELAY 6000 00045 #define INT_CLVL_PRESSURE 225 00046 00047 const ModelOptionCateg MOC_SeaBee_Controller = { 00048 MOC_SORTPRI_3, "SeaBee controller related options" }; 00049 00050 const ModelOptionDef OPT_SeaBeeSimMode = 00051 { MODOPT_FLAG, "SeabeeSimMode", &MOC_SeaBee_Controller, OPTEXP_CORE, 00052 "Run in simulator mode", 00053 "seabee-sim-mode", '\0', "", "false" }; 00054 00055 namespace 00056 { 00057 class SubControllerPIDLoop : public JobWithSemaphore 00058 { 00059 public: 00060 SubControllerPIDLoop(SubController* subCtrl) 00061 : 00062 itsSubController(subCtrl), 00063 itsPriority(1), 00064 itsJobType("controllerLoop") 00065 {} 00066 00067 virtual ~SubControllerPIDLoop() {} 00068 00069 virtual void run() 00070 { 00071 ASSERT(itsSubController); 00072 while(1) 00073 { 00074 itsSubController->sendHeartBeat(); 00075 itsSubController->updatePID(); 00076 } 00077 } 00078 00079 virtual const char* jobType() const 00080 { return itsJobType.c_str(); } 00081 00082 virtual int priority() const 00083 { return itsPriority; } 00084 00085 private: 00086 SubController* itsSubController; 00087 const int itsPriority; 00088 const std::string itsJobType; 00089 }; 00090 } 00091 00092 00093 // ###################################################################### 00094 SubController::SubController(OptionManager& mgr, 00095 const std::string& descrName, 00096 const std::string& tagName, 00097 const bool simulation): 00098 00099 ModelComponent(mgr, descrName, tagName), 00100 itsSimulation(&OPT_SeaBeeSimMode, this, ALLOW_ONLINE_CHANGES), 00101 itsDesiredPitch(30), 00102 itsDesiredRoll(0), 00103 itsDesiredHeading(20), 00104 itsDesiredDepth(200), 00105 itsDesiredSpeed(0), 00106 itsDesiredTurningSpeed(0), 00107 itsCurrentPitch(0), 00108 itsCurrentRoll(0), 00109 itsCurrentHeading(0), 00110 itsCurrentDepth(-1), 00111 itsCurrentSpeed(0), 00112 speedScale("speedScale", this, 1, ALLOW_ONLINE_CHANGES), 00113 itsSpeedScale(speedScale.getVal()), 00114 depthRatio("depthRatio", this, 1.3, ALLOW_ONLINE_CHANGES), 00115 itsDepthRatio(depthRatio.getVal()), 00116 itsPitchPID(0.5f, 0.0, 0.0, -20, 20), 00117 itsRollPID(0.0f, 0, 0, -20, 20), 00118 headingP("headingP", this, 2.0, ALLOW_ONLINE_CHANGES), 00119 headingI("headingI", this, 0, ALLOW_ONLINE_CHANGES), 00120 headingD("headingD", this, 0, ALLOW_ONLINE_CHANGES), 00121 itsHeadingPID(headingP.getVal(), headingI.getVal(), headingD.getVal(), -20, 20), 00122 depthP("depthP", this, -13.0, ALLOW_ONLINE_CHANGES), 00123 depthI("depthI", this, -0.5, ALLOW_ONLINE_CHANGES), 00124 depthD("depthD", this, -8.0, ALLOW_ONLINE_CHANGES), 00125 itsDepthPID(depthP.getVal(), depthI.getVal(), depthD.getVal(), -20, 20), 00126 itsCurrentThruster_Up_Left(0), 00127 itsCurrentThruster_Up_Right(0), 00128 itsCurrentThruster_Up_Back(0), 00129 itsCurrentThruster_Fwd_Right(0), 00130 itsCurrentThruster_Fwd_Left(0), 00131 setCurrentThruster_Up_Left("ThrusterUpLeft", this, 0, ALLOW_ONLINE_CHANGES), 00132 setCurrentThruster_Up_Right("ThrusterUpRight", this, 0, ALLOW_ONLINE_CHANGES), 00133 setCurrentThruster_Up_Back("ThrusterUpBack", this, 0, ALLOW_ONLINE_CHANGES), 00134 setCurrentThruster_Fwd_Right("ThrusterFwdRight", this, 0, ALLOW_ONLINE_CHANGES), 00135 setCurrentThruster_Fwd_Left("ThrusterFwdLeft", this, 0, ALLOW_ONLINE_CHANGES), 00136 pitchP("pitchP", this, 0, ALLOW_ONLINE_CHANGES), 00137 pitchI("pitchI", this, 0, ALLOW_ONLINE_CHANGES), 00138 pitchD("pitchD", this, 0, ALLOW_ONLINE_CHANGES), 00139 rollP("rollP", this, 0, ALLOW_ONLINE_CHANGES), 00140 rollI("rollI", this, 0, ALLOW_ONLINE_CHANGES), 00141 rollD("rollD", this, 0, ALLOW_ONLINE_CHANGES), 00142 motorsOn("motorsOn", this, false, ALLOW_ONLINE_CHANGES), 00143 pidOn("pidOn", this, true, ALLOW_ONLINE_CHANGES), 00144 guiOn("guiOn", this, true, ALLOW_ONLINE_CHANGES), 00145 depthPIDDisplay("Depth PID Disp", this, false, ALLOW_ONLINE_CHANGES), 00146 pitchPIDDisplay("Pitch PID Disp", this, false, ALLOW_ONLINE_CHANGES), 00147 headingPIDDisplay("Heading PID Disp", this, false, ALLOW_ONLINE_CHANGES), 00148 rollPIDDisplay("Roll PID Disp", this, false, ALLOW_ONLINE_CHANGES), 00149 00150 setDepthValue("DepthValue", this, 450, ALLOW_ONLINE_CHANGES), 00151 setPitchValue("PitchValue", this, itsDesiredPitch, ALLOW_ONLINE_CHANGES), 00152 setRollValue("RollValue", this, 0, ALLOW_ONLINE_CHANGES), 00153 setHeadingValue("HeadingValue", this, 20, ALLOW_ONLINE_CHANGES), 00154 itsPIDImage(256, 256, ZEROS), 00155 itsSubImage(256, 256, ZEROS), 00156 itsPrevDepth(0), 00157 itsPrevPrevDepth(0), 00158 itsDepthCount(0) 00159 { 00160 if (itsSimulation.getVal()) 00161 { 00162 itsBeeStemSim = nub::soft_ref<BeeStemSim>(new BeeStemSim(mgr)); 00163 addSubComponent(itsBeeStemSim); 00164 00165 } 00166 else 00167 { 00168 itsBeeStemTiny = nub::soft_ref<BeeStemTiny>(new BeeStemTiny(mgr,"BeeStemTiny", "BeeStemTiny", "/dev/ttyS1")); 00169 addSubComponent(itsBeeStemTiny); 00170 00171 itsForwardCam = nub::ref<V4L2grabber>(new V4L2grabber(mgr)); 00172 itsForwardCam->exportOptions(MC_RECURSE); 00173 addSubComponent(itsForwardCam); 00174 00175 itsBottomCam = nub::ref<V4L2grabber>(new V4L2grabber(mgr)); 00176 itsBottomCam->exportOptions(MC_RECURSE); 00177 addSubComponent(itsBottomCam); 00178 } 00179 00180 } 00181 00182 void SubController::start1() 00183 { 00184 if (!(itsSimulation.getVal())) 00185 { 00186 itsForwardCam->setModelParamVal("FrameGrabberDevice",std::string("/dev/video0")); 00187 itsBottomCam->setModelParamVal("FrameGrabberDevice",std::string("/dev/video1")); 00188 } 00189 } 00190 00191 void SubController::start2() 00192 { 00193 00194 killMotors(); 00195 sleep(1); 00196 00197 //setup pid loop thread 00198 itsThreadServer.reset(new WorkThreadServer("SubController",1)); //start a single worker thread 00199 itsThreadServer->setFlushBeforeStopping(false); 00200 rutz::shared_ptr<SubControllerPIDLoop> j(new SubControllerPIDLoop(this)); 00201 itsThreadServer->enqueueJob(j); 00202 00203 setHeading(getHeading()); 00204 00205 if (!(itsSimulation.getVal())) 00206 { 00207 itsForwardCam->startStream(); 00208 itsBottomCam->startStream(); 00209 } 00210 00211 } 00212 00213 // ###################################################################### 00214 SubController::~SubController() 00215 { 00216 00217 //killMotors(); 00218 } 00219 00220 void SubController::sendHeartBeat() 00221 { 00222 // itsBeeStem->setHeartBeat(); 00223 usleep(10000); 00224 } 00225 00226 // ###################################################################### 00227 void SubController::initSensorVals() 00228 { 00229 itsBeeStemTiny->getSensors(itsCurrentHeading, 00230 itsCurrentPitch, 00231 itsCurrentRoll, 00232 itsCurrentDepth, 00233 itsCurrentIntPressure); 00234 } 00235 00236 // ###################################################################### 00237 bool SubController::setHeading(int heading) 00238 { 00239 //<TODO mmontalbo> check for heading greater than 360 00240 heading = heading % 360; 00241 00242 itsDesiredHeading = heading; 00243 return true; 00244 } 00245 00246 // ###################################################################### 00247 bool SubController::setPitch(int pitch) 00248 { 00249 itsDesiredPitch = pitch; 00250 return true; 00251 } 00252 00253 bool SubController::setDepth(int depth) 00254 { 00255 itsDesiredDepth = depth; 00256 return true; 00257 } 00258 00259 00260 // ###################################################################### 00261 bool SubController::setRoll(int roll) 00262 { 00263 itsDesiredRoll = roll; 00264 return true; 00265 } 00266 00267 bool SubController::setSpeed(int speed) 00268 { 00269 itsDesiredSpeed = speed; 00270 itsCurrentSpeed = itsDesiredSpeed; 00271 return true; 00272 } 00273 00274 bool SubController::setTurningSpeed(int speed) 00275 { 00276 itsDesiredTurningSpeed = speed; 00277 return true; 00278 } 00279 00280 00281 // ###################################################################### 00282 00283 void SubController::updateHeading(unsigned int heading) 00284 { 00285 itsCurrentHeading = heading; 00286 } 00287 00288 void SubController::updatePitch(int pitch) 00289 { 00290 itsCurrentPitch = pitch; 00291 } 00292 00293 void SubController::updateRoll(int roll) 00294 { 00295 itsCurrentRoll = roll; 00296 } 00297 00298 void SubController::updateDepth(unsigned int depth) 00299 { 00300 00301 itsAvgDepth.push_back(depth); 00302 00303 if (itsAvgDepth.size() > 40) 00304 { 00305 00306 long avg = 0; 00307 for(std::list<int>::iterator itr=itsAvgDepth.begin(); itr != itsAvgDepth.end(); ++itr) 00308 avg += *itr; 00309 itsAvgDepth.pop_front(); 00310 00311 itsCurrentDepth = avg/itsAvgDepth.size(); 00312 } 00313 } 00314 00315 void SubController::updatePID() 00316 { 00317 00318 if (itsSimulation.getVal()) 00319 itsBeeStemSim->getSensors(itsCurrentHeading, itsCurrentPitch, itsCurrentRoll, itsCurrentDepth, itsCurrentIntPressure); 00320 else 00321 itsBeeStemTiny->getSensors(itsCurrentHeading, itsCurrentPitch, itsCurrentRoll, itsCurrentDepth, itsCurrentIntPressure); 00322 00323 if(guiOn.getVal()) 00324 { 00325 genPIDImage(); 00326 genSubImage(); 00327 } 00328 00329 00330 if (pidOn.getVal()) 00331 { 00332 00333 int desiredHeading; 00334 00335 if(itsCurrentHeading >= 180) { 00336 desiredHeading = itsDesiredHeading + 360 - itsCurrentHeading; 00337 } 00338 else { 00339 desiredHeading = itsDesiredHeading - itsCurrentHeading; 00340 } 00341 00342 while(desiredHeading > 360) 00343 desiredHeading -= 360; 00344 while(desiredHeading < 0) 00345 desiredHeading += 360; 00346 00347 if(desiredHeading >180) 00348 desiredHeading = -(360 - desiredHeading); 00349 00350 float headingCorrection = (float)itsHeadingPID.update(desiredHeading, 0); 00351 float pitchCorrection = itsPitchPID.update((float)itsDesiredPitch, (float)itsCurrentPitch); 00352 //float rollCorrection = itsRollPID.update(itsDesiredRoll, (float)itsCurrentRoll); 00353 float depthCorrection = itsDepthPID.update((float)itsDesiredDepth, (float)itsCurrentDepth); 00354 00355 if (depthCorrection > 75) depthCorrection = 75; 00356 if (depthCorrection < -75) depthCorrection = -75; 00357 00358 // LINFO("Heading | Desired: %d, Current %d, Correction %f", normDes, normHead, headingCorrection); 00359 00360 int polCorr = 1; 00361 00362 if (!itsSimulation.getVal()) 00363 { 00364 polCorr = -1; 00365 } 00366 00367 int thruster_Fwd_Left; 00368 int thruster_Fwd_Right; 00369 if(itsDesiredTurningSpeed != 0) 00370 { 00371 thruster_Fwd_Left = polCorr*(THRUSTER_FWD_LEFT_THRESH - (int)(itsDesiredTurningSpeed) - itsCurrentSpeed); 00372 thruster_Fwd_Right = THRUSTER_FWD_RIGHT_THRESH + (int)(itsDesiredTurningSpeed) - itsCurrentSpeed; 00373 } 00374 else 00375 { 00376 thruster_Fwd_Left = polCorr*(THRUSTER_FWD_LEFT_THRESH - (int)(headingCorrection) - itsCurrentSpeed); 00377 thruster_Fwd_Right = THRUSTER_FWD_RIGHT_THRESH + (int)(headingCorrection) - itsCurrentSpeed; 00378 } 00379 00380 itsCurrentThruster_Fwd_Left = (int)(thruster_Fwd_Left * itsSpeedScale); 00381 itsCurrentThruster_Fwd_Right = (int)(thruster_Fwd_Right * itsSpeedScale); 00382 00383 if (itsDesiredDepth != -1) //hack to set the depth manually 00384 { 00385 int thruster_Up_Left = -1*(THRUSTER_UP_LEFT_THRESH + (int)((depthCorrection/itsDepthRatio) + pitchCorrection)); 00386 int thruster_Up_Right = THRUSTER_UP_RIGHT_THRESH + (int)((depthCorrection/itsDepthRatio) + pitchCorrection); 00387 int thruster_Up_Back = THRUSTER_UP_BACK_THRESH + (int)(depthCorrection - pitchCorrection); 00388 00389 itsCurrentThruster_Up_Left = (int)(thruster_Up_Left * itsSpeedScale); 00390 itsCurrentThruster_Up_Right = (int)(thruster_Up_Right * itsSpeedScale); 00391 itsCurrentThruster_Up_Back = (int)(thruster_Up_Back * itsSpeedScale); 00392 00393 // itsCurrentThruster_Up_Back = 0; 00394 // itsCurrentThruster_Up_Left = 0; 00395 // itsCurrentThruster_Up_Right = 0; 00396 } 00397 } 00398 00399 00400 00401 if (!motorsOn.getVal()) 00402 { 00403 itsCurrentThruster_Up_Left = 0; 00404 itsCurrentThruster_Fwd_Left = 0; 00405 itsCurrentThruster_Up_Back = 0; 00406 itsCurrentThruster_Fwd_Right = 0; 00407 itsCurrentThruster_Up_Right = 0; 00408 } 00409 00410 if (itsSimulation.getVal()) 00411 itsBeeStemSim->setThrusters( 00412 itsCurrentThruster_Up_Left, 00413 itsCurrentThruster_Fwd_Left, 00414 itsCurrentThruster_Up_Back, 00415 itsCurrentThruster_Fwd_Right, 00416 itsCurrentThruster_Up_Right); 00417 else 00418 itsBeeStemTiny->setThrusters( 00419 itsCurrentThruster_Up_Left, 00420 itsCurrentThruster_Fwd_Left, 00421 itsCurrentThruster_Up_Back, 00422 itsCurrentThruster_Fwd_Right, 00423 itsCurrentThruster_Up_Right); 00424 00425 00426 00427 } 00428 00429 void SubController::setThruster(int thruster, int val) 00430 { 00431 //LINFO("Set Thruster %i %i", thruster, val); 00432 switch(thruster) 00433 { 00434 case THRUSTER_UP_LEFT: itsCurrentThruster_Up_Left = val; break; 00435 case THRUSTER_UP_RIGHT: itsCurrentThruster_Up_Right = val; break; 00436 case THRUSTER_UP_BACK: itsCurrentThruster_Up_Back = val; break; 00437 case THRUSTER_FWD_RIGHT: itsCurrentThruster_Fwd_Right = val; break; 00438 case THRUSTER_FWD_LEFT: itsCurrentThruster_Fwd_Left = val; break; 00439 default: LINFO("Invalid motor %i", thruster); break; 00440 } 00441 00442 } 00443 00444 void SubController::setIntPressure(unsigned int pressure) 00445 { 00446 itsCurrentIntPressure = pressure; 00447 } 00448 00449 00450 void SubController::killMotors() 00451 { 00452 //itsBeeStem->setThrusters(0, 0, 0, 0, 0); 00453 } 00454 00455 00456 void SubController::paramChanged(ModelParamBase* const param, const bool valueChanged, ParamClient::ChangeStatus* status) 00457 { 00458 00459 //////// Pitch PID constants/gain change //////// 00460 if (param == &pitchP && valueChanged) 00461 itsPitchPID.setPIDPgain(pitchP.getVal()); 00462 else if(param == &pitchI && valueChanged) 00463 itsPitchPID.setPIDIgain(pitchI.getVal()); 00464 else if(param == &pitchD && valueChanged) 00465 itsPitchPID.setPIDDgain(pitchD.getVal()); 00466 00467 //////// Roll PID constants/gain change /////// 00468 else if(param == &rollP && valueChanged) 00469 itsRollPID.setPIDPgain(rollP.getVal()); 00470 else if(param == &rollI && valueChanged) 00471 itsRollPID.setPIDIgain(rollI.getVal()); 00472 else if(param == &rollD && valueChanged) 00473 itsRollPID.setPIDDgain(rollD.getVal()); 00474 00475 //////// Heading PID constants/gain change //// 00476 else if(param == &headingP && valueChanged) 00477 itsHeadingPID.setPIDPgain(headingP.getVal()); 00478 else if(param == &headingI && valueChanged) 00479 itsHeadingPID.setPIDIgain(headingI.getVal()); 00480 else if(param == &headingD && valueChanged) 00481 itsHeadingPID.setPIDDgain(headingD.getVal()); 00482 00483 /////// Depth PID constants/gain change //// 00484 else if(param == &depthP && valueChanged) 00485 itsDepthPID.setPIDPgain(depthP.getVal()); 00486 else if(param == &depthI && valueChanged) 00487 itsDepthPID.setPIDIgain(depthI.getVal()); 00488 else if(param == &depthD && valueChanged) 00489 itsDepthPID.setPIDDgain(depthD.getVal()); 00490 else if(param == &setDepthValue && valueChanged) 00491 setDepth(setDepthValue.getVal()); 00492 else if(param == &setPitchValue && valueChanged) 00493 setPitch(setPitchValue.getVal()); 00494 else if(param == &setRollValue && valueChanged) 00495 setRoll(setRollValue.getVal()); 00496 else if(param == &setHeadingValue && valueChanged) 00497 setHeading(setHeadingValue.getVal()); 00498 00499 //Thruster_Settings 00500 else if(param == &setCurrentThruster_Up_Left && valueChanged) 00501 setThruster(THRUSTER_UP_LEFT, setCurrentThruster_Up_Left.getVal()); 00502 else if(param == &setCurrentThruster_Up_Right && valueChanged) 00503 setThruster(THRUSTER_UP_RIGHT, setCurrentThruster_Up_Right.getVal()); 00504 else if(param == &setCurrentThruster_Up_Back && valueChanged) 00505 setThruster(THRUSTER_UP_BACK, setCurrentThruster_Up_Back.getVal()); 00506 else if(param == &setCurrentThruster_Fwd_Left && valueChanged) 00507 setThruster(THRUSTER_FWD_LEFT, setCurrentThruster_Fwd_Left.getVal()); 00508 else if(param == &setCurrentThruster_Fwd_Right && valueChanged) 00509 setThruster(THRUSTER_FWD_RIGHT, setCurrentThruster_Fwd_Right.getVal()); 00510 00511 else if(param == &speedScale && valueChanged) 00512 itsSpeedScale = speedScale.getVal(); 00513 else if(param == &depthRatio && valueChanged) 00514 itsDepthRatio = depthRatio.getVal(); 00515 00516 00517 } 00518 00519 ////////////////// GUI Related //////////////////////////////////// 00520 00521 void SubController::genPIDImage() 00522 { 00523 static int x = 0; 00524 00525 int depthErr, pitchErr, headingErr, rollErr; 00526 00527 depthErr = (itsDesiredDepth - itsCurrentDepth); 00528 pitchErr = (itsDesiredPitch - itsCurrentPitch); 00529 headingErr = (itsDesiredHeading - itsCurrentHeading); 00530 rollErr = (itsDesiredRoll - itsCurrentRoll); 00531 00532 while (headingErr <= -180) headingErr += 360; 00533 while (headingErr > 180) headingErr -= 360; 00534 00535 00536 00537 int depth_y = (256/2) + (depthErr*2); 00538 if (depth_y > 255) depth_y = 255; 00539 if (depth_y < 0) depth_y = 0; 00540 00541 int pitch_y = (256/2) + (pitchErr*2); 00542 if (pitch_y > 255) pitch_y = 255; 00543 if (pitch_y < 0) pitch_y = 0; 00544 00545 int heading_y = (256/2) + (headingErr*2); 00546 if (heading_y > 255) heading_y = 255; 00547 if (heading_y < 0) heading_y = 0; 00548 00549 int roll_y = (256/2) + (rollErr*2); 00550 if (roll_y > 255) roll_y = 255; 00551 if (roll_y < 0) roll_y = 0; 00552 00553 00554 if (!x) 00555 { 00556 itsPIDImage.clear(); 00557 drawLine(itsPIDImage, Point2D<int>(0, 256/2), Point2D<int>(256, 256/2), PixRGB<byte>(255,0,0)); 00558 } 00559 if(depthPIDDisplay.getVal()) itsPIDImage.setVal(x,depth_y,PixRGB<byte>(0,255,0)); 00560 if(pitchPIDDisplay.getVal()) itsPIDImage.setVal(x,pitch_y,PixRGB<byte>(255,0,0)); 00561 if(headingPIDDisplay.getVal()) itsPIDImage.setVal(x,heading_y,PixRGB<byte>(0,0,255)); 00562 if(rollPIDDisplay.getVal()) itsPIDImage.setVal(x,roll_y,PixRGB<byte>(255,255,0)); 00563 00564 x = (x+1)%256; 00565 00566 } 00567 00568 void SubController::genSubImage() 00569 { 00570 itsSubImage.clear(); 00571 drawCircle(itsSubImage, Point2D<int>(128,128), 100, PixRGB<byte>(255,0,0)); 00572 int x = (int)(100.0*cos((itsCurrentHeading-90)*(M_PI/180))); //shift by 90 so that 0 is up 00573 int y = (int)(100.0*sin((itsCurrentHeading-90)*(M_PI/180))); 00574 drawArrow(itsSubImage, Point2D<int>(128,128), Point2D<int>(128+x,128+y), PixRGB<byte>(0,255,0)); 00575 00576 int dx = (int)(100.0*cos((itsDesiredHeading-90)*(M_PI/180))); //shift by 90 so that 0 is up 00577 int dy = (int)(100.0*sin((itsDesiredHeading-90)*(M_PI/180))); 00578 drawArrow(itsSubImage, Point2D<int>(128,128), Point2D<int>(128+dx,128+dy), PixRGB<byte>(0,0,255)); 00579 00580 } 00581 00582 const Image<PixRGB<byte> > SubController::getImage(int camera) 00583 { 00584 00585 if (itsSimulation.getVal()) 00586 { 00587 return itsBeeStemSim->getImage(camera); 00588 } 00589 else 00590 { 00591 GenericFrame inputFrame; 00592 Image<PixRGB<byte> > img; 00593 00594 switch(camera) 00595 { 00596 case 1: 00597 inputFrame = itsBottomCam->readFrame(); 00598 if(!inputFrame.initialized()) return Image<PixRGB<byte> >(); 00599 00600 img = inputFrame.asRgb(); 00601 break; 00602 00603 case 2: 00604 inputFrame = itsForwardCam->readFrame(); 00605 if(!inputFrame.initialized()) return Image<PixRGB<byte> >(); 00606 00607 img = inputFrame.asRgb(); 00608 break; 00609 00610 default: 00611 return Image<PixRGB<byte> >(); 00612 } 00613 00614 img = rescale(img, 320, 240); 00615 00616 return img; 00617 } 00618 00619 return Image<PixRGB<byte> >(); 00620 00621 } 00622 00623 const Dims SubController::peekDims() 00624 { 00625 return Dims(320,240); 00626 } 00627 00628 bool SubController::isSimMode() 00629 { 00630 return itsSimulation.getVal(); 00631 } 00632 00633 int SubController::getHeadingErr() 00634 { 00635 return abs(itsDesiredHeading - itsCurrentHeading); 00636 } 00637 00638 int SubController::getDepthErr() 00639 { 00640 return abs(itsDesiredDepth - itsCurrentDepth); 00641 } 00642 00643 // ###################################################################### 00644 /* So things look consistent in everyone's emacs... */ 00645 /* Local Variables: */ 00646 /* indent-tabs-mode: nil */ 00647 /* End: */