00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "Robots/SeaBeeIII/SeaBee3Simulator.H"
00036 #include "Component/OptionManager.H"
00037 #include "Util/MathFunctions.H"
00038 #include "Util/Assert.H"
00039 #include "rutz/compat_snprintf.h"
00040 #include "Image/MatrixOps.H"
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <signal.h>
00044
00045
00046 namespace {
00047
00048 void nearCallback (void *data, dGeomID o1, dGeomID o2){
00049 SeaBee3Simulator *subSim = (SeaBee3Simulator *)data;
00050 const int MaxContacts = 10;
00051
00052
00053 dContact contact[MaxContacts];
00054 int nContacts = dCollide (o1,o2,MaxContacts,
00055 &contact[0].geom,sizeof(dContact));
00056 for (int i=0; i<nContacts; i++) {
00057 contact[i].surface.mode = dContactSoftCFM ;
00058 contact[i].surface.mu = 0.5;
00059 contact[i].surface.mu2 = 0.5;
00060 contact[i].surface.bounce = 0.01;
00061 contact[i].surface.bounce_vel = 0.01;
00062 contact[i].surface.soft_cfm = 0.001;
00063
00064 dJointID c = dJointCreateContact (subSim->getWorld(),
00065 subSim->getContactgroup(),&contact[i]);
00066 dJointAttach (c,
00067 dGeomGetBody(contact[i].geom.g1),
00068 dGeomGetBody(contact[i].geom.g2));
00069 }
00070 }
00071 }
00072
00073
00074 SeaBee3Simulator::SeaBee3Simulator(OptionManager& mgr, const std::string& descrName,
00075 const std::string& tagName) :
00076 RobotBrainComponent(mgr, descrName, tagName),
00077 itsPoolDepth(4.5),
00078 itsPoolLength(70),
00079 itsPoolWidth(20),
00080 itsWaterLevel(4.57),
00081 itsSubLength(1.5),
00082 itsSubRadius(0.2),
00083 itsSubWeight(20),
00084 vp(new ViewPort("SeaBee3Simulator", "sea_floor.ppm", "sky.ppm", true, true)),
00085 itsWorldView(true),
00086 itsShowWorld(true),
00087 itsWorldDisp(NULL),
00088 itsCameraUpdateTime(.0333333),
00089 itsBeeStemUpdateTime(.1),
00090 itsSimXPos(0),
00091 itsSimYPos(0),
00092 itsSimDepth(0),
00093 itsSimRoll(0),
00094 itsSimPitch(0),
00095 itsSimYaw(0),
00096 itsPIDsEnabled(false),
00097 itsDepthPID(new PID<float>(0,0,0,0,100)),
00098 itsHeadingPID(new PID<Angle>(0,0,0,0,100))
00099 {
00100 dInitODE();
00101
00102 Initialized = false;
00103
00104
00105
00106 itsWorldDisp = new XWinManaged(vp->getDims(), -1, -1, "World View");
00107
00108 pthread_mutex_init(&itsDispLock, NULL);
00109
00110 world = dWorldCreate();
00111 space = dHashSpaceCreate(0);
00112 contactgroup = dJointGroupCreate(0);
00113 ground = dCreatePlane(space, 0, 0, 1, 0);
00114
00115
00116 dWorldSetGravity(world,0,0,-9.81);
00117
00118 dWorldSetCFM (world,1e-6);
00119 dWorldSetERP (world,1);
00120
00121 dWorldSetContactMaxCorrectingVel (world,0.1);
00122
00123 dWorldSetContactSurfaceLayer(world, 0.001);
00124
00125 makeSub();
00126
00127
00128 double xyz[3] = {0 , -3.0, 15};
00129 double hpr[3] = {90.0,-45,0.0};
00130 vp->dsSetViewpoint (xyz,hpr);
00131
00132 arenaWallTexture = new Texture("etc/textures/sea_floor.ppm");
00133 waterSurfaceTexture = new Texture("etc/textures/water.ppm");
00134
00135 itsJSValues.resize(8);
00136 itsButValues.resize(20);
00137
00138
00139 itsJSValues[4] = -100;
00140 itsJSValues[5] = -100;
00141 }
00142
00143 SeaBee3Simulator::~SeaBee3Simulator()
00144 {
00145 dSpaceDestroy(space);
00146 dWorldDestroy(world);
00147
00148 delete vp;
00149 delete itsWorldDisp;
00150 pthread_mutex_destroy(&itsDispLock);
00151 }
00152
00153 void SeaBee3Simulator::registerTopics()
00154 {
00155 registerPublisher("RetinaMessageTopic");
00156 registerPublisher("BeeStemMessageTopic");
00157 registerSubscription("XBox360RemoteControlMessageTopic");
00158 registerSubscription("BeeStemConfigTopic");
00159
00160 }
00161
00162 void SeaBee3Simulator::makeSub()
00163 {
00164 dMass mass;
00165 itsSubBody = dBodyCreate(world);
00166
00167
00168
00169
00170
00171 dBodySetPosition(itsSubBody,10,5,itsPoolDepth-.1);
00172
00173
00174 dMatrix3 R;
00175 dRFromAxisAndAngle (R,1,0,0,-M_PI/2);
00176 dBodySetRotation(itsSubBody, R);
00177
00178
00179 dMassSetZero(&mass);
00180 dMassSetCappedCylinderTotal(&mass,itsSubWeight,3,itsSubRadius,itsSubLength);
00181 dMassRotate(&mass, R);
00182 dBodySetMass(itsSubBody,&mass);
00183 itsSubGeom = dCreateCCylinder(space, itsSubRadius, itsSubLength);
00184 dGeomSetRotation(itsSubGeom, R);
00185 dGeomSetBody(itsSubGeom, itsSubBody);
00186 }
00187
00188 void SeaBee3Simulator::drawSub()
00189 {
00190 dReal r, length;
00191
00192 dGeomCCylinderGetParams(itsSubGeom,&r,&length);
00193
00194 vp->dsSetColor(1,1,0);
00195 vp->dsDrawCappedCylinder(
00196 dBodyGetPosition(itsSubBody),
00197 dBodyGetRotation(itsSubBody),
00198 length,
00199 r);
00200 }
00201
00202 void SeaBee3Simulator::drawArena()
00203 {
00204 double pos[3];
00205
00206 drawWaterSurface();
00207 drawPool();
00208
00209 pos[0] = 10; pos[1] = 10; pos[2] = 2.80;
00210 drawGate(pos);
00211
00212 pos[0] = 11; pos[1] = 17; pos[2] = 1.83;
00213 drawBuoy(pos);
00214
00215 pos[0] = 10; pos[1] = 20; pos[2] = 0.6;
00216 drawPipeline(M_PI/2.0, pos);
00217
00218 pos[0] = 10; pos[1] = 25; pos[2] = 0.6;
00219 drawBin(0, pos);
00220
00221 pos[0] = 10; pos[1] = 27; pos[2] = 0.6;
00222 drawPipeline(M_PI/4.0, pos);
00223
00224 pos[0] = 12; pos[1] = 29; pos[2] = 0.6;
00225 drawPipeline(M_PI/2.0, pos);
00226
00227 pos[0] = 12; pos[1] = 32; pos[2] = 0.6;
00228 drawPipeline(-M_PI/4, pos);
00229
00230 pos[0] = 8; pos[1] = 37; pos[2] = 0.6;
00231 drawBin(M_PI/2, pos);
00232
00233 pos[0] = 8; pos[1] = 37; pos[2] = 1.83;
00234 drawBuoy(pos);
00235
00236
00237
00238
00239
00240
00241 }
00242
00243
00244 void SeaBee3Simulator::drawGate(const double *gatePos)
00245 {
00246 double gateHeight = 3.0;
00247
00248 double pos[3];
00249 double R[12];
00250
00251
00252 vp->dsSetColor(0,0,0);
00253
00254
00255 pos[0] = gatePos[0]; pos[1] = gatePos[1]; pos[2] = gatePos[2];
00256 dRFromAxisAndAngle (R,0,1,0,-M_PI/2);
00257 vp->dsDrawCappedCylinder(pos, R, 3.05f, 0.1f);
00258
00259
00260 dRSetIdentity(R);
00261 pos[0] = gatePos[0]-(3.05/2); pos[1] = gatePos[1]; pos[2] = gatePos[2] - gateHeight/2;
00262 vp->dsDrawCappedCylinder(pos, R, gateHeight, 0.1);
00263
00264 pos[0] = gatePos[0]+(3.05/2); pos[1] = gatePos[1]; pos[2] = gatePos[2] - gateHeight/2;
00265 vp->dsDrawCappedCylinder(pos, R, gateHeight, 0.1);
00266 }
00267
00268
00269 void SeaBee3Simulator::drawBuoy(const double *bouyPos)
00270 {
00271 static int frame = 0;
00272 static bool bouyOn = false;
00273 double pos[3];
00274 double R[12];
00275
00276
00277
00278 if (frame++ > 5)
00279 {
00280 bouyOn = !bouyOn;
00281 frame = 0;
00282 }
00283
00284 if (bouyOn)
00285 vp->dsSetColor(1,0,0);
00286 else
00287 vp->dsSetColor(0.5,0,0);
00288 pos[0] = bouyPos[0]; pos[1] = bouyPos[1]; pos[2] = bouyPos[2];
00289 dRSetIdentity(R);
00290 vp->dsDrawSphere(pos, R, 0.20);
00291 double pos1[3];
00292 vp->dsSetColor(0,0,0);
00293 pos1[0] = pos[0]; pos1[1] = pos[1]; pos1[2] = 0;
00294 vp->dsDrawLine(pos, pos1);
00295 }
00296
00297 void SeaBee3Simulator::drawWaterSurface()
00298 {
00299
00300 static double texOff=0.0f;
00301 texOff += 0.1f;
00302
00303
00304 glEnable (GL_TEXTURE_2D);
00305
00306 glBindTexture(GL_TEXTURE_2D, waterSurfaceTexture->getName());
00307
00308
00309 glBegin(GL_QUADS);
00310 {
00311 glNormal3f(0,0,-1);
00312 glTexCoord2f(0.0f, 0.0f+texOff); glVertex3f( -5.0f, -5.0f, itsPoolDepth);
00313 glTexCoord2f(1.0f, 0.0f+texOff); glVertex3f( itsPoolWidth+5.0f, -5.0f, itsPoolDepth);
00314 glTexCoord2f(1.0f, 1.0f+texOff); glVertex3f( itsPoolWidth+5.0f, itsPoolLength+5.0f, itsPoolDepth);
00315 glTexCoord2f(0.0f, 1.0f+texOff); glVertex3f( -5.0f, itsPoolLength+5.0f, itsPoolDepth);
00316
00317
00318 glNormal3f(0,0,1);
00319 glTexCoord2f(0.0f, 0.0f+texOff); glVertex3f( -5.0f, -5.0f, itsPoolDepth);
00320 glTexCoord2f(0.0f, 1.0f+texOff); glVertex3f( -5.0f, itsPoolLength+5.0f, itsPoolDepth);
00321 glTexCoord2f(1.0f, 1.0f+texOff); glVertex3f( itsPoolWidth+5.0f, itsPoolLength+5.0f, itsPoolDepth);
00322 glTexCoord2f(1.0f, 0.0f+texOff); glVertex3f( itsPoolWidth+5.0f, -5.0f, itsPoolDepth);
00323 }
00324 glEnd();
00325
00326 if(texOff > 1.0f) texOff = 0.0f;
00327 }
00328 void SeaBee3Simulator::drawPool()
00329 {
00330 double pos[3];
00331 double R[12];
00332 double sides[3];
00333
00334 double WallAngle = M_PI/8;
00335
00336 double WallHeight = itsPoolDepth / cos(WallAngle);
00337
00338
00339 pos[0] = itsPoolWidth/2.0; pos[1] = itsPoolLength; pos[2] = itsPoolDepth/2;
00340 dRFromAxisAndAngle(R, 1,0,0,-WallAngle);
00341 sides[0] = itsPoolWidth*1.5; sides[1] = 0.5; sides[2] = WallHeight;
00342 vp->dsSetTexture(ViewPort::OTHER,arenaWallTexture);
00343 vp->dsDrawBox(pos, R, sides);
00344
00345
00346 pos[0] = itsPoolWidth/2.0; pos[1] = 0; pos[2] = itsPoolDepth/2;
00347 dRFromAxisAndAngle(R, 1,0,0,WallAngle);
00348 sides[0] = itsPoolWidth*1.5; sides[1] = 0.5; sides[2] = WallHeight;
00349 vp->dsSetTexture(ViewPort::OTHER,arenaWallTexture);
00350 vp->dsDrawBox(pos, R, sides);
00351
00352
00353 pos[0] = itsPoolWidth; pos[1] = itsPoolLength/2.0; pos[2] = itsPoolDepth/2;
00354 dRFromAxisAndAngle(R, 0,1,0,WallAngle);
00355 sides[0] = 0.5; sides[1] = itsPoolLength*1.5; sides[2] = WallHeight;
00356 vp->dsSetTexture(ViewPort::OTHER,arenaWallTexture);
00357 vp->dsDrawBox(pos, R, sides);
00358
00359
00360 pos[0] = 0; pos[1] = itsPoolLength/2.0; pos[2] = itsPoolDepth/2;
00361 dRFromAxisAndAngle(R, 0,1,0,-WallAngle);
00362 sides[0] = 0.5; sides[1] = itsPoolLength*1.5; sides[2] = WallHeight;
00363 vp->dsSetTexture(ViewPort::OTHER,arenaWallTexture);
00364 vp->dsDrawBox(pos, R, sides);
00365 }
00366
00367 void SeaBee3Simulator::drawPipeline(const double ori, const double *pipePos)
00368 {
00369
00370 double sides[3] = {1.2, 0.15, 0.1};
00371 double R[12];
00372
00373 dRFromAxisAndAngle (R,0,0,1,ori);
00374
00375 vp->dsSetColor(1,0.5,0);
00376
00377 vp->dsDrawBox(pipePos, R, sides);
00378 }
00379
00380 void SeaBee3Simulator::drawBin(const double ori, const double *binPos)
00381 {
00382
00383 double sides[3];
00384 double R[12];
00385
00386 dRFromAxisAndAngle (R,0,0,1,ori);
00387
00388 vp->dsSetColor(1,1,1);
00389 sides[0] = 0.6; sides[1] = 0.8; sides[2] = 0.1;
00390 vp->dsDrawBox(binPos, R, sides);
00391
00392 vp->dsSetColor(0,0,0);
00393 sides[0] = 0.3; sides[1] = 0.6; sides[2] = 0.15;
00394 vp->dsDrawBox(binPos, R, sides);
00395 }
00396
00397 void SeaBee3Simulator::drawPinger(const double *pingerPos)
00398 {
00399 double pos[3];
00400 double R[12];
00401
00402 vp->dsSetColor(1,1,1);
00403 pos[0] = pingerPos[0]; pos[1] = pingerPos[1]; pos[1] = pingerPos[2] + 1.2/2;
00404 vp->dsDrawCappedCylinder(pos, R, 1.2, 0.1);
00405
00406 }
00407
00408
00409 void SeaBee3Simulator::handleWinEvents(XEvent& event)
00410 {}
00411
00412 void SeaBee3Simulator::updateSensors(const dReal *pos, const dReal *R)
00413 {
00414 itsSimXPos = pos[0];
00415 itsSimYPos = pos[1];
00416 itsSimDepth = 2000 - pos[2] * 100 + randomDoubleFromNormal(3.0);
00417 itsSimRoll = atan2(R[9], R[10]) + M_PI/2+ randomDoubleFromNormal(5.0);
00418 itsSimPitch = asin(-R[8]) + randomDoubleFromNormal(5.0);
00419 itsSimYaw = atan2(R[4], R[0]) * 180.0/M_PI + randomDoubleFromNormal(2.0);
00420
00421 if (itsSimYaw < 0) itsSimYaw += 360;
00422
00423
00424 if(itsCameraTimer.getSecs() > itsCameraUpdateTime)
00425 {
00426
00427 Image<PixRGB<byte> > fwdCameraImage = flipVertic(getFrame(1));
00428
00429 RobotSimEvents::RetinaMessagePtr fwdRetMsg = new RobotSimEvents::RetinaMessage;
00430 fwdRetMsg->img = Image2Ice(fwdCameraImage);
00431 fwdRetMsg->cameraID = "DwnCamera";
00432
00433 this->publish("RetinaMessageTopic", fwdRetMsg);
00434
00435
00436 Image<PixRGB<byte> > dwnCameraImage = flipVertic(getFrame(2));
00437
00438 RobotSimEvents::RetinaMessagePtr dwnRetMsg = new RobotSimEvents::RetinaMessage;
00439 dwnRetMsg->img = Image2Ice(dwnCameraImage);
00440 dwnRetMsg->cameraID = "FwdCamera";
00441
00442 this->publish("RetinaMessageTopic", dwnRetMsg);
00443
00444 itsCameraTimer.reset();
00445 }
00446
00447 if(itsBeeStemTimer.getSecs() > itsBeeStemUpdateTime)
00448 {
00449
00450 RobotSimEvents::BeeStemMessagePtr BeeStemMsg = new RobotSimEvents::BeeStemMessage;
00451 BeeStemMsg->accelX = 0;
00452 BeeStemMsg->accelY = 0;
00453 BeeStemMsg->accelZ = 0;
00454 BeeStemMsg->compassHeading = itsSimYaw;
00455 BeeStemMsg->compassPitch = itsSimRoll;
00456 BeeStemMsg->compassRoll = itsSimPitch;
00457 BeeStemMsg->internalPressure = 3000 + randomDoubleFromNormal(3.0);
00458 BeeStemMsg->externalPressure = itsSimDepth;
00459 BeeStemMsg->desiredHeading = itsDesiredHeading;
00460 BeeStemMsg->desiredDepth = itsDesiredDepth;
00461 BeeStemMsg->desiredSpeed = itsDesiredSpeed;
00462 BeeStemMsg->headingK = itsHeadingK;
00463 BeeStemMsg->headingP = itsHeadingP;
00464 BeeStemMsg->headingD = itsHeadingD;
00465 BeeStemMsg->headingI = itsHeadingI;
00466 BeeStemMsg->headingOutput = itsHeadingOutput;
00467 BeeStemMsg->depthK = itsDepthK;
00468 BeeStemMsg->depthP = itsDepthP;
00469 BeeStemMsg->depthD = itsDepthD;
00470 BeeStemMsg->depthI = itsDepthI;
00471 BeeStemMsg->depthOutput = itsDepthOutput;
00472 BeeStemMsg->killSwitch = 1;
00473 BeeStemMsg->thruster1 = itsForwardLeftThrusterVal;
00474 BeeStemMsg->thruster2 = itsForwardRightThrusterVal;
00475 BeeStemMsg->thruster3 = itsFrontStrafeThrusterVal;
00476 BeeStemMsg->thruster4 = itsBackStrafeThrusterVal;
00477 BeeStemMsg->thruster5 = itsLeftVertThrusterVal;
00478 BeeStemMsg->thruster6 = itsRightVertThrusterVal;
00479
00480 this->publish("BeeStemMessageTopic", BeeStemMsg);
00481 itsBeeStemTimer.reset();
00482 }
00483 }
00484
00485
00486 void SeaBee3Simulator::evolve() {usleep(10000000);}
00487
00488
00489 void SeaBee3Simulator::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg,
00490 const Ice::Current&)
00491 {
00492
00493 if(eMsg->ice_isA("::RobotSimEvents::JoyStickControlMessage"))
00494 {
00495 RobotSimEvents::JoyStickControlMessagePtr msg = RobotSimEvents::JoyStickControlMessagePtr::dynamicCast(eMsg);
00496
00497 itsJSMutex.lock();
00498 if(msg->axis >= 0)
00499 itsJSValues[msg->axis] = msg->axisVal;
00500 if(msg->button >= 0)
00501 itsButValues[msg->button] = msg->butVal;
00502 itsJSMutex.unlock();
00503 }
00504
00505 else if(eMsg->ice_isA("::RobotSimEvents::BeeStemConfigMessage"))
00506 {
00507 RobotSimEvents::BeeStemConfigMessagePtr msg = RobotSimEvents::BeeStemConfigMessagePtr::dynamicCast(eMsg);
00508
00509
00510 if(msg->enablePID == 1)
00511 {
00512
00513 itsStemMutex.lock();
00514 {
00515 if(msg->enableVal == 1)
00516 itsPIDsEnabled = true;
00517 else
00518 itsPIDsEnabled = false;
00519
00520 LINFO("PIDEnable=%d", itsPIDsEnabled);
00521 }
00522 itsStemMutex.unlock();
00523
00524 }
00525 else if(msg->updateHeadingPID == 0 && msg->updateDepthPID == 0)
00526 {
00527
00528 itsStemMutex.lock();
00529 {
00530 LINFO("Update Pose: %d\n",msg->updateDesiredValue);
00531 if(msg->updateDesiredValue == 1)
00532 itsTargetHeading = msg->desiredHeading;
00533 else if(msg->updateDesiredValue == 2)
00534 itsTargetDepth = msg->desiredDepth;
00535 else if(msg->updateDesiredValue == 3)
00536 itsTargetSpeed = msg->desiredSpeed;
00537 }
00538 itsStemMutex.unlock();
00539
00540 }
00541 else if(msg->updateDepthPID == 1)
00542 {
00543
00544 itsStemMutex.lock();
00545 {
00546 itsDepthPID->setPIDPgain(float(msg->depthP) / float(msg->depthK));
00547 itsDepthPID->setPIDIgain(float(msg->depthI) / float(msg->depthK));
00548 itsDepthPID->setPIDDgain(float(msg->depthD) / float(msg->depthK));
00549 }
00550 itsStemMutex.unlock();
00551
00552 }
00553 else if(msg->updateHeadingPID == 1)
00554 {
00555
00556 itsStemMutex.lock();
00557 {
00558 itsHeadingPID->setPIDPgain(float(msg->headingP) / float(msg->headingK));
00559 itsHeadingPID->setPIDIgain(float(msg->headingI) / float(msg->headingK));
00560 itsHeadingPID->setPIDDgain(float(msg->headingD) / float(msg->headingK));
00561 }
00562 itsStemMutex.unlock();
00563
00564 }
00565 }
00566 }
00567
00568 void SeaBee3Simulator::simLoop()
00569 {
00570
00571 dBodyAddRelForceAtRelPos(itsSubBody,
00572 0,0, itsForwardLeftThrusterVal/10.0,
00573 -.25, 0, 0);
00574
00575 dBodyAddRelForceAtRelPos(itsSubBody,
00576 0,0, itsForwardRightThrusterVal/10.0,
00577 +.25, 0, 0);
00578
00579 dBodyAddRelForceAtRelPos(itsSubBody,
00580 itsFrontStrafeThrusterVal/10.0, 0,0,
00581 0, 0, +.5);
00582
00583 dBodyAddRelForceAtRelPos(itsSubBody,
00584 itsBackStrafeThrusterVal/10.0, 0,0,
00585 0, 0, -.5);
00586
00587 dBodyAddRelForceAtRelPos(itsSubBody,
00588 0, itsLeftVertThrusterVal/10.0, 0,
00589 -.25, 0, 0);
00590
00591 dBodyAddRelForceAtRelPos(itsSubBody,
00592 0, itsRightVertThrusterVal/10.0, 0,
00593 +.25, 0, 0);
00594
00595
00596 applyHydrodynamicForces(.2);
00597
00598
00599 updateControllers();
00600
00601
00602
00603
00604 const dReal *bodyPos = dBodyGetPosition(itsSubBody);
00605 const dReal *bodyR = dBodyGetRotation(itsSubBody);
00606
00607 updateSensors(bodyPos, bodyR);
00608
00609 dSpaceCollide (space,this,&nearCallback);
00610
00611 dWorldStep(world,0.1);
00612
00613 dJointGroupEmpty (contactgroup);
00614
00615 itsWorldDisp->drawImage(flipVertic(getFrame(0)));
00616 }
00617
00618
00619
00620 void SeaBee3Simulator::updateControllers()
00621 {
00622 if(itsPIDsEnabled)
00623 {
00624 float DepthCommand = itsDepthPID->update(itsTargetDepth, itsSimDepth)*100;
00625 itsLeftVertThrusterVal = DepthCommand;
00626 itsRightVertThrusterVal = DepthCommand;
00627 itsDepthOutput = DepthCommand;
00628
00629 Angle currHeadingAngle(itsSimYaw);
00630 Angle desHeadingAngle(itsTargetHeading);
00631
00632 float HeadingCommand = (itsHeadingPID->update(desHeadingAngle, currHeadingAngle)).getRadians() * (180.0/M_PI)*100.0;
00633 itsForwardLeftThrusterVal = -HeadingCommand;
00634 itsForwardRightThrusterVal = HeadingCommand;
00635 itsHeadingOutput = HeadingCommand;
00636 }
00637 else
00638 {
00639 itsJSMutex.lock();
00640 int rightVal = itsJSValues[1]*-1;
00641 int leftVal = itsJSValues[1]*-1;
00642
00643 int depthVal = int((float(itsJSValues[5]) + 100.0)/2.0 - (float(itsJSValues[4]) + 100.0)/2.0);
00644
00645 int depthValRight = depthVal;
00646 int depthValLeft = depthVal;
00647
00648 int frontVal = itsJSValues[2] + itsJSValues[0];
00649 int backVal = itsJSValues[2]*-1 + itsJSValues[0];
00650
00651 if(itsButValues[5])
00652 {
00653 depthValRight = 75;
00654 depthValLeft = -75;
00655 }
00656 else if(itsButValues[4])
00657 {
00658 depthValRight = -75;
00659 depthValLeft = 75;
00660 }
00661
00662
00663
00664
00665 itsForwardRightThrusterVal = rightVal;
00666 itsForwardLeftThrusterVal = leftVal;
00667
00668
00669
00670
00671 itsLeftVertThrusterVal = depthValLeft;
00672 itsRightVertThrusterVal = depthValRight;
00673
00674
00675
00676 itsFrontStrafeThrusterVal = frontVal;
00677 itsBackStrafeThrusterVal = backVal;
00678 itsJSMutex.unlock();
00679 }
00680 }
00681
00682
00683
00684
00685 void SeaBee3Simulator::applyHydrodynamicForces(dReal viscosity)
00686 {
00687 const dReal *lvel = dBodyGetLinearVel(itsSubBody);
00688 const dReal *avel = dBodyGetAngularVel(itsSubBody);
00689 const dReal *R = dBodyGetRotation(itsSubBody);
00690
00691
00692 dReal AreaX = 10;
00693 dReal AreaY = 10;
00694 dReal AreaZ = 10;
00695
00696 dReal nx = (R[0] * lvel[0] + R[4] * lvel[1] + R[8] * lvel[2]) * AreaX;
00697 dReal ny = (R[1] * lvel[0] + R[5] * lvel[1] + R[9] * lvel[2]) * AreaY;
00698 dReal nz = (R[2] * lvel[0] + R[6] * lvel[1] + R[10] * lvel[2]) * AreaZ;
00699
00700 dReal temp = -nx * viscosity;
00701 dBodyAddForce(itsSubBody, temp * R[0], temp * R[4], temp * R[8]);
00702
00703 temp = -ny * viscosity;
00704 dBodyAddForce(itsSubBody, temp * R[1], temp * R[5], temp * R[9]);
00705
00706 temp =-nz * viscosity;
00707 dBodyAddForce(itsSubBody, temp * R[2], temp * R[6], temp * R[10]);
00708
00709 nx = (R[0] * avel[0] + R[4] * avel[1] + R[8] * avel[2]) * AreaZ;
00710 ny = (R[1] * avel[0] + R[5] * avel[1] + R[9] * avel[2]) * AreaX;
00711 nz = (R[2] * avel[0] + R[6] * avel[1] + R[10] * avel[2]) * AreaY;
00712
00713 temp = -nx * viscosity;
00714 dBodyAddTorque(itsSubBody, temp * R[0], temp * R[4], temp * R[8]);
00715
00716 temp = -ny * viscosity;
00717 dBodyAddTorque(itsSubBody, temp * R[1], temp * R[5], temp * R[9]);
00718
00719 temp = -nz * viscosity;
00720 dBodyAddTorque(itsSubBody, temp * R[2], temp * R[6], temp * R[10]);
00721
00722
00723 const dReal *bodyPos = dBodyGetPosition(itsSubBody);
00724
00725
00726 dMass *subMass = new dMass();
00727 dBodyGetMass(itsSubBody, subMass);
00728
00729 double TotalBuoyancy = 9.86;
00730
00731
00732 if(bodyPos[2] <= itsPoolDepth)
00733 {
00734
00735
00736
00737 dBodyAddForceAtRelPos(itsSubBody,0,0,subMass->mass * TotalBuoyancy,
00738 0,-0.01,0);
00739 }
00740 else if(bodyPos[2] <= itsPoolDepth + itsSubRadius)
00741 {
00742
00743
00744
00745
00746
00747
00748
00749
00750 dBodyAddForceAtRelPos(itsSubBody,0,0,subMass->mass *
00751 (TotalBuoyancy *
00752 (1 - (bodyPos[2] - itsPoolDepth)/(itsSubRadius))),
00753 0,-0.01,0);
00754 }
00755
00756
00757 }
00758
00759 Image<PixRGB<byte> > SeaBee3Simulator::getFrame(int camera)
00760 {
00761 const dReal *bodyPos = dBodyGetPosition(itsSubBody);
00762 const dReal *bodyR = dBodyGetRotation(itsSubBody);
00763
00764 double cam_xyz[3], cam_hpr[3] = {0.0,0.0,0.0};
00765
00766 double roll= (atan2(bodyR[9], bodyR[10]) + M_PI/2.0) * 180.0/M_PI;
00767 double pitch = asin(-bodyR[8]) * 180.0/M_PI;
00768 double yaw = atan2(bodyR[4], bodyR[0]) * 180.0/M_PI;
00769
00770 switch (camera)
00771 {
00772 case 0:
00773 cam_xyz[0] = bodyPos[0];
00774 cam_xyz[1] = bodyPos[1]-5;
00775 cam_xyz[2] = 10;
00776
00777 cam_hpr[0] = 90.0;
00778 cam_hpr[1] = -45.0;
00779 cam_hpr[2] = 0.0;
00780
00781 break;
00782 case 1:
00783 cam_xyz[0] = bodyPos[0];
00784 cam_xyz[1] = bodyPos[1];
00785 cam_xyz[2] = bodyPos[2];
00786
00787 cam_hpr[0] = yaw + 90;
00788 cam_hpr[1] = pitch;
00789 cam_hpr[2] = roll;
00790
00791 break;
00792 case 2:
00793 cam_xyz[0] = bodyPos[0];
00794 cam_xyz[1] = bodyPos[1];
00795 cam_xyz[2] = bodyPos[2];
00796
00797 cam_hpr[0] = yaw + 90;
00798 cam_hpr[1] = pitch - 90;
00799 cam_hpr[2] = roll;
00800
00801 break;
00802 }
00803 pthread_mutex_lock(&itsDispLock);
00804 if (camera != -1)
00805 vp->dsSetViewpoint (cam_xyz,cam_hpr);
00806 vp->initFrame();
00807 drawSub();
00808 drawArena();
00809 vp->updateFrame();
00810 pthread_mutex_unlock(&itsDispLock);
00811
00812
00813 return vp->getFrame();
00814 }
00815
00816 void SeaBee3Simulator::getSensors(float &xPos, float &yPos, float &depth,
00817 float &roll, float &pitch, float &yaw)
00818 {
00819
00820 xPos = itsSimXPos;
00821 yPos = itsSimYPos;
00822 depth = itsSimDepth;
00823 roll = itsSimRoll;
00824 pitch = itsSimPitch;
00825 yaw = itsSimYaw;
00826
00827 }
00828
00829 void SeaBee3Simulator::setThrusters(double forwardLeftThruster, double forwardRightThruster,
00830 double verticalLeftThruster, double verticalRightThruster,
00831 double forwardStrafeThruster, double backStrafeThruster)
00832 {
00833
00834 itsForwardLeftThrusterVal = forwardLeftThruster;
00835 itsForwardRightThrusterVal = forwardRightThruster;
00836 itsFrontStrafeThrusterVal = forwardStrafeThruster;
00837 itsBackStrafeThrusterVal = backStrafeThruster;
00838 itsLeftVertThrusterVal = verticalLeftThruster;
00839 itsRightVertThrusterVal = verticalRightThruster;
00840 }
00841