00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <ros/ros.h>
00014 #include <uwsim/SimulatorConfig.h>
00015 #include <uwsim/UWSimUtils.h>
00016 #include <osg/Material>
00017 #include <osg/ShapeDrawable>
00018 #include <osg/Shape>
00019 #include <osg/Geode>
00020 #include <osg/Switch>
00021 #include <osg/MatrixTransform>
00022 #include <osgDB/ReadFile>
00023
00024 #if OSG_VERSION_MAJOR>=3
00025 #include <osgDB/Options>
00026 #endif
00027
00028
00029
00030
00031 findNodeVisitor::findNodeVisitor() :
00032 osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName()
00033 {
00034 }
00035
00036
00037
00038
00039 findNodeVisitor::findNodeVisitor(const std::string &searchName) :
00040 osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), searchForName(searchName)
00041 {
00042 }
00043
00044
00045
00046
00047 void findNodeVisitor::apply(osg::Node &searchNode)
00048 {
00049
00050 if (searchNode.getName() == searchForName)
00051 {
00052 foundNodeList.push_back(&searchNode);
00053 }
00054 traverse(searchNode);
00055 }
00056
00057
00058 void findNodeVisitor::setNameToFind(const std::string &searchName)
00059 {
00060 searchForName = searchName;
00061 foundNodeList.clear();
00062 }
00063
00064 osg::Node* findNodeVisitor::getFirst()
00065 {
00066 if (foundNodeList.size() == 0)
00067 return NULL;
00068 else
00069 return foundNodeList[0];
00070 }
00071
00072 findRoutedNode::findRoutedNode() :
00073 nodeVisitor()
00074 {
00075 }
00076
00077 findRoutedNode::findRoutedNode(const std::string &searchName) :
00078 nodeVisitor(), searchRoute(searchName)
00079 {
00080 }
00081
00082 void findRoutedNode::setNameToFind(const std::string &searchName)
00083 {
00084 searchRoute = searchName;
00085 rootList.clear();
00086 }
00087
00088 void findRoutedNode::find(osg::ref_ptr<osg::Node> searchNode)
00089 {
00090 unsigned int pos = 0;
00091 rootList.clear();
00092 rootList.push_back(searchNode);
00093 nodeListType auxList, auxList2;
00094
00095 while ((pos = searchRoute.find("/")) < searchRoute.size())
00096 {
00097 for (unsigned int i = 0; i < rootList.size(); i++)
00098 {
00099 nodeVisitor.setNameToFind(searchRoute.substr(0, pos));
00100 rootList[i]->accept(nodeVisitor);
00101 auxList2 = nodeVisitor.getNodeList();
00102 auxList.insert(auxList.end(), auxList2.begin(), auxList2.end());
00103 }
00104 searchRoute.erase(0, pos + 1);
00105 rootList = auxList;
00106 auxList.clear();
00107 }
00108 for (unsigned int i = 0; i < rootList.size(); i++)
00109 {
00110 nodeVisitor.setNameToFind(searchRoute);
00111 rootList[i]->accept(nodeVisitor);
00112 auxList2 = nodeVisitor.getNodeList();
00113 auxList.insert(auxList.end(), auxList2.begin(), auxList2.end());
00114 }
00115 rootList = auxList;
00116 }
00117
00118 osg::Node* findRoutedNode::getFirst()
00119 {
00120 if (rootList.size() == 0)
00121 return NULL;
00122 else
00123 return rootList[0];
00124 }
00125
00126 osg::Node * findRN(std::string target, osg::Group * root)
00127 {
00128 findRoutedNode findRN(target);
00129 findRN.find(root);
00130 return findRN.getFirst();
00131 }
00132
00133
00134 osg::Node* UWSimGeometry::createSwitchableFrame(double radius, double length, unsigned int mask)
00135 {
00136 osg::Switch *axis = new osg::Switch();
00137 axis->setNewChildDefaultValue(false);
00138 axis->setName("switch_frames");
00139 axis->addChild(UWSimGeometry::createFrame());
00140 axis->setNodeMask(mask);
00141 return axis;
00142 }
00143
00144 osg::Node* UWSimGeometry::createFrame(double radius, double length)
00145 {
00146 osg::Matrix linkBaseMatrix;
00147 linkBaseMatrix.makeIdentity();
00148 osg::MatrixTransform *linkBaseTransform = new osg::MatrixTransform(linkBaseMatrix);
00149
00150
00151 osg::Matrix XBase;
00152 XBase.makeIdentity();
00153 XBase.preMultRotate(osg::Quat(M_PI_2, osg::Vec3d(0, 1, 0)));
00154 XBase.preMultTranslate(osg::Vec3d(0, 0, length / 2));
00155 osg::MatrixTransform *XBaseTransform = new osg::MatrixTransform(XBase);
00156 linkBaseTransform->addChild(XBaseTransform);
00157
00158
00159 osg::Node * Xcylinder = UWSimGeometry::createOSGCylinder(radius, length);
00160 osg::StateSet * Xstateset = new osg::StateSet();
00161 osg::Material * Xmaterial = new osg::Material();
00162 Xmaterial->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 0, 0, 0));
00163 Xstateset->setAttribute(Xmaterial);
00164 Xcylinder->setStateSet(Xstateset);
00165 XBaseTransform->addChild(Xcylinder);
00166
00167
00168 osg::Matrix YBase;
00169 YBase.preMultRotate(osg::Quat(M_PI_2, osg::Vec3d(1, 0, 0)));
00170 YBase.preMultTranslate(osg::Vec3d(0, 0, -length / 2));
00171 osg::MatrixTransform *YBaseTransform = new osg::MatrixTransform(YBase);
00172 linkBaseTransform->addChild(YBaseTransform);
00173
00174
00175 osg::Node *Ycylinder = UWSimGeometry::createOSGCylinder(radius, length);
00176 osg::StateSet * Ystateset = new osg::StateSet();
00177 osg::Material * Ymaterial = new osg::Material();
00178 Ymaterial->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 1, 0, 0));
00179 Ystateset->setAttribute(Ymaterial);
00180 Ycylinder->setStateSet(Ystateset);
00181 YBaseTransform->addChild(Ycylinder);
00182
00183
00184 osg::Matrix ZBase;
00185 ZBase.makeIdentity();
00186 ZBase.preMultRotate(osg::Quat(M_PI_2, osg::Vec3d(0, 0, 1)));
00187 ZBase.preMultTranslate(osg::Vec3d(0, 0, length / 2));
00188 osg::MatrixTransform *ZBaseTransform = new osg::MatrixTransform(ZBase);
00189 linkBaseTransform->addChild(ZBaseTransform);
00190
00191
00192 osg::Node * Zcylinder = UWSimGeometry::createOSGCylinder(radius, length);
00193 osg::StateSet * Zstateset = new osg::StateSet();
00194 osg::Material * Zmaterial = new osg::Material();
00195 Zmaterial->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 1, 0));
00196 Zstateset->setAttribute(Zmaterial);
00197 Zcylinder->setStateSet(Zstateset);
00198 ZBaseTransform->addChild(Zcylinder);
00199
00200 return linkBaseTransform;
00201 }
00202
00203 osg::Node * UWSimGeometry::createOSGBox(osg::Vec3 size)
00204 {
00205 osg::Box *box = new osg::Box();
00206
00207 box->setHalfLengths(size / 2);
00208
00209 osg::ShapeDrawable *shape = new osg::ShapeDrawable(box);
00210 osg::Geode *geode = new osg::Geode();
00211 geode->addDrawable(shape);
00212
00213 osg::Node* node = new osg::Group();
00214 node->asGroup()->addChild(geode);
00215
00216 return node;
00217 }
00218
00219 osg::Node* UWSimGeometry::createOSGCylinder(double radius, double height)
00220 {
00221 osg::Cylinder *cylinder = new osg::Cylinder();
00222
00223 cylinder->setRadius(radius);
00224 cylinder->setHeight(height);
00225
00226 osg::ShapeDrawable *shape = new osg::ShapeDrawable(cylinder);
00227 osg::Geode *geode = new osg::Geode();
00228 geode->addDrawable(shape);
00229
00230 osg::Node *node = new osg::Group();
00231 node->asGroup()->addChild(geode);
00232
00233 return node;
00234 }
00235
00236 osg::Node * UWSimGeometry::createOSGSphere(double radius)
00237 {
00238 osg::Sphere *sphere = new osg::Sphere();
00239
00240 sphere->setRadius(radius);
00241
00242 osg::ShapeDrawable *shape = new osg::ShapeDrawable(sphere);
00243 osg::Geode *geode = new osg::Geode();
00244 geode->addDrawable(shape);
00245
00246 osg::Node *node = new osg::Group();
00247 node->asGroup()->addChild(geode);
00248
00249 return node;
00250 }
00251
00252 osg::Node * UWSimGeometry::createLabel(std::string textToDraw,double charSize, int bb, osg::Vec4 color )
00253 {
00254
00255 osg::ref_ptr<osgText::Text> text = new osgText::Text;
00256 text->setFont( "fonts/arial.ttf" );
00257 text->setText(textToDraw);
00258 text->setAxisAlignment( osgText::TextBase::SCREEN );
00259 text->setDataVariance( osg::Object::DYNAMIC );
00260 text->setColor(color);
00261 text->setCharacterSize(charSize);
00262 if(bb)
00263 {
00264 text->setBoundingBoxColor(color);
00265 text->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT | osgText::Text::BOUNDINGBOX);
00266 }
00267 else
00268 text->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT);
00269
00270
00271 osg::ref_ptr<osg::Geode> geode = new osg::Geode;
00272 geode->addDrawable( text.get() );
00273 geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
00274 geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF );
00275
00276 geode->getOrCreateStateSet()->setAttributeAndModes(new osg::Program(), osg::StateAttribute::ON);
00277 return geode.release();
00278 }
00279
00280 osg::Node * UWSimGeometry::retrieveResource(std::string name)
00281 {
00282
00283 resource_retriever::Retriever r;
00284 resource_retriever::MemoryResource resource;
00285
00286 try
00287 {
00288 resource = r.get(name);
00289 }
00290 catch (resource_retriever::Exception& e)
00291 {
00292 return NULL;
00293 }
00294
00295
00296 std::stringstream buffer;
00297 buffer.write((char *)resource.data.get(), resource.size);
00298
00299
00300 std::string file_ext = osgDB::getFileExtension(name);
00301 #if OSG_VERSION_MAJOR>=3
00302 osg::ref_ptr<osgDB::Options> local_opt = new osgDB::Options;
00303 #endif
00304
00305
00306 osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension(file_ext);
00307 if (!rw)
00308 {
00309 std::cout << "Data file format " << file_ext << " not supported" << std::endl;
00310 return NULL;
00311 }
00312
00313
00314 #if OSG_VERSION_MAJOR>=3
00315 osgDB::ReaderWriter::ReadResult readResult = rw->readNode( buffer,local_opt.get());
00316 #else
00317 osgDB::ReaderWriter::ReadResult readResult = rw->readNode(buffer);
00318 #endif
00319 if (readResult.validNode())
00320 return readResult.takeNode();
00321 else
00322 std::cout << "Can't load file " << name << std::endl;
00323 return NULL;
00324
00325 }
00326
00327 osg::Node * UWSimGeometry::loadGeometry(boost::shared_ptr<Geometry> geom)
00328 {
00329 if (geom->type == 0)
00330 {
00331 osg::Node * node = retrieveResource(geom->file);
00332 if (node == NULL)
00333 {
00334
00335 const std::string SIMULATOR_DATA_PATH = std::string(getenv("HOME")) + "/.uwsim/data";
00336
00337 osgDB::Registry::instance()->getDataFilePathList().push_back(std::string(SIMULATOR_DATA_PATH));
00338 osgDB::Registry::instance()->getDataFilePathList().push_back(
00339 std::string(SIMULATOR_DATA_PATH) + std::string("/objects"));
00340 osgDB::Registry::instance()->getDataFilePathList().push_back(
00341 std::string(SIMULATOR_DATA_PATH) + std::string("/terrain"));
00342 osgDB::Registry::instance()->getDataFilePathList().push_back(
00343 std::string(UWSIM_ROOT_PATH) + std::string("/data/shaders"));
00344 node = osgDB::readNodeFile(geom->file);
00345
00346 if (node == NULL)
00347 {
00348 std::cerr << "Error retrieving file " << geom->file
00349 << " Check URDF file or set your data path with the --dataPath option." << std::endl;
00350 exit(0);
00351 }
00352 }
00353
00354 if (node->asGroup() == NULL)
00355 {
00356 osg::Node * aux = node;
00357 node = new osg::Group();
00358 node->asGroup()->addChild(aux);
00359 }
00360 return node;
00361 }
00362 else if (geom->type == 1)
00363 {
00364 return UWSimGeometry::createOSGBox(osg::Vec3(geom->boxSize[0], geom->boxSize[1], geom->boxSize[2]));
00365 }
00366 else if (geom->type == 2)
00367 return UWSimGeometry::createOSGCylinder(geom->radius, geom->length);
00368 else if (geom->type == 3)
00369 return UWSimGeometry::createOSGSphere(geom->radius);
00370 else if (geom->type == 4)
00371 return new osg::Group();
00372 std::cerr << "Unknown geometry type. " << std::endl;
00373 exit(0);
00374 return NULL;
00375 }
00376
00377 getWorldCoordOfNodeVisitor::getWorldCoordOfNodeVisitor() :
00378 osg::NodeVisitor(NodeVisitor::TRAVERSE_PARENTS), done(false)
00379 {
00380 wcMatrix.reset(new osg::Matrixd());
00381 }
00382
00383 void getWorldCoordOfNodeVisitor::apply(osg::Node &node)
00384 {
00385 if (!done)
00386 {
00387 if (0 == node.getNumParents())
00388 {
00389 wcMatrix->set(osg::computeLocalToWorld(this->getNodePath()));
00390 done = true;
00391 }
00392 traverse(node);
00393 }
00394 }
00395
00396 boost::shared_ptr<osg::Matrix> getWorldCoordOfNodeVisitor::giveUpDaMat()
00397 {
00398 return wcMatrix;
00399 }
00400
00401 boost::shared_ptr<osg::Matrix> getWorldCoords(osg::Node* node)
00402 {
00403 osg::ref_ptr<getWorldCoordOfNodeVisitor> ncv = new getWorldCoordOfNodeVisitor();
00404 if (node && ncv)
00405 {
00406 node->accept(*ncv);
00407 return ncv->giveUpDaMat();
00408 }
00409 else
00410 {
00411 return boost::shared_ptr<osg::Matrix>();
00412 }
00413 }
00414
00415
00416
00417
00418 #include <osg/ComputeBoundsVisitor>
00419 #include "uwsim/SimulatedIAUV.h"
00420
00421 DynamicHF::DynamicHF(osg::HeightField* height, boost::shared_ptr<osg::Matrix> mat, std::vector<boost::shared_ptr<AbstractDredgeTool> > tools)
00422 {
00423 dredgeTools=tools;
00424 heightField=height;
00425 objectMat=mat;
00426 mat->preMultRotate(heightField->getRotation());
00427 }
00428
00429
00430 void DynamicHF::update( osg::NodeVisitor*,osg::Drawable* drawable )
00431 {
00432
00433 for(unsigned int i=0;i<dredgeTools.size();i++)
00434 {
00435 boost::shared_ptr<osg::Matrix> dredgeToolmat=dredgeTools[i]->getDredgePosition();
00436
00437 int modified=0;
00438 int nparticles=0;
00439
00440 for (int r = 0; r < heightField->getNumRows(); r++)
00441 {
00442 for (int c = 0; c < heightField->getNumColumns(); c++)
00443 {
00444
00445 if( ( dredgeToolmat->getTrans() - (objectMat->getTrans() + (heightField->getRotation().inverse() *heightField->getOrigin()) +
00446 osg::Vec3(c*heightField->getXInterval(),r*heightField->getYInterval(),heightField->getHeight(c,r)))
00447 ).length2()< 0.01)
00448 {
00449 heightField->setHeight(c, r,heightField->getHeight(c,r)-0.01);
00450 modified=1;
00451 nparticles++;
00452 }
00453 }
00454 }
00455
00456 if(modified)
00457 {
00458 drawable->dirtyDisplayList();
00459 drawable->dirtyBound();
00460 }
00461
00462 dredgeTools[i]->dredgedParticles(nparticles);
00463
00464 }
00465 }
00466
00467
00468 osg::Node* createHeightField(osg::ref_ptr<osg::Node> object, std::string texFile, double percent, const std::vector<boost::shared_ptr<SimulatedIAUV> > vehicles)
00469 {
00470 osg::ComputeBoundsVisitor cbv;
00471 object->accept(cbv);
00472 osg::BoundingBox box = cbv.getBoundingBox();
00473
00474 boost::shared_ptr<osg::Matrix> mat=getWorldCoords( object);
00475
00476 box._min= mat->getRotate() * box._min;
00477 box._max= mat->getRotate() * box._max;
00478
00479
00480
00481
00482
00483 float resX=0.01 + fmod((double)abs(box.xMax()-box.xMin()),0.01) / (double)floor(abs(box.xMax()-box.xMin())/0.01);
00484 float resY=0.01 + fmod((double)abs(box.yMax()-box.yMin()),0.01) / (double)floor(abs(box.yMax()-box.yMin())/0.01);
00485
00486
00487
00488
00489 int addedElems = abs(box.zMax()-box.zMin())*percent / 0.01*3;
00490
00491
00492 osg::HeightField* heightField = new osg::HeightField();
00493 heightField->allocate(abs(box.xMax()-box.xMin())/(resX)+1+addedElems*2,abs(box.yMax()-box.yMin())/(resY)+1+addedElems*2);
00494 heightField->setOrigin(mat->getRotate().inverse() * osg::Vec3(min(box.xMin(),box.xMax())-addedElems*resX,min(box.yMin(),box.yMax())-addedElems*resY, min(box.zMin(),box.zMax())));
00495 heightField->setRotation(mat->getRotate().inverse());
00496 heightField->setXInterval(resX);
00497 heightField->setYInterval(resY);
00498 heightField->setSkirtHeight(0.01f);
00499
00500
00501
00502
00503
00504
00505 for (int r = 0; r < heightField->getNumRows(); r++)
00506 {
00507 for (int c = 0; c < heightField->getNumColumns(); c++)
00508 {
00509 heightField->setHeight(c, r, abs(box.zMax()-box.zMin())*percent );
00510
00511 if(r<addedElems)
00512 heightField->setHeight(c, r,min((double)heightField->getHeight(c,r), (1 - ( (addedElems-r)*(addedElems-r) / ((double)(addedElems)*(addedElems)))) * abs(box.zMax()-box.zMin())*percent) );
00513
00514 if(heightField->getNumRows()-r<addedElems)
00515 heightField->setHeight(c, r,min((double)heightField->getHeight(c,r),(1 - ( (addedElems-(heightField->getNumRows()-r))*(addedElems-(heightField->getNumRows()-r)) / ((double)(addedElems)*(addedElems)))) * abs(box.zMax()-box.zMin())*percent) );
00516
00517 if(c<addedElems)
00518 heightField->setHeight(c, r,min((double)heightField->getHeight(c,r), (1 - ( (addedElems-c)*(addedElems-c) / ((double)(addedElems)*(addedElems)))) * abs(box.zMax()-box.zMin())*percent) );
00519
00520 if(heightField->getNumColumns()-c<addedElems)
00521 heightField->setHeight(c, r,min((double)heightField->getHeight(c,r), (1 - ( (addedElems-(heightField->getNumColumns()-c))*(addedElems-(heightField->getNumColumns()-c)) / ((double)(addedElems)*(addedElems)))) * abs(box.zMax()-box.zMin())*percent) );
00522
00523 }
00524 }
00525
00526
00527 std::vector<boost::shared_ptr<AbstractDredgeTool> > dredgeTools;
00528 for(unsigned int i=0;i<vehicles.size();i++)
00529 {
00530 for(unsigned int j=0;j<vehicles[i]->devices->all.size();j++)
00531 {
00532 boost::shared_ptr<AbstractDredgeTool> dredgeTool = boost::dynamic_pointer_cast < AbstractDredgeTool > (vehicles[i]->devices->all[j]);
00533
00534 if(dredgeTool)
00535 dredgeTools.push_back(dredgeTool);
00536 }
00537 }
00538
00539
00540
00541 osg::Geode* geode = new osg::Geode();
00542 osg::ShapeDrawable* draw=new osg::ShapeDrawable(heightField);
00543 geode->addDrawable(draw);
00544 DynamicHF * dynamicHF=new DynamicHF(heightField,mat, dredgeTools );
00545 draw->setUpdateCallback( dynamicHF);
00546
00547
00548 osg::Texture2D* tex = new osg::Texture2D(osgDB::readImageFile(texFile));
00549 tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
00550 tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
00551 geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex);
00552
00553 return geode;
00554 }
00555