00001 /*!@file Robots/IRobot/IRobotSim.C IRobot 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. // 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 $ 00035 // $Id $ 00036 // 00037 00038 #include "Robots/IRobot/IRobotSim.H" 00039 #include "Component/OptionManager.H" 00040 #include "Util/MathFunctions.H" 00041 #include "Util/Assert.H" 00042 #include "rutz/compat_snprintf.h" 00043 #include "Image/MatrixOps.H" 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 #include <signal.h> 00047 00048 00049 namespace { 00050 00051 void nearCallback (void *data, dGeomID o1, dGeomID o2){ 00052 IRobotSim *iRobotSim = (IRobotSim *)data; 00053 const int MaxContacts = 10; 00054 00055 double surface_mu = dInfinity; 00056 00057 //Dont colide the robot with the ground 00058 if ((o1 == iRobotSim->getRobotGeom() && o2 == iRobotSim->getGroundGeom()) || 00059 (o2 == iRobotSim->getRobotGeom() && o1 == iRobotSim->getGroundGeom())) 00060 return; 00061 00062 //If we are contacted with a castor, then set the contact to slip 00063 if (o1 == iRobotSim->getCasterGeom() || o2 == iRobotSim->getCasterGeom()) 00064 surface_mu = 0; 00065 00066 00067 //create a contact joint to simulate collisions 00068 dContact contact[MaxContacts]; 00069 int nContacts = dCollide (o1,o2,MaxContacts, 00070 &contact[0].geom,sizeof(dContact)); 00071 for (int i=0; i<nContacts; i++) { 00072 //contact[i].surface.mode = dContactSoftCFM ; //| dContactBounce; // | dContactSoftCFM; 00073 contact[i].surface.mode = dContactSlip1 | dContactSlip2 | 00074 dContactSoftERP | dContactSoftCFM | dContactApprox1; 00075 contact[i].surface.mu = surface_mu; 00076 contact[i].surface.slip1 = 0.1; 00077 contact[i].surface.slip2 = 0.1; 00078 contact[i].surface.soft_erp = 0.005; 00079 contact[i].surface.soft_cfm = 0.003; 00080 00081 dJointID c = dJointCreateContact (iRobotSim->getWorld(), 00082 iRobotSim->getContactgroup(),&contact[i]); 00083 dJointAttach (c, 00084 dGeomGetBody(contact[i].geom.g1), 00085 dGeomGetBody(contact[i].geom.g2)); 00086 } 00087 } 00088 } 00089 00090 // ###################################################################### 00091 IRobotSim::IRobotSim(OptionManager& mgr, const std::string& descrName, 00092 const std::string& tagName, bool showWorld) : 00093 ModelComponent(mgr, descrName, tagName), 00094 itsRobotStartZ(0.3), //the start loc of the robot 00095 itsRobotRadius(0.33), //the radius of the sub in meters 00096 itsRobotHeight(0.06), //the radius of the sub in meters 00097 itsRobotWeight(1), // the weight of the sub in kg 00098 itsRobotWheelRadius(0.02), // the wheel size 00099 itsRightWheelSpeed(0), 00100 itsLeftWheelSpeed(0), 00101 itsXPos(0), 00102 itsYPos(0), 00103 itsOri(0), 00104 itsRightEncoder(0), 00105 itsLeftEncoder(0), 00106 itsPrevRightWheelAng(0), 00107 itsPrevLeftWheelAng(0), 00108 itsWorldView(true), 00109 itsShowWorld(showWorld), 00110 itsWorldDisp(NULL) 00111 { 00112 pthread_mutex_init(&itsDispLock, NULL); 00113 00114 } 00115 00116 IRobotSim::~IRobotSim() 00117 { 00118 for(uint i=0; i<itsObjects.size(); i++) 00119 { 00120 Object obj = itsObjects[i]; 00121 if (obj.texturePtr) 00122 delete obj.texturePtr; 00123 } 00124 00125 dSpaceDestroy(space); 00126 dWorldDestroy(world); 00127 00128 delete itsVP; 00129 delete itsWorldDisp; 00130 pthread_mutex_destroy(&itsDispLock); 00131 } 00132 00133 void IRobotSim::start2() 00134 { 00135 // setDrawStuff(); 00136 world = dWorldCreate(); 00137 space = dHashSpaceCreate(0); 00138 contactgroup = dJointGroupCreate(0); 00139 dWorldSetGravity(world,0,0,-0.5); 00140 00141 ground = dCreatePlane(space, 0, 0, 1, 0); 00142 dGeomSetCategoryBits(ground, GROUND_BITFIELD); 00143 00144 //dWorldSetCFM (world,1e-6); 00145 //dWorldSetERP (world,1); 00146 //dWorldSetAutoDisableFlag (world,1); 00147 dWorldSetContactMaxCorrectingVel (world,0.1); 00148 //set the contact penetration 00149 dWorldSetContactSurfaceLayer(world, 0.0001); 00150 00151 00152 00153 } 00154 00155 void IRobotSim::initViewport() 00156 { 00157 itsVP = new ViewPort("IRobotSim", "grass.ppm", "sky.ppm"); 00158 00159 makeRobot(); 00160 makeWorld(); 00161 00162 //Overhead cam 00163 //double xyz[3] = {0 , 0, 40}; 00164 //double hpr[3] = {90.0,-90,0.0}; 00165 00166 double xyz[3] = {0.6 , -1.5, 2}; 00167 double hpr[3] = {90.0,-25,0.0}; 00168 itsVP->dsSetViewpoint (xyz,hpr); 00169 } 00170 00171 void IRobotSim::makeRobot() 00172 { 00173 dMass mass; 00174 00175 //The body 00176 itsRobotBody = dBodyCreate(world); 00177 dMassSetZero(&mass); 00178 dMassSetCylinder(&mass,itsRobotWeight,3,itsRobotRadius,itsRobotHeight); 00179 dMassAdjust(&mass, itsRobotWeight); 00180 dBodySetMass(itsRobotBody,&mass); 00181 00182 dBodySetPosition(itsRobotBody,0,0,itsRobotStartZ); 00183 itsRobotGeom = dCreateCCylinder(space, itsRobotRadius, itsRobotHeight); 00184 dGeomSetBody(itsRobotGeom, itsRobotBody); 00185 //dGeomSetCategoryBits(itsRobotGeom,ROBOT_BITFIELD); 00186 //dGeomSetCollideBits(itsRobotGeom,!ROBOT_BITFIELD && !GROUND_BITFIELD); //don't colide with the ground 00187 00188 // wheel bodies 00189 dQuaternion q; 00190 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5); 00191 dMassSetSphere (&mass,1,itsRobotWheelRadius); 00192 dMassAdjust (&mass,0.2); 00193 00194 itsRightWheelBody = dBodyCreate (world); 00195 dBodySetQuaternion (itsRightWheelBody,q); 00196 dBodySetMass (itsRightWheelBody,&mass); 00197 dGeomID rWheelSphere = dCreateSphere (space,itsRobotWheelRadius); 00198 dGeomSetBody (rWheelSphere,itsRightWheelBody); 00199 dBodySetPosition (itsRightWheelBody,-itsRobotRadius/2, itsRobotRadius,itsRobotStartZ-itsRobotHeight-0.01); 00200 //dGeomSetCategoryBits(rWheelSphere,ROBOT_BITFIELD); 00201 //dGeomSetCollideBits(rWheelSphere,!ROBOT_BITFIELD); //don't colide with the Robot 00202 00203 itsLeftWheelBody = dBodyCreate (world); 00204 dBodySetQuaternion (itsLeftWheelBody,q); 00205 dBodySetMass (itsLeftWheelBody,&mass); 00206 dGeomID lWheelSphere = dCreateSphere (space,itsRobotWheelRadius); 00207 dGeomSetBody (lWheelSphere,itsLeftWheelBody); 00208 dBodySetPosition (itsLeftWheelBody,-itsRobotRadius/2, -itsRobotRadius,itsRobotStartZ-itsRobotHeight-0.01); 00209 //dGeomSetCategoryBits(lWheelSphere,ROBOT_BITFIELD); 00210 //dGeomSetCollideBits(lWheelSphere,!ROBOT_BITFIELD); //don't colide with the Robot 00211 00212 //Wheel hinges 00213 itsRightWheelJoint = dJointCreateHinge2 (world,0); 00214 dJointAttach (itsRightWheelJoint,itsRobotBody,itsRightWheelBody); 00215 const dReal *rWheelPos = dBodyGetPosition (itsRightWheelBody); 00216 dJointSetHinge2Anchor (itsRightWheelJoint,rWheelPos[0],rWheelPos[1],rWheelPos[2]); 00217 dJointSetHinge2Axis1 (itsRightWheelJoint,0,0,1); 00218 dJointSetHinge2Axis2 (itsRightWheelJoint,0,1,0); 00219 // set joint suspension 00220 dJointSetHinge2Param (itsRightWheelJoint,dParamSuspensionERP,0.002); 00221 dJointSetHinge2Param (itsRightWheelJoint,dParamSuspensionCFM,0.004); 00222 00223 // lock all wheels along the steering axis 00224 // set stops to make sure wheels always stay in alignment 00225 dJointSetHinge2Param (itsRightWheelJoint,dParamLoStop,0); 00226 dJointSetHinge2Param (itsRightWheelJoint,dParamHiStop,0); 00227 00228 itsLeftWheelJoint = dJointCreateHinge2 (world,0); 00229 dJointAttach (itsLeftWheelJoint,itsRobotBody,itsLeftWheelBody); 00230 const dReal *lWheelPos = dBodyGetPosition (itsLeftWheelBody); 00231 dJointSetHinge2Anchor (itsLeftWheelJoint,lWheelPos[0],lWheelPos[1],lWheelPos[2]); 00232 dJointSetHinge2Axis1 (itsLeftWheelJoint,0,0,1); 00233 dJointSetHinge2Axis2 (itsLeftWheelJoint,0,1,0); 00234 // set joint suspension 00235 dJointSetHinge2Param (itsLeftWheelJoint,dParamSuspensionERP,0.002); 00236 dJointSetHinge2Param (itsLeftWheelJoint,dParamSuspensionCFM,0.004); 00237 00238 // lock all wheels along the steering axis 00239 // set stops to make sure wheels always stay in alignment 00240 dJointSetHinge2Param (itsLeftWheelJoint,dParamLoStop,0); 00241 dJointSetHinge2Param (itsLeftWheelJoint,dParamHiStop,0); 00242 00243 00244 //Create the castor 00245 dQFromAxisAndAngle (q,1,0,0,M_PI*0.5); 00246 dMassSetSphere (&mass,1,itsRobotWheelRadius); 00247 dMassAdjust (&mass,0.2); 00248 00249 itsCasterBody = dBodyCreate (world); 00250 dBodySetQuaternion (itsCasterBody,q); 00251 dBodySetMass (itsCasterBody,&mass); 00252 dGeomID itsCasterGeom = dCreateSphere (space,itsRobotWheelRadius); 00253 dGeomSetBody (itsCasterGeom,itsCasterBody); 00254 dBodySetPosition (itsCasterBody,itsRobotRadius, 0, itsRobotStartZ-itsRobotHeight-0.01); 00255 //dGeomSetCategoryBits(itsCasterGeom,ROBOT_BITFIELD); 00256 //dGeomSetCollideBits(itsCasterGeom,!ROBOT_BITFIELD); //don't colide with the Robot 00257 00258 dJointID casterJoint = dJointCreateHinge2 (world,0); 00259 dJointAttach (casterJoint,itsRobotBody,itsCasterBody); 00260 const dReal *casterPos = dBodyGetPosition (itsCasterBody); 00261 dJointSetHinge2Anchor (casterJoint,casterPos[0],casterPos[1],casterPos[2]); 00262 dJointSetHinge2Axis1 (casterJoint,0,0,1); 00263 dJointSetHinge2Axis2 (casterJoint,0,1,0); 00264 // set joint suspension 00265 dJointSetHinge2Param (casterJoint,dParamSuspensionERP,0.00002); 00266 dJointSetHinge2Param (casterJoint,dParamSuspensionCFM,0.00004); 00267 dJointSetHinge2Param (casterJoint,dParamLoStop,0); 00268 dJointSetHinge2Param (casterJoint,dParamHiStop,0); 00269 00270 } 00271 00272 void IRobotSim::drawRobot() 00273 { 00274 //double r, length; 00275 dReal r, length; 00276 00277 dGeomCCylinderGetParams(itsRobotGeom,&r,&length); 00278 00279 itsVP->dsSetColor(1,1,0); 00280 00281 //Draw Body 00282 itsVP->dsDrawCylinder( 00283 dBodyGetPosition(itsRobotBody), 00284 dBodyGetRotation(itsRobotBody), 00285 length, 00286 r); 00287 00288 //Draw Wheels 00289 itsVP->dsSetColor(0,0,0); 00290 itsVP->dsDrawCylinder (dBodyGetPosition(itsRightWheelBody), 00291 dBodyGetRotation(itsRightWheelBody),0.02f,itsRobotWheelRadius); 00292 itsVP->dsDrawCylinder (dBodyGetPosition(itsLeftWheelBody), 00293 dBodyGetRotation(itsLeftWheelBody),0.02f,itsRobotWheelRadius); 00294 00295 //Draw Caster 00296 itsVP->dsDrawSphere (dBodyGetPosition(itsCasterBody), 00297 dBodyGetRotation(itsCasterBody),itsRobotWheelRadius); 00298 00299 } 00300 00301 00302 void IRobotSim::makeWorld() 00303 { 00304 00305 initRandomNumbersZero(); 00306 00307 //Draw 50 random trees 00308 //for(int i=0; i<50; i++) 00309 //{ 00310 // double initPos[3] = { 0, 0, 0}; 00311 // double objSize[3] = { 0.20, 3.5, 0.0}; 00312 00313 // initPos[0] = (randomDouble()*50-25) + 2; 00314 // initPos[1] = (randomDouble()*50-25) + 2; 00315 00316 // addObject(TREE, initPos, objSize); 00317 //} 00318 00319 double initPos[3] = { -25.0, 25.0, 0.0}; 00320 double objSize[3] = { 2, 2, 2}; 00321 addObject(TOBJ, initPos, objSize, true, "./etc/textures/detail040.ppm"); 00322 00323 initPos[0] = -5; initPos[1] = 16; initPos[2] = 0; 00324 objSize[0] = 3; objSize[1] = 2; objSize[2] = 5; 00325 addObject(TOBJ, initPos, objSize, true, "./etc/textures/build123.ppm"); 00326 00327 initPos[0] = -7; initPos[1] = 7; initPos[2] = 0; 00328 objSize[0] = 6; objSize[1] = 4; objSize[2] = 10; 00329 addObject(TOBJ, initPos, objSize, true, "./etc/textures/build123.ppm"); 00330 00331 initPos[0] = 5; initPos[1] = 10; initPos[2] = 0; 00332 objSize[0] = 3; objSize[1] = 2; objSize[2] = 5; 00333 addObject(TOBJ, initPos, objSize, true, "./etc/textures/build085.ppm"); 00334 00335 initPos[0] = -5; initPos[1] = -5; initPos[2] = 0; 00336 objSize[0] = 3; objSize[1] = 2; objSize[2] = 5; 00337 addObject(TOBJ, initPos, objSize, true, "./etc/textures/build085.ppm"); 00338 00339 initPos[0] = 5; initPos[1] = -10; initPos[2] = 0; 00340 objSize[0] = 3; objSize[1] = 2; objSize[2] = 5; 00341 addObject(TOBJ, initPos, objSize, true, "./etc/textures/brick.ppm"); 00342 00343 //Place trees at waypoints 00344 00345 objSize[0] = 0.1; objSize[1] = 3.5; objSize[2] = 0; 00346 00347 initPos[0] = 0.0; initPos[1] = 0.0; initPos[2] = 0; 00348 addObject(TREE, initPos, objSize, false); 00349 00350 initPos[0] = -1800/100; initPos[1] = 200/100; initPos[2] = 0; 00351 addObject(TREE, initPos, objSize, false); 00352 00353 initPos[0] = -1800/100; initPos[1] = 2300/100; initPos[2] = 0; 00354 addObject(TREE, initPos, objSize, false); 00355 00356 initPos[0] = 400/100; initPos[1] = 1800/100; initPos[2] = 0; 00357 addObject(TREE, initPos, objSize, false); 00358 00359 } 00360 00361 void IRobotSim::addObject(OBJECT_TYPE objType, 00362 double initPos[3],double objSize[3], 00363 bool addToSpace, 00364 const char* texture) 00365 { 00366 00367 dMass m; 00368 00369 Object obj; 00370 obj.body = dBodyCreate(world); 00371 obj.texturePtr = NULL; 00372 00373 dSpaceID spaceToAdd = 0; 00374 if (addToSpace) 00375 spaceToAdd = space; 00376 00377 switch(objType) 00378 { 00379 case BOX: 00380 dMassSetZero(&m); 00381 dMassSetBoxTotal(&m, 1, objSize[0], objSize[1], objSize[2]); 00382 dBodySetMass(obj.body, &m); 00383 obj.geom = dCreateBox(spaceToAdd, objSize[0], objSize[1], objSize[2]); 00384 dBodySetPosition(obj.body, initPos[0], initPos[1], initPos[2]); 00385 dGeomSetBody(obj.geom, obj.body); 00386 obj.color[0] = 0; obj.color[1] = 196; obj.color[2] = 127; //1 0 0 Red object 00387 obj.texture = ViewPort::WOOD; 00388 obj.type = BOX; 00389 break; 00390 case TREE: 00391 obj.geom = dCreateCCylinder(spaceToAdd, objSize[0], objSize[1]); 00392 dGeomSetBody(obj.geom, 0); 00393 dGeomSetPosition(obj.geom, initPos[0], initPos[1], initPos[2]); 00394 obj.texture = ViewPort::WOOD; 00395 obj.color[0] = 0.543; obj.color[1] = 0.270; obj.color[2] = 0.074; //1 0 0 Red object 00396 obj.type = TREE; 00397 break; 00398 case DS: 00399 itsVP->load3DSObject(obj.object, "./tests/spaceship.3ds"); 00400 obj.object.scale = 0.01; 00401 obj.texture = ViewPort::OTHER; 00402 obj.texturePtr = new Texture("./etc/textures/spaceshiptexture.ppm"); 00403 obj.geom = dCreateBox(spaceToAdd, objSize[0], objSize[1], objSize[2]); 00404 dGeomSetBody(obj.geom, 0); 00405 dGeomSetPosition(obj.geom, initPos[0], initPos[1], initPos[2]); 00406 obj.color[0] = 1.0; obj.color[1] = 1.0; obj.color[2] = 1.0; //1 0 0 Red object 00407 obj.type = DS; 00408 break; 00409 case TOBJ: 00410 sprintf(obj.object.name, "Textured Object"); 00411 obj.object.vertices_qty = 8; 00412 obj.object.vertex.resize(8); 00413 obj.object.vertex[0] = ViewPort::vertex_type(0, 0, objSize[2]); //, // vertex v0 00414 obj.object.vertex[1] = ViewPort::vertex_type( objSize[0], 0, objSize[2]); // vertex v1 00415 obj.object.vertex[2] = ViewPort::vertex_type( objSize[0], 0, 0); // vertex v2 00416 obj.object.vertex[3] = ViewPort::vertex_type( 0, 0, 0); // vertex v3 00417 00418 obj.object.vertex[4] = ViewPort::vertex_type( 0, objSize[1], objSize[2]); // vertex v4 00419 obj.object.vertex[5] = ViewPort::vertex_type( objSize[0], objSize[1], objSize[2]); // vertex v5 00420 obj.object.vertex[6] = ViewPort::vertex_type( objSize[0], objSize[1], 0); // vertex v6 00421 obj.object.vertex[7] = ViewPort::vertex_type( 0, objSize[1], 0); // vertex v7 00422 00423 00424 obj.object.polygons_qty = 12; 00425 obj.object.polygon.resize(12); 00426 obj.object.polygon[0] = ViewPort::polygon_type(0, 1, 4); // polygon v0,v1,v4 00427 obj.object.polygon[1] = ViewPort::polygon_type(1, 5, 4); // polygon v1,v5,v4 00428 obj.object.polygon[2] = ViewPort::polygon_type(1, 2, 5); // polygon v1,v2,v5 00429 obj.object.polygon[3] = ViewPort::polygon_type(2, 6, 5); // polygon v2,v6,v5 00430 obj.object.polygon[4] = ViewPort::polygon_type(2, 3, 6); // polygon v2,v3,v6 00431 obj.object.polygon[5] = ViewPort::polygon_type(3, 7, 6); // polygon v3,v7,v6 00432 obj.object.polygon[6] = ViewPort::polygon_type(3, 0, 7); // polygon v3,v0,v7 00433 obj.object.polygon[7] = ViewPort::polygon_type(0, 4, 7); // polygon v0,v4,v7 00434 obj.object.polygon[8] = ViewPort::polygon_type(4, 5, 7); // polygon v4,v5,v7 00435 obj.object.polygon[9] = ViewPort::polygon_type(5, 6, 7); // polygon v5,v6,v7 00436 obj.object.polygon[10] = ViewPort::polygon_type(3, 2, 0); // polygon v3,v2,v0 00437 obj.object.polygon[11] = ViewPort::polygon_type(2, 1, 0); // polygon v2,v1,v0 00438 00439 obj.object.mapcoord.resize(8); 00440 obj.object.mapcoord[0] = ViewPort::mapcoord_type(0.0, 0.0); // mapping coordinates for vertex v0 00441 obj.object.mapcoord[1] = ViewPort::mapcoord_type(1.0, 0.0); // mapping coordinates for vertex v1 00442 obj.object.mapcoord[2] = ViewPort::mapcoord_type(1.0, 1.0); // mapping coordinates for vertex v2 00443 obj.object.mapcoord[3] = ViewPort::mapcoord_type(0.0, 1.0); // mapping coordinates for vertex v3 00444 obj.object.mapcoord[4] = ViewPort::mapcoord_type(0.0, 0.0); // mapping coordinates for vertex v4 00445 obj.object.mapcoord[5] = ViewPort::mapcoord_type(0.0, 1.0); // mapping coordinates for vertex v5 00446 obj.object.mapcoord[6] = ViewPort::mapcoord_type(1.0, 1.0); // mapping coordinates for vertex v6 00447 obj.object.mapcoord[7] = ViewPort::mapcoord_type(0.0, 1.0); // mapping coordinates for vertex v7 00448 00449 00450 obj.object.scale = 1; 00451 if (texture) 00452 { 00453 obj.texture = ViewPort::OTHER; 00454 obj.texturePtr = new Texture(texture); 00455 } 00456 obj.geom = dCreateBox(spaceToAdd, objSize[0], objSize[1], objSize[2]); 00457 dGeomSetBody(obj.geom, 0); 00458 dGeomSetPosition(obj.geom, initPos[0], initPos[1], initPos[2]); 00459 obj.color[0] = 256; obj.color[1] = 256; obj.color[2] = 256; 00460 obj.type = DS; 00461 break; 00462 00463 00464 default: 00465 LINFO("Unknown object"); 00466 break; 00467 } 00468 itsObjects.push_back(obj); 00469 00470 00471 } 00472 00473 00474 00475 void IRobotSim::drawWorld() 00476 { 00477 00478 for(uint i=0; i<itsObjects.size(); i++) 00479 { 00480 Object obj = itsObjects[i]; 00481 00482 itsVP->dsSetColor(obj.color[0],obj.color[1],obj.color[2]); 00483 00484 itsVP->dsSetTexture(obj.texture, obj.texturePtr); 00485 00486 const dReal *bodyPos = dGeomGetPosition(obj.geom); 00487 const dReal *bodyRot = dGeomGetRotation(obj.geom); 00488 00489 switch(obj.type) 00490 { 00491 case BOX: 00492 dReal size[3]; 00493 dGeomBoxGetLengths(obj.geom,size); 00494 itsVP->dsDrawBox(bodyPos, bodyRot, size); 00495 break; 00496 case TREE: 00497 dReal r, length; 00498 dGeomCCylinderGetParams(obj.geom,&r,&length); 00499 00500 //Move the cylinder down by the r since its a capted cylinder 00501 //The cap cylinder is used wince its is more stable 00502 dReal pos[3]; 00503 pos[0] = bodyPos[0]; 00504 pos[1] = bodyPos[1]; 00505 pos[2] = bodyPos[2] - r; 00506 00507 itsVP->dsDrawCylinder(pos, bodyRot, length, r); 00508 00509 //Draw the top of the tree 00510 pos[2] = bodyPos[2] + length/2; 00511 00512 itsVP->dsSetTexture(ViewPort::TREE); 00513 itsVP->dsSetColor(0,1,0); 00514 itsVP->dsDrawSphere (pos, 00515 dBodyGetRotation(obj.body),r*4); 00516 00517 break; 00518 case DS: 00519 case TOBJ: 00520 itsVP->dsDraw3DSObject(bodyPos, bodyRot, obj.object); 00521 break; 00522 00523 default: 00524 break; 00525 } 00526 } 00527 } 00528 00529 void IRobotSim::handleWinEvents(XEvent& event) 00530 { 00531 } 00532 00533 void IRobotSim::updateSensors() 00534 { 00535 00536 //GPS sensor update 00537 const dReal *pos = dBodyGetPosition(itsRobotBody); 00538 const dReal *R = dBodyGetRotation(itsRobotBody); 00539 00540 itsXPos = pos[0]; 00541 itsYPos = pos[1]; 00542 itsOri = atan2(R[4], R[0]); //greek Y 00543 if (itsOri < 0) itsOri += M_PI*2; 00544 00545 00546 00547 //Encoder sensors 00548 //itsRoll = atan2(R[9], R[10]) + M_PI/2; //phi correct for initial rotation 00549 // itsPitch = asin(-R[8]); //theta 00550 // itsYaw = atan2(R[4], R[0]); 00551 // const dReal *rightR = dBodyGetRotation(itsRightWheelBody); 00552 // //const dReal *leftR = dBodyGetRotation(itsLeftWheelBody); 00553 // 00554 // int rightWheelAng = (int)((asin(-rightR[8]) + M_PI/2)*180/M_PI); 00555 // //int leftWheelAng = (int)((asin(-leftR[8]) + M_PI/2)*180/M_PI); 00556 // 00557 // int tick; 00558 // if (itsPrevRightWheelAng > rightWheelAng) 00559 // tick = 1; 00560 // else 00561 // tick = 0; 00562 // LINFO("Ang %i %i %i", rightWheelAng*(tick*-1) + tick*+180, itsPrevRightWheelAng - rightWheelAng, tick); 00563 // 00564 // itsPrevRightWheelAng = rightWheelAng; 00565 00566 // LINFO("(%f,%f) Depth %f, roll %f pitch %f yaw %f", 00567 // itsXPos, itsYPos, itsDepth, 00568 // itsRoll, itsPitch, itsYaw); 00569 00570 } 00571 00572 void IRobotSim::simLoop() 00573 { 00574 00575 //Move the robot 00576 dJointSetHinge2Param (itsRightWheelJoint,dParamVel2,itsRightWheelSpeed); 00577 dJointSetHinge2Param (itsRightWheelJoint,dParamFMax2,0.5); 00578 00579 dJointSetHinge2Param (itsLeftWheelJoint,dParamVel2,itsLeftWheelSpeed); 00580 dJointSetHinge2Param (itsLeftWheelJoint,dParamFMax2,0.5); 00581 00582 //update the sensors 00583 updateSensors(); 00584 00585 dSpaceCollide (space,this,&nearCallback); //check for collisions 00586 00587 dWorldStep(world,0.1); 00588 00589 dJointGroupEmpty (contactgroup); //delete the contact joints 00590 00591 if (itsShowWorld) 00592 { 00593 itsWorldDisp->drawImage(flipVertic(getFrame(0))); 00594 } 00595 } 00596 00597 00598 Image<PixRGB<byte> > IRobotSim::getFrame(int camera) 00599 { 00600 const dReal *bodyPos = dBodyGetPosition(itsRobotBody); 00601 const dReal *bodyR = dBodyGetRotation(itsRobotBody); 00602 00603 double cam_xyz[3], cam_hpr[3] = {0.0,0.0,0.0}; 00604 00605 switch (camera) 00606 { 00607 case 0: //world camera 00608 cam_xyz[0] = 0; 00609 cam_xyz[1] = 0; 00610 cam_xyz[2] = 40; 00611 00612 cam_hpr[0] = 90.0; 00613 cam_hpr[1] = -90.0; 00614 cam_hpr[2] = 0.0; 00615 00616 break; 00617 case 1: 00618 cam_xyz[0] = bodyPos[0]; 00619 cam_xyz[1] = bodyPos[1]; 00620 cam_xyz[2] = bodyPos[2] + 1; 00621 00622 cam_hpr[0] = (atan2(bodyR[4], bodyR[0])*180/M_PI) + 180; //yaw 00623 00624 break; 00625 case 2: 00626 cam_xyz[0] = bodyPos[0]; 00627 cam_xyz[1] = bodyPos[1]; 00628 cam_xyz[2] = bodyPos[2]; 00629 00630 cam_hpr[0] = (atan2(bodyR[4], bodyR[0])*180/M_PI) + 90; //yaw 00631 cam_hpr[1] = -90; //yaw 00632 00633 00634 break; 00635 } 00636 pthread_mutex_lock(&itsDispLock); 00637 if (camera != -1) 00638 itsVP->dsSetViewpoint (cam_xyz,cam_hpr); 00639 itsVP->initFrame(); 00640 drawRobot(); 00641 drawWorld(); 00642 itsVP->updateFrame(); 00643 pthread_mutex_unlock(&itsDispLock); 00644 00645 00646 return itsVP->getFrame(); 00647 00648 } 00649 00650 void IRobotSim::getSensors(float &xPos, float &yPos, float &ori) 00651 { 00652 xPos = itsXPos; 00653 yPos = itsYPos; 00654 ori = itsOri; 00655 00656 if (false) 00657 { 00658 //Add some random gauss noise to the sensor 00659 int idum = getIdum(); 00660 xPos += gasdev(idum)*0.5; 00661 yPos += gasdev(idum)*0.5; 00662 ori += gasdev(idum)*0.2; 00663 } 00664 } 00665 00666 void IRobotSim::setMotors(double rightSpeed, double leftSpeed) 00667 { 00668 itsRightWheelSpeed = rightSpeed; 00669 itsLeftWheelSpeed = leftSpeed; 00670 } 00671 00672 // ###################################################################### 00673 /* So things look consistent in everyone's emacs... */ 00674 /* Local Variables: */ 00675 /* indent-tabs-mode: nil */ 00676 /* End: */