SubSim.C

Go to the documentation of this file.
00001 /*!@file BeoSub/SubSim.C Sub Simulator */
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.         // // See http://iLab.usc.edu for information about this project.          //
00006 // //////////////////////////////////////////////////////////////////// //
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 // //////////////////////////////////////////////////////////////////// //
00031 //
00032 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/SubSim.C $
00034 // $Id: SubSim.C 11565 2009-08-09 02:14:40Z rand $
00035 //
00036 
00037 #include "BeoSub/SubSim.H"
00038 #include "Component/OptionManager.H"
00039 #include "Util/MathFunctions.H"
00040 #include "Util/Assert.H"
00041 #include "rutz/compat_snprintf.h"
00042 #include "Image/MatrixOps.H"
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <signal.h>
00046 
00047 
00048 namespace {
00049 
00050   void nearCallback (void *data, dGeomID o1, dGeomID o2){
00051     SubSim *subSim = (SubSim *)data;
00052     const int MaxContacts = 10;
00053 
00054     //create a contact joint to simulate collisions
00055     dContact contact[MaxContacts];
00056     int nContacts = dCollide (o1,o2,MaxContacts,
00057         &contact[0].geom,sizeof(dContact));
00058     for (int i=0; i<nContacts; i++) {
00059       contact[i].surface.mode = dContactSoftCFM ; //| dContactBounce; // | dContactSoftCFM;
00060       contact[i].surface.mu = 0.5;
00061       contact[i].surface.mu2 = 0.5;
00062       contact[i].surface.bounce = 0.01;
00063       contact[i].surface.bounce_vel = 0.01;
00064       contact[i].surface.soft_cfm = 0.001;
00065 
00066       dJointID c = dJointCreateContact (subSim->getWorld(),
00067           subSim->getContactgroup(),&contact[i]);
00068       dJointAttach (c,
00069           dGeomGetBody(contact[i].geom.g1),
00070           dGeomGetBody(contact[i].geom.g2));
00071     }
00072   }
00073 }
00074 
00075 // ######################################################################
00076 SubSim::SubSim(OptionManager& mgr, const std::string& descrName,
00077     const std::string& tagName, bool showWorld) :
00078   ModelComponent(mgr, descrName, tagName),
00079   itsWaterLevel(4.57), //15 feet of water
00080   itsSubLength(1.5), //the length of sub in meters
00081   itsSubRadius(0.2), //the radius of the sub in meters
00082   itsSubWeight(30), // the weight of the sub in kg
00083   vp(new ViewPort("SubSim")),
00084   itsPanTruster(0),
00085   itsTiltTruster(0),
00086   itsForwardTruster(0),
00087   itsUpTruster(0),
00088   itsXPos(0),
00089   itsYPos(0),
00090   itsDepth(0),
00091   itsRoll(0),
00092   itsPitch(0),
00093   itsYaw(0),
00094   itsWorldView(true),
00095   itsShowWorld(showWorld),
00096   itsWorldDisp(NULL)
00097 {
00098   vp->isSubSim = true;
00099 
00100   if (itsShowWorld)
00101   {
00102     itsWorldDisp = new XWinManaged(vp->getDims(), -1, -1, "World View");
00103   }
00104 
00105   pthread_mutex_init(&itsDispLock, NULL);
00106 
00107 }
00108 
00109 SubSim::~SubSim()
00110 {
00111   dSpaceDestroy(space);
00112   dWorldDestroy(world);
00113 
00114   delete vp;
00115   delete itsWorldDisp;
00116   pthread_mutex_destroy(&itsDispLock);
00117 }
00118 
00119 void SubSim::start2()
00120 {
00121   //        setDrawStuff();
00122   world = dWorldCreate();
00123   space = dHashSpaceCreate(0);
00124   contactgroup = dJointGroupCreate(0);
00125   ground = dCreatePlane(space, 0, 0, 1, 0);
00126   dWorldSetGravity(world,0,0,0);
00127 
00128   dWorldSetCFM (world,1e-6);
00129   dWorldSetERP (world,1);
00130   //dWorldSetAutoDisableFlag (world,1);
00131   dWorldSetContactMaxCorrectingVel (world,0.1);
00132   //set the contact penetration
00133   dWorldSetContactSurfaceLayer(world, 0.001);
00134 
00135 
00136   makeSub();
00137 
00138   //set the viewpoint
00139   double xyz[3] = {0 , -3.0, 15};
00140   double hpr[3] = {90.0,-45,0.0};
00141   vp->dsSetViewpoint (xyz,hpr);
00142 
00143 }
00144 
00145 void SubSim::makeSub()
00146 {
00147   dMass mass;
00148   itsSubBody = dBodyCreate(world);
00149   //pos[0] = 0; pos[1] = 1.0*5; pos[2] = 1.80;
00150 
00151   //  dBodySetPosition(itsSubBody,1.85,4.91*5,3.04); //Sub is 10 feet underwater
00152   dBodySetPosition(itsSubBody,0,0.2*5,1.94); //Sub is 10 feet underwater
00153 
00154   dMatrix3 R;
00155   dRFromAxisAndAngle (R,1,0,0,-M_PI/2);
00156   dBodySetRotation(itsSubBody, R);
00157   dMassSetZero(&mass);
00158   dMassSetCappedCylinderTotal(&mass,itsSubWeight,3,itsSubRadius,itsSubLength);
00159   dMassRotate(&mass, R);
00160   dBodySetMass(itsSubBody,&mass);
00161   itsSubGeom = dCreateCCylinder(space, itsSubRadius, itsSubLength);
00162   dGeomSetRotation(itsSubGeom, R);
00163   dGeomSetBody(itsSubGeom, itsSubBody);
00164 }
00165 
00166 void SubSim::drawSub()
00167 {
00168   //double r, length;
00169   dReal r, length;
00170 
00171   dGeomCCylinderGetParams(itsSubGeom,&r,&length);
00172 
00173   vp->dsSetColor(1,1,0);
00174   vp->dsDrawCappedCylinder(
00175       dBodyGetPosition(itsSubBody),
00176       dBodyGetRotation(itsSubBody),
00177       length,
00178       r);
00179 
00180 }
00181 
00182 void SubSim::drawArena()
00183 {
00184 
00185   double pos[3];
00186 
00187   pos[0] = 0; pos[1] = 1.0*5; pos[2] = 2.80;
00188   drawGate(pos);
00189 
00190   pos[0] = 0.16*5; pos[1] = 3.8*5; pos[2] = 1.83;
00191   drawBuoy(pos);
00192 
00193   pos[0] = 0.66*5; pos[1] = 4.33*5; pos[2] = 0.6;
00194   drawPipeline(0, pos);
00195 
00196   pos[0] = 1.16*5; pos[1] = 4.66*5; pos[2] = 0.6;
00197   drawBin(0, pos);
00198 
00199   pos[0] = 1.75*5; pos[1] = 4.91*5; pos[2] = 0.6;
00200   drawPipeline(M_PI/4, pos);
00201 
00202   pos[0] = 2.33*5; pos[1] = 5.41*5; pos[2] = 0.6;
00203   drawPipeline(0, pos);
00204 
00205   pos[0] = 3.0*5; pos[1] = 5.25*5; pos[2] = 0.6;
00206   drawPipeline(-M_PI/4, pos);
00207 
00208   pos[0] = 3.5*5; pos[1] = 4.083*5; pos[2] = 0.6;
00209   drawBin(M_PI/2, pos);
00210 
00211   pos[0] = 3.5*5; pos[1] = 4.083*5; pos[2] = 1.83;
00212   drawBuoy(pos);
00213 
00214   pos[0] = 3.83*5; pos[1] = 4.33*5; pos[2] = 0.6;
00215   drawPipeline(-M_PI/4, pos);
00216 
00217 
00218   pos[0] = 4.75*5; pos[1] = 3.5*5; pos[2] = 0.6;
00219   drawPinger(pos);
00220 }
00221 
00222 
00223 void SubSim::drawGate(const double *gatePos)
00224 {
00225   double pos[3];
00226   double R[12];
00227   //Gate
00228   vp->dsSetColor(0,0,0);
00229   //Top
00230   pos[0] = gatePos[0]; pos[1] = gatePos[1]; pos[2] = gatePos[2];
00231 
00232   dRFromAxisAndAngle (R,0,1,0,-M_PI/2);
00233   vp->dsDrawCappedCylinder(pos, R, 3.05f, 0.1f);
00234 
00235   //side
00236   dRSetIdentity(R);
00237   pos[0] = gatePos[0]-(3.05/2); pos[1] = gatePos[1]; pos[2] = gatePos[2]/2;
00238   vp->dsDrawCappedCylinder(pos, R, 1.83, 0.1);
00239 
00240   pos[0] = gatePos[0]+(3.05/2); pos[1] = gatePos[1]; pos[2] = gatePos[2]/2;
00241   vp->dsDrawCappedCylinder(pos, R, 1.83, 0.1);
00242 }
00243 
00244 
00245 void SubSim::drawBuoy(const double *bouyPos)
00246 {
00247   static int frame = 0;
00248   static bool bouyOn = false;
00249   double pos[3];
00250   double R[12];
00251 
00252   //start Buoy
00253   //flash buoy
00254   if (frame++ > 5) //this sets the frame rate
00255   {
00256     bouyOn = !bouyOn;
00257     frame = 0;
00258   }
00259 
00260   if (bouyOn)
00261     vp->dsSetColor(1,0,0);
00262   else
00263     vp->dsSetColor(0.5,0,0);
00264   pos[0] = bouyPos[0]; pos[1] = bouyPos[1]; pos[2] = bouyPos[2];
00265   dRSetIdentity(R);
00266   vp->dsDrawSphere(pos, R, 0.20);
00267   double pos1[3];
00268   vp->dsSetColor(0,0,0);
00269   pos1[0] = pos[0]; pos1[1] = pos[1]; pos1[2] = 0;
00270   vp->dsDrawLine(pos, pos1);
00271 
00272 }
00273 
00274 void SubSim::drawPipeline(const double ori, const double *pipePos)
00275 {
00276 
00277   double sides[3] = {1.2, 0.15, 0.1};
00278   double R[12];
00279 
00280   dRFromAxisAndAngle (R,0,0,1,ori);
00281 
00282   vp->dsSetColor(1,0.5,0);
00283 
00284   vp->dsDrawBox(pipePos, R, sides);
00285 }
00286 
00287 void SubSim::drawBin(const double ori, const double *binPos)
00288 {
00289 
00290   double sides[3];
00291   double R[12];
00292 
00293   dRFromAxisAndAngle (R,0,0,1,ori);
00294 
00295   vp->dsSetColor(1,1,1);
00296   sides[0] = 0.6; sides[1] = 0.8; sides[2] = 0.1;
00297   vp->dsDrawBox(binPos, R, sides);
00298 
00299   vp->dsSetColor(0,0,0);
00300   sides[0] = 0.3; sides[1] = 0.6; sides[2] = 0.15;
00301   vp->dsDrawBox(binPos, R, sides);
00302 }
00303 
00304 void SubSim::drawPinger(const double *pingerPos)
00305 {
00306   double pos[3];
00307   double R[12];
00308 
00309   vp->dsSetColor(1,1,1);
00310   pos[0] = pingerPos[0]; pos[1] = pingerPos[1]; pos[1] = pingerPos[2] + 1.2/2;
00311   vp->dsDrawCappedCylinder(pos, R, 1.2, 0.1);
00312 
00313 }
00314 
00315 
00316 void SubSim::handleWinEvents(XEvent& event)
00317 {
00318 }
00319 
00320 //void SubSim::updateSensors(const double *pos, const double *R)
00321 void SubSim::updateSensors(const dReal *pos, const dReal *R)
00322 {
00323   itsXPos = pos[0];
00324   itsYPos = pos[1];
00325   itsDepth = pos[2];
00326   itsRoll  = atan2(R[9], R[10]) + M_PI/2;     //phi correct for initial rotation
00327   itsPitch = asin(-R[8]);            //theta
00328   itsYaw   = atan2(R[4], R[0]);      //greek Y
00329 
00330   if (itsYaw < 0) itsYaw += M_PI*2;
00331   // LINFO("(%f,%f) Depth %f, roll %f pitch %f yaw %f",
00332   //     itsXPos, itsYPos, itsDepth,
00333   //     itsRoll, itsPitch, itsYaw);
00334 
00335 }
00336 
00337 void SubSim::simLoop()
00338 {
00339 
00340   //set the trusters
00341   dBodyAddRelForceAtRelPos(itsSubBody,0,itsUpTruster,0, 0,0,0);
00342   dBodyAddRelTorque(itsSubBody,itsTiltTruster, 0, 0);
00343   dBodyAddRelTorque(itsSubBody,0, itsPanTruster, 0);
00344   dBodyAddRelForceAtRelPos(itsSubBody,0,0,itsForwardTruster, 0,0,0);
00345 
00346   //Apply a viscosity water force
00347   applyHydrodynamicForces(0.5);
00348 
00349   //Folow the sub with the camera
00350   //  const double *bodyPos = dBodyGetPosition(itsSubBody);
00351   //const double *bodyR = dBodyGetRotation(itsSubBody);
00352   const dReal *bodyPos = dBodyGetPosition(itsSubBody);
00353   const dReal *bodyR = dBodyGetRotation(itsSubBody);
00354 
00355   updateSensors(bodyPos, bodyR);
00356 
00357   dSpaceCollide (space,this,&nearCallback); //check for collisions
00358 
00359   dWorldStep(world,0.1);
00360 
00361   dJointGroupEmpty (contactgroup); //delete the contact joints
00362 
00363   if (itsShowWorld)
00364   {
00365     itsWorldDisp->drawImage(flipVertic(getFrame(0)));
00366   }
00367 }
00368 
00369 
00370 //! Calculate the water forces on the object
00371 // Obtained from http://ode.org/pipermail/ode/2005-January/014929.html
00372 void SubSim::applyHydrodynamicForces(dReal viscosity)
00373 {
00374   const dReal *lvel = dBodyGetLinearVel(itsSubBody);
00375   const dReal *avel = dBodyGetAngularVel(itsSubBody);
00376   const dReal *R = dBodyGetRotation(itsSubBody);
00377 
00378 
00379   //Should be the area of the sub
00380   dReal AreaX = 10;
00381   dReal AreaY = 10;
00382   dReal AreaZ = 10;
00383 
00384   dReal nx = (R[0] * lvel[0] + R[4] * lvel[1] + R[8] * lvel[2]) *  AreaX;
00385   dReal ny = (R[1] * lvel[0] + R[5] * lvel[1] + R[9] * lvel[2]) * AreaY;
00386   dReal nz = (R[2] * lvel[0] + R[6] * lvel[1] + R[10] * lvel[2]) * AreaZ;
00387 
00388   dReal temp = -nx * viscosity;
00389   dBodyAddForce(itsSubBody, temp * R[0], temp * R[4], temp * R[8]);
00390 
00391   temp = -ny * viscosity;
00392   dBodyAddForce(itsSubBody, temp * R[1], temp * R[5], temp * R[9]);
00393 
00394   temp =-nz * viscosity;
00395   dBodyAddForce(itsSubBody, temp * R[2], temp * R[6], temp * R[10]);
00396 
00397   nx = (R[0] * avel[0] + R[4] * avel[1] + R[8] * avel[2]) * AreaZ;
00398   ny = (R[1] * avel[0] + R[5] * avel[1] + R[9] * avel[2]) * AreaX;
00399   nz = (R[2] * avel[0] + R[6] * avel[1] + R[10] * avel[2]) * AreaY;
00400 
00401   temp = -nx * viscosity; // * 500; //seems to strong
00402   dBodyAddTorque(itsSubBody, temp * R[0], temp * R[4], temp * R[8]);
00403 
00404   temp = -ny * viscosity; // * 500;
00405   dBodyAddTorque(itsSubBody, temp * R[1], temp * R[5], temp * R[9]);
00406 
00407   temp = -nz * viscosity; // * 500;
00408   dBodyAddTorque(itsSubBody, temp * R[2], temp * R[6], temp * R[10]);
00409 
00410 }
00411 
00412 Image<PixRGB<byte> > SubSim::getFrame(int camera)
00413 {
00414   const dReal *bodyPos = dBodyGetPosition(itsSubBody);
00415   const dReal *bodyR = dBodyGetRotation(itsSubBody);
00416 
00417   double cam_xyz[3], cam_hpr[3] = {0.0,0.0,0.0};
00418 
00419   switch (camera)
00420   {
00421     case 0: //world camera
00422       cam_xyz[0] = bodyPos[0];
00423       cam_xyz[1] =  bodyPos[1]-5;
00424       cam_xyz[2] =  10;
00425 
00426       cam_hpr[0]   = 90.0;
00427       cam_hpr[1]   = -45.0;
00428       cam_hpr[2]   = 0.0;
00429 
00430       break;
00431     case 1:
00432       cam_xyz[0] = bodyPos[0];
00433       cam_xyz[1] = bodyPos[1];
00434       cam_xyz[2] = bodyPos[2];
00435 
00436       cam_hpr[0]   = (atan2(bodyR[4], bodyR[0])*180/M_PI) + 90; //yaw
00437 
00438       break;
00439     case 2:
00440       cam_xyz[0] = bodyPos[0];
00441       cam_xyz[1] = bodyPos[1];
00442       cam_xyz[2] = bodyPos[2];
00443 
00444       cam_hpr[0]   = (atan2(bodyR[4], bodyR[0])*180/M_PI) + 90; //yaw
00445       cam_hpr[1]   = -90; //yaw
00446 
00447 
00448       break;
00449   }
00450   pthread_mutex_lock(&itsDispLock);
00451   if (camera != -1)
00452     vp->dsSetViewpoint (cam_xyz,cam_hpr);
00453   vp->initFrame();
00454   drawSub();
00455   drawArena();
00456   vp->updateFrame();
00457   pthread_mutex_unlock(&itsDispLock);
00458 
00459 
00460   return vp->getFrame();
00461 
00462 }
00463 
00464 void SubSim::getSensors(float &xPos, float &yPos, float &depth,
00465     float &roll, float &pitch, float &yaw)
00466 {
00467 
00468   xPos = itsXPos;
00469   yPos = itsYPos;
00470   depth = itsDepth;
00471   roll = itsRoll;
00472   pitch = itsPitch;
00473   yaw = itsYaw;
00474 
00475 }
00476 
00477 void SubSim::setTrusters(float panTruster, float tiltTruster, float forwardTruster, float upTruster)
00478 {
00479 
00480   itsPanTruster =      panTruster;
00481   itsTiltTruster =     tiltTruster;
00482   itsForwardTruster =  forwardTruster;
00483   itsUpTruster =       upTruster;
00484 }
00485 
00486 // ######################################################################
00487 /* So things look consistent in everyone's emacs... */
00488 /* Local Variables: */
00489 /* indent-tabs-mode: nil */
00490 /* End: */
Generated on Sun May 8 08:04:33 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3