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
00030 #include <string>
00031 #include <algorithm>
00032
00033 #include <QStringList>
00034 #include <QSettings>
00035 #include <QPushButton>
00036 #include <Q3GroupBox>
00037 #include <QFile>
00038 #include <QDateTime>
00039 #include <QTextStream>
00040 #include <Inventor/sensors/SoIdleSensor.h>
00041
00042 #include "myRegistry.h"
00043 #include "matvecIO.h"
00044 #include "world.h"
00045 #include "worldElement.h"
00046 #include "mytools.h"
00047 #include "body.h"
00048 #include "robot.h"
00049 #include "humanHand.h"
00050 #include "contact.h"
00051 #include "contactSetting.h"
00052 #include "ivmgr.h"
00053 #include "dynamics.h"
00054 #include "grasp.h"
00055 #include "dynJoint.h"
00056 #include "ivmgr.h"
00057 #include "barrett.h"
00058 #include "matvec3D.h"
00059 #include "bBox.h"
00060 #include "collisionInterface.h"
00061 #include "tinyxml.h"
00062 #include "worldElementFactory.h"
00063
00064
00065
00066
00067 #ifdef PQP_COLLISION
00068 #include "PQPCollision.h"
00069 #endif
00070 #ifdef BULLET_COLLISION
00071 #include "Bullet/bulletCollision.h"
00072 #endif
00073 #ifdef GRASPIT_COLLISION
00074 #include "Graspit/graspitCollision.h"
00075 #endif
00076
00077
00078 #include "arch.h"
00079
00080 #ifdef USE_DMALLOC
00081 #include "dmalloc.h"
00082 #endif
00083
00084 FILE *errFP=NULL;
00085
00086
00087 #include "debug.h"
00088
00089
00090 #include "profiling.h"
00091 PROF_DECLARE(WORLD_FIND_CONTACTS);
00092 PROF_DECLARE(WORLD_COLLISION_REPORT);
00093 PROF_DECLARE(WORLD_NO_COLLISION);
00094 PROF_DECLARE(WORLD_GET_DIST);
00095 PROF_DECLARE(WORLD_POINT_TO_BODY_DISTANCE);
00096 PROF_DECLARE(WORLD_FIND_VIRTUAL_CONTACTS);
00097 PROF_DECLARE(WORLD_FIND_REGION);
00098 PROF_DECLARE(DYNAMICS);
00099
00100 #define MAXBODIES 256
00101 #define TIMER_MILLISECONDS 100.0
00102
00103 char graspitVersionStr[] = "GraspIt! version 2.1";
00104
00109 World::World(QObject *parent, const char *name, IVmgr *mgr) : QObject(parent,name)
00110 {
00111 myIVmgr = mgr;
00112
00113 numBodies = numGB = numRobots = numHands = 0;
00114 numSelectedBodyElements = numSelectedRobotElements = 0;
00115 numSelectedElements = 0;
00116 numSelectedBodies = 0;
00117 currentHand = NULL;
00118
00119 isTendonSelected = false;
00120 selectedTendon = NULL;
00121
00122 worldTime = 0.0;
00123 modified = false;
00124
00125 allCollisionsOFF = false;
00126 softContactsON = true;
00127
00128 cofTable=kcofTable=NULL;
00129
00130 readSettings();
00131
00132 #ifdef PQP_COLLISION
00133 mCollisionInterface = new PQPCollision();
00134 #endif
00135 #ifdef BULLET_COLLISION
00136 mCollisionInterface = new BulletCollision();
00137 #endif
00138 #ifdef GRASPIT_COLLISION
00139 mCollisionInterface = new GraspitCollision();
00140 #endif
00141
00142 IVRoot = new SoSeparator;
00143 IVRoot->ref();
00144
00145 idleSensor = NULL;
00146 dynamicsOn = false;
00147
00148
00149
00150 WorldElementFactory::registerBuiltinCreators();
00151 }
00152
00156 World::~World()
00157 {
00158 int i;
00159 DBGP("Deleting world");
00160
00161 saveSettings();
00162
00163 for (i=0;i<numMaterials;i++) {
00164 free(cofTable[i]);
00165 free(kcofTable[i]);
00166 }
00167 free(cofTable);
00168 free(kcofTable);
00169
00170 for (i=numRobots-1;i>=0;i--)
00171 destroyElement(robotVec[i]);
00172
00173 for (i=numBodies-1;i>=0;i--) {
00174 DBGP("Deleting body: " << i <<" "<<bodyVec[i]->getName().latin1());
00175 destroyElement(bodyVec[i]);
00176 }
00177
00178 if (idleSensor) delete idleSensor;
00179 delete mCollisionInterface;
00180 IVRoot->unref();
00181 }
00182
00185 int
00186 World::getMaterialIdx(const QString &matName) const
00187 {
00188 for (int i=0; i<numMaterials; i++) {
00189 if (materialNames[i] == matName) return i;
00190 }
00191 return -1;
00192 }
00193
00194
00212 void
00213 World::setDefaults()
00214 {
00215 int i;
00216 dynamicsTimeStep = 0.0025;
00217
00218 if (cofTable) {
00219 for (i=0;i<numMaterials;i++) {
00220 free(cofTable[i]);
00221 free(kcofTable[i]);
00222 }
00223 free(cofTable);
00224 free(kcofTable);
00225 }
00226
00227 numMaterials = 7;
00228 cofTable = (double **)malloc(numMaterials*sizeof(double *));
00229 kcofTable = (double **)malloc(numMaterials*sizeof(double *));
00230 for (i=0;i<numMaterials;i++) {
00231 cofTable[i] = (double *)malloc(numMaterials*sizeof(double));
00232 kcofTable[i] = (double *)malloc(numMaterials*sizeof(double));
00233 }
00234
00235 materialNames.clear();
00236 materialNames.push_back("frictionless");
00237 materialNames.push_back("glass");
00238 materialNames.push_back("metal");
00239 materialNames.push_back("plastic");
00240 materialNames.push_back("wood");
00241 materialNames.push_back("rubber");
00242 materialNames.push_back("stone");
00243
00244
00245 for (i=0;i<7;i++) {
00246 cofTable[0][i] = cofTable[i][0] = 0.0;
00247 kcofTable[0][i] = kcofTable[i][0] = 0.0;
00248 }
00249
00250
00251 cofTable[6][6] = 0.7;
00252 cofTable[6][1] = cofTable[1][6] = 0.3;
00253 cofTable[6][2] = cofTable[2][6] = 0.4;
00254 cofTable[6][3] = cofTable[3][6] = 0.4;
00255 cofTable[6][4] = cofTable[4][6] = 0.6;
00256 cofTable[6][5] = cofTable[5][6] = 1.5;
00257 kcofTable[6][6] = 0.6;
00258 kcofTable[6][1] = kcofTable[1][6] = 0.2;
00259 kcofTable[6][2] = kcofTable[2][6] = 0.3;
00260 kcofTable[6][3] = kcofTable[3][6] = 0.3;
00261 kcofTable[6][4] = kcofTable[4][6] = 0.5;
00262 kcofTable[6][5] = kcofTable[5][6] = 1.4;
00263
00264
00265 cofTable[1][1] = 0.2;
00266 cofTable[1][2] = cofTable[2][1] = 0.2;
00267 cofTable[1][3] = cofTable[3][1] = 0.2;
00268 cofTable[1][4] = cofTable[4][1] = 0.3;
00269 cofTable[1][5] = cofTable[5][1] = 1.0;
00270 kcofTable[1][1] = 0.1;
00271 kcofTable[1][2] = kcofTable[2][1] = 0.1;
00272 kcofTable[1][3] = kcofTable[3][1] = 0.1;
00273 kcofTable[1][4] = kcofTable[4][1] = 0.2;
00274 kcofTable[1][5] = kcofTable[5][1] = 0.9;
00275
00276
00277 cofTable[2][2] = 0.2;
00278 cofTable[2][3] = cofTable[3][2] = 0.2;
00279 cofTable[2][4] = cofTable[4][2] = 0.3;
00280 cofTable[2][5] = cofTable[5][2] = 1.0;
00281 kcofTable[2][2] = 0.1;
00282 kcofTable[2][3] = kcofTable[3][2] = 0.1;
00283 kcofTable[2][4] = kcofTable[4][2] = 0.2;
00284 kcofTable[2][5] = kcofTable[5][2] = 0.9;
00285
00286
00287 cofTable[3][3] = 0.3;
00288 cofTable[3][4] = cofTable[4][3] = 0.4;
00289 cofTable[3][5] = cofTable[5][3] = 1.0;
00290 kcofTable[3][3] = 0.2;
00291 kcofTable[3][4] = kcofTable[4][3] = 0.3;
00292 kcofTable[3][5] = kcofTable[5][3] = 0.9;
00293
00294
00295 cofTable[4][4] = 0.4;
00296 cofTable[4][5] = cofTable[5][4] = 1.0;
00297 kcofTable[4][4] = 0.3;
00298 kcofTable[4][5] = kcofTable[5][4] = 0.9;
00299
00300
00301 cofTable[5][5] = 2.0;
00302 kcofTable[5][5] = 1.9;
00303 }
00304
00310 void
00311 World::readSettings()
00312 {
00313 QSettings settings;
00314 int i,j,newNumMaterials;
00315 double **newcofTable,**newkcofTable;
00316 std::vector<QString> newMaterialNames;
00317
00318 setDefaults();
00319
00320 settings.insertSearchPath(QSettings::Windows, COMPANY_KEY);
00321
00322 dynamicsTimeStep = settings.readDoubleEntry(APP_KEY + QString("World/dynamicsTimeStep"),dynamicsTimeStep);
00323
00324 newNumMaterials = settings.readNumEntry(APP_KEY + QString("World/numMaterials"),numMaterials);
00325
00326 newcofTable = (double **)malloc(newNumMaterials*sizeof(double *));
00327 newkcofTable = (double **)malloc(newNumMaterials*sizeof(double *));
00328 newMaterialNames.resize(newNumMaterials, QString::null);
00329
00330 for (i=0;i<newNumMaterials;i++) {
00331 newcofTable[i] = (double *)malloc(newNumMaterials*sizeof(double));
00332 newkcofTable[i] = (double *)malloc(newNumMaterials*sizeof(double));
00333 }
00334
00335 for (i=0;i<numMaterials;i++) {
00336 newMaterialNames[i] = settings.readEntry(APP_KEY + QString("World/material%1").arg(i),materialNames[i]);
00337
00338 for (j=i;j<numMaterials;j++) {
00339 newcofTable[i][j] = newcofTable[j][i] =
00340 settings.readDoubleEntry(APP_KEY + QString("World/cof%1%2").arg(i).arg(j),cofTable[i][j]);
00341
00342 newkcofTable[i][j] = newkcofTable[j][i] =
00343 settings.readDoubleEntry(APP_KEY + QString("World/kcof%1%2").arg(i).arg(j),kcofTable[i][j]);
00344 }
00345
00346 for (;j<newNumMaterials;j++) {
00347 newcofTable[i][j] = newcofTable[j][i] =
00348 settings.readDoubleEntry(APP_KEY + QString("World/cof%1%2").arg(i).arg(j));
00349
00350 newkcofTable[i][j] = newkcofTable[j][i] =
00351 settings.readDoubleEntry(APP_KEY + QString("World/kcof%1%2").arg(i).arg(j));
00352 }
00353 }
00354 for (;i<newNumMaterials;i++){
00355 newMaterialNames.push_back(settings.readEntry(APP_KEY + QString("World/material%1").arg(i)));
00356
00357 for (j=i;j<newNumMaterials;j++) {
00358 newcofTable[i][j] = newcofTable[j][i] =
00359 settings.readDoubleEntry(APP_KEY + QString("World/cof%1%2").arg(i).arg(j));
00360
00361 newkcofTable[i][j] = newkcofTable[j][i] =
00362 settings.readDoubleEntry(APP_KEY + QString("World/kcof%1%2").arg(i).arg(j));
00363 }
00364 }
00365
00366 for (i=0;i<numMaterials;i++) {
00367 free(cofTable[i]);
00368 free(kcofTable[i]);
00369 }
00370
00371 free(cofTable);
00372 free(kcofTable);
00373 materialNames = newMaterialNames;
00374 numMaterials = newNumMaterials;
00375 cofTable = newcofTable;
00376 kcofTable = newkcofTable;
00377 }
00378
00380 void
00381 World::saveSettings()
00382 {
00383 int i,j;
00384 QSettings settings;
00385 settings.insertSearchPath(QSettings::Windows, COMPANY_KEY);
00386
00387 settings.writeEntry(APP_KEY + QString("World/numMaterials"),numMaterials);
00388 for (i=0;i<numMaterials;i++) {
00389 settings.writeEntry(APP_KEY + QString("World/material%1").arg(i),materialNames[i]);
00390 for (j=i;j<numMaterials;j++) {
00391 settings.writeEntry(APP_KEY + QString("World/cof%1%2").arg(i).arg(j),cofTable[i][j]);
00392 settings.writeEntry(APP_KEY + QString("World/kcof%1%2").arg(i).arg(j),kcofTable[i][j]);
00393 }
00394 }
00395 }
00396
00403 void
00404 World::destroyElement(WorldElement *e, bool deleteElement)
00405 {
00406 std::vector<Body *>::iterator bp;
00407 std::vector<GraspableBody *>::iterator gp;
00408 std::vector<Robot *>::iterator rp;
00409 std::vector<Hand *>::iterator hp;
00410 DBGP("In remove element: " << e->className());
00411
00412 if (e->inherits("Body")) {
00413 DBGP("found a body");
00414 mCollisionInterface->removeBody( (Body*) e);
00415 for (bp=bodyVec.begin();bp!=bodyVec.end();bp++) {
00416 if (*bp == e) {
00417 bodyVec.erase(bp); numBodies--;
00418 DBGP("removed body "<<((Body *)e)->getName()<<" from world");
00419 break;
00420 }
00421 }
00422 for (gp=GBVec.begin();gp!=GBVec.end();gp++) {
00423 if (*gp == e) {
00424 GBVec.erase(gp); numGB--;
00425 for (hp=handVec.begin();hp!=handVec.end();hp++) {
00426 if ((*hp)->getGrasp()->getObject() == e) {
00427 if (numGB > 0)
00428 (*hp)->getGrasp()->setObject(GBVec[0]);
00429 else
00430 (*hp)->getGrasp()->setObject(NULL);
00431 }
00432 }
00433 DBGP("removed GB " << ((Body *)e)->getName()<<" from world");
00434 break;
00435 }
00436 }
00437 }
00438
00439 if (e->inherits("Robot")) {
00440 DBGP(" found a robot");
00441 for (hp=handVec.begin();hp!=handVec.end();hp++) {
00442 if (*hp == e) {
00443 handVec.erase(hp); numHands--;
00444 if (currentHand == e) {
00445 if (numHands > 0) currentHand = handVec[0];
00446 else currentHand = NULL;
00447 }
00448 DBGP("removed hand " << ((Robot *)e)->getName() << " from world");
00449 emit handRemoved();
00450 break;
00451 }
00452 }
00453 for (rp=robotVec.begin();rp!=robotVec.end();rp++) {
00454 if (*rp == e) {
00455 robotVec.erase(rp); numRobots--;
00456 DBGP("removed robot " << ((Robot *)e)->getName() << " from world");
00457 break;
00458 }
00459 }
00460 }
00461
00462 int idx = IVRoot->findChild(e->getIVRoot());
00463 if (deleteElement) delete e;
00464 else e->getIVRoot()->ref();
00465 if (idx > -1)
00466 IVRoot->removeChild(idx);
00467 if (!deleteElement) e->getIVRoot()->unrefNoDelete();
00468
00469 emit numElementsChanged();
00470 modified = true;
00471 }
00472
00478 int
00479 World::load(const QString &filename)
00480 {
00481 QString graspitRoot = getenv("GRASPIT");
00482 graspitRoot.replace("\\","/");
00483 if (graspitRoot.at(graspitRoot.size()-1)!='/') {
00484 graspitRoot += "/";
00485 }
00486
00487 TiXmlDocument doc(filename);
00488 if(doc.LoadFile()==false){
00489 QTWARNING("Could not open file " + filename);
00490 return FAILURE;
00491 }
00492 const TiXmlElement* root = doc.RootElement();
00493 if(root==NULL){
00494 QTWARNING("Empty XML");
00495 return FAILURE;
00496 }
00497 if (loadFromXml(root,graspitRoot) == FAILURE) {
00498 return FAILURE;
00499 }
00500 return SUCCESS;
00501 }
00502
00503 int
00504 World::loadFromXml(const TiXmlElement* root,QString rootPath)
00505 {
00506 const TiXmlElement* child = root->FirstChildElement();
00507 const TiXmlElement* xmlElement;
00508 QString buf, elementType, matStr, elementPath, elementName,mountFilename;
00509 Link *mountPiece;
00510 QString line;
00511 WorldElement *element;
00512 transf tr;
00513 int prevRobNum,chainNum,nextRobNum;
00514 bool badFile,cameraFound;
00515 while(child!=NULL){
00516 elementType = child->Value();
00517 if(elementType.isNull()){
00518 QTWARNING("Empty Element Type");
00519 }
00520 if (elementType == "obstacle") {
00521 xmlElement = findXmlElement(child, "filename");
00522 bool loadFromFile=false;
00523 if(xmlElement){
00524 elementName = xmlElement->GetText();
00525 elementPath = rootPath + elementName;
00526 elementPath = elementPath.stripWhiteSpace();
00527 DBGP("importing " << elementPath.latin1());
00528 element = importBody("Body",elementPath);
00529 if (!element) {
00530 QTWARNING("Could not open " + elementPath);
00531 return FAILURE;
00532 }
00533 loadFromFile = true;
00534 }
00535 xmlElement = findXmlElement(child, "body");
00536 if(loadFromFile){
00537 if(xmlElement) {
00538 QTWARNING("Contains both filename and body info: Load From File");
00539 }
00540 } else{
00541 if(!xmlElement){
00542 QTWARNING("Neither filename nor body info found");
00543 return FAILURE;
00544 }
00545 DBGP("importing obstacle from body info");
00546 element = importBodyFromXml("Body", xmlElement,rootPath);
00547 if (!element) {
00548 QTWARNING("Could not open file " + elementPath);
00549 return FAILURE;
00550 }
00551 }
00552 xmlElement = findXmlElement(child,"transform");
00553 if(xmlElement){
00554 if (getTransform(xmlElement,tr)==false) {
00555 QTWARNING("Obstacle transformation Error");
00556 return FAILURE;
00557 }
00558 element->setTran(tr);
00559 }
00560 }
00561 else if (elementType == "graspableBody") {
00562 xmlElement = findXmlElement(child, "filename");
00563 bool loadFromFile = false;
00564 if(xmlElement){
00565 elementName = xmlElement->GetText();
00566 elementPath = rootPath + elementName;
00567 elementPath = elementPath.stripWhiteSpace();
00568 DBGP("importing " << elementPath.latin1());
00569 element = importBody("GraspableBody",elementPath);
00570 if (!element) {
00571 QTWARNING("Could not open " + elementPath);
00572 return FAILURE;
00573 }
00574 loadFromFile = true;
00575 }
00576 xmlElement = findXmlElement(child, "body");
00577 if(loadFromFile){
00578 if(xmlElement) {
00579 QTWARNING("Contains both filename and body info: Load From File");
00580 }
00581 }
00582 else{
00583 if(!xmlElement){
00584 QTWARNING("Neither filename nor body info found");
00585 return FAILURE;
00586 }
00587 DBGP("importing graspable body from body info");
00588 element = importBodyFromXml("GraspableBody", xmlElement,rootPath);
00589 if (!element) {
00590 QTWARNING("Could not open " + elementPath);
00591 return FAILURE;
00592 }
00593 }
00594 xmlElement = findXmlElement(child,"transform");
00595 if(xmlElement){
00596 if (getTransform(xmlElement,tr)==false) {
00597 QTWARNING("GraspableBody transformation Error");
00598 return FAILURE;
00599 }
00600 element->setTran(tr);
00601 }
00602 }
00603 else if (elementType == "robot") {
00604 Robot *robot;
00605 xmlElement = findXmlElement(child, "filename");
00606 if(!xmlElement){
00607 QTWARNING("Robot filename not found");
00608 return FAILURE;
00609 }
00610 elementName = xmlElement->GetText();
00611 elementPath = rootPath + elementName;
00612 DBGP("importing " << elementPath.latin1());
00613 if ((robot = importRobot(elementPath))==NULL){
00614 QTWARNING("Could not open " + elementPath);
00615 return FAILURE;
00616 }
00617 element = robot;
00618 xmlElement = findXmlElement(child,"dofValues");
00619 if(xmlElement){
00620 QString dofValues = xmlElement->GetText();
00621 dofValues = dofValues.stripWhiteSpace().simplifyWhiteSpace();
00622 QTextStream lineStream(&dofValues,QIODevice::ReadOnly);
00623 robot->readDOFVals(lineStream);
00624 }
00625 xmlElement = findXmlElement(child,"transform");
00626 if(xmlElement){
00627 if (getTransform(xmlElement,tr)==false) {
00628 QTWARNING("Robot transformation Error");
00629 return FAILURE;
00630 }
00631 element->setTran(tr);
00632 }
00633 }
00634 else if (elementType == "connection") {
00635 if(!getInt(child, "parentRobot", prevRobNum)){
00636 QTWARNING("Failed to load Parent Robot Number");
00637 return FAILURE;
00638 }
00639 if(!getInt(child, "parentChain", chainNum)){
00640 QTWARNING("Failed to load Parent Robot's Chain Number");
00641 return FAILURE;
00642 }
00643 if(!getInt(child, "childRobot", nextRobNum)){
00644 QTWARNING("Failed to load Child Robot Number");
00645 return FAILURE;
00646 }
00647 if (prevRobNum < 0 || prevRobNum >= numRobots || nextRobNum < 0 ||
00648 nextRobNum >= numRobots || chainNum < 0 ||
00649 chainNum >= robotVec[prevRobNum]->getNumChains()) {
00650 badFile = true; break;
00651 }
00652 xmlElement = findXmlElement( child, "transform");
00653 if(xmlElement){
00654 if (!getTransform(xmlElement,tr)) {
00655 badFile = true;
00656 QTWARNING("Error reading connection transform"); break;
00657 }
00658 }
00659 DBGP("offset tran " << tr);
00660 xmlElement = findXmlElement(child, "mountFilename");
00661 if(xmlElement){
00662 mountFilename = xmlElement->GetText();
00663 if (!mountFilename.isEmpty()) {
00664 mountFilename = mountFilename.stripWhiteSpace();
00665 KinematicChain *prevChain= robotVec[prevRobNum]->getChain(chainNum);
00666 mountFilename = rootPath + mountFilename;
00667 DBGA("Mount filename: " << mountFilename.latin1());
00668 if ((mountPiece = robotVec[nextRobNum]->importMountPiece(mountFilename))) {
00669 addLink(mountPiece);
00670 toggleCollisions(false, prevChain->getLink(prevChain->getNumLinks()-1), mountPiece);
00671 toggleCollisions(false, mountPiece,robotVec[nextRobNum]->getBase());
00672 }
00673 mountFilename=(char *)NULL;
00674 }
00675 }
00676 robotVec[prevRobNum]->attachRobot(robotVec[nextRobNum],chainNum,tr);
00677 }
00678 else if (elementType == "camera" ) {
00679 double px, py, pz, q1, q2, q3, q4, fd;
00680 QStringList l;
00681 xmlElement = findXmlElement(child,"position");
00682 if(!xmlElement){
00683 QTWARNING("Camera Position not found");
00684 return FAILURE;
00685 }
00686 QString position = xmlElement->GetText();
00687 position = position.simplifyWhiteSpace().stripWhiteSpace();
00688 l = QStringList::split(' ', position);
00689 if(l.count()!=3){
00690 QTWARNING("Invalid camera position input");
00691 return FAILURE;
00692 }
00693 bool ok1,ok2,ok3, ok4;
00694 px = l[0].toDouble(&ok1);
00695 py = l[1].toDouble(&ok2);
00696 pz = l[2].toDouble(&ok3);
00697 if(!ok1 || !ok2 || !ok3){
00698 QTWARNING("Invalid camera position input");
00699 return FAILURE;
00700 }
00701 xmlElement = findXmlElement(child,"orientation");
00702 if(!xmlElement){
00703 QTWARNING("Camera orientation not found");
00704 return FAILURE;
00705 }
00706 QString orientation = xmlElement->GetText();
00707 position = orientation.simplifyWhiteSpace().stripWhiteSpace();
00708 l = QStringList::split(' ', orientation);
00709 if(l.count()!=4){
00710 QTWARNING("Invalid camera orientation input");
00711 return FAILURE;
00712 }
00713 q1 = l[0].toDouble(&ok1);
00714 q2 = l[1].toDouble(&ok2);
00715 q3 = l[2].toDouble(&ok3);
00716 q4 = l[3].toDouble(&ok4);
00717 if(!ok1 || !ok2 || !ok3 || !ok4){
00718 QTWARNING("Invalid camera position input");
00719 return FAILURE;
00720 }
00721 if(!getDouble(child, "focalDistance", fd)){
00722 QTWARNING("Failed to load focal distance");
00723 return FAILURE;
00724 }
00725 myIVmgr->setCamera(px, py, pz, q1, q2, q3, q4, fd);
00726 cameraFound = true;
00727 }
00728 else {
00729 QTWARNING(elementType + " is not a valid WorldElement type");
00730 return FAILURE;
00731 }
00732 child = child->NextSiblingElement();
00733 }
00734
00735 if (!cameraFound) {
00736 myIVmgr->getViewer()->viewAll();
00737 }
00738 findAllContacts();
00739 modified = false;
00740 resetDynamics();
00741 return SUCCESS;
00742 }
00743
00748 int
00749 World::save(const QString &filename)
00750 {
00751 QFile file(filename);
00752 int i,j,k,l;
00753
00754 if (!file.open(QIODevice::WriteOnly)) {
00755 QTWARNING("could not open " + filename + "for writing");
00756 return FAILURE;
00757 }
00758 QTextStream stream( &file );
00759 stream << "<?xml version=\"1.0\" ?>" <<endl;
00760 stream << "<world>" << endl;
00761 for (i=0;i<numBodies;i++) {
00762 if (bodyVec[i]->isA("Body")) {
00763 stream<<"\t<obstacle>"<<endl;
00764 if(bodyVec[i]->getFilename()=="unspecified"){
00765 stream<<"\t\t<body>"<<endl;
00766 if(bodyVec[i]->saveToXml(stream)==FAILURE){
00767 QTWARNING("Failed to save body info");
00768 return FAILURE;
00769 }
00770 stream<<"\t\t</body>"<<endl;
00771 }
00772 else
00773 stream<<"\t\t<filename>"<<bodyVec[i]->getFilename().latin1()<<"</filename>"<<endl;
00774 stream<<"\t\t<transform>" <<endl;
00775 stream<< "\t\t\t<fullTransform>"<< bodyVec[i]->getTran() << "</fullTransform>" << endl;
00776 stream<<"\t\t</transform>" <<endl;
00777 stream<<"\t</obstacle>"<<endl;
00778 }
00779 else if (bodyVec[i]->inherits("GraspableBody")) {
00780 stream<<"\t<graspableBody>"<<endl;
00781 if(bodyVec[i]->getFilename()=="unspecified"){
00782 stream<<"\t\t<body>"<<endl;
00783 if(bodyVec[i]->saveToXml(stream)==FAILURE){
00784 QTWARNING("Failed to save body info");
00785 return FAILURE;
00786 }
00787 stream<<"\t\t</body>"<<endl;
00788 }
00789 else
00790 stream<<"\t\t<filename>"<<bodyVec[i]->getFilename().latin1()<<"</filename>"<<endl;
00791 stream<<"\t\t<transform>" <<endl;
00792 stream<< "\t\t\t<fullTransform>"<< bodyVec[i]->getTran() << "</fullTransform>" << endl;
00793 stream<<"\t\t</transform>" <<endl;
00794 stream<<"\t</graspableBody>"<<endl;
00795 }
00796 }
00797
00798 for (i=0;i<numRobots;i++) {
00799 stream<<"\t<robot>"<<endl;
00800 stream<<"\t\t<filename>"<<robotVec[i]->getFilename().latin1()<<"</filename>"<<endl;
00801 stream<<"\t\t<dofValues>";
00802 robotVec[i]->writeDOFVals(stream);
00803 stream << "</dofValues>" << endl;
00804 stream<<"\t\t<transform>" <<endl;
00805 stream<< "\t\t\t<fullTransform>"<< robotVec[i]->getTran() << "</fullTransform>" << endl;
00806 stream<<"\t\t</transform>" <<endl;
00807 stream<<"\t</robot>"<<endl;
00808 }
00809
00810 for(i=0;i<numRobots;i++) {
00811 for (j=0;j<robotVec[i]->getNumChains();j++) {
00812 KinematicChain *chain = robotVec[i]->getChain(j);
00813 for (k=0;k<chain->getNumAttachedRobots();k++) {
00814 stream<<"\t<connection>"<<endl;
00815 stream<< "\t\t<parentRobot>" << i << "</parentRobot>" << endl;
00816 stream<< "\t\t<parentChain>" << j << "</parentChain>" << endl;
00817 for (l=0;l<numRobots;l++)
00818 if (chain->getAttachedRobot(k) == robotVec[l]) break;
00819 stream<< "\t\t<childRobot>" << l << "</childRobot>" << endl;
00820 if (chain->getAttachedRobot(k)->getMountPiece()) {
00821 stream<< "\t\t<mountFilename>" << chain->getAttachedRobot(k)->getMountPiece()->getFilename() << "</mountFilename>" << endl;
00822 }
00823 stream<<"\t\t<transform>" <<endl;
00824 stream<< "\t\t\t<fullTransform>"<< chain->getAttachedRobotOffset(k) << "</fullTransform>" << endl;
00825 stream<<"\t\t</transform>" <<endl;
00826 stream<<"\t</connection>"<<endl;
00827 }
00828 }
00829 }
00830 stream<<"\t<camera>"<<endl;
00831 float px, py, pz, q1, q2, q3, q4, fd;
00832 if (myIVmgr) {
00833 myIVmgr->getCamera(px, py, pz, q1, q2, q3, q4, fd);
00834 stream<<"\t\t<position>"<<px<<" "<<py<<" "<<pz<<"</position>"<<endl;
00835 stream<<"\t\t<orientation>"<<q1<<" "<<q2<<" "<<q3<<" "<<q4<<"</orientation>"<<endl;
00836 stream<<"\t\t<focalDistance>"<<fd<<"</focalDistance>"<<endl;
00837 }
00838 stream<<"\t</camera>"<<endl;
00839 stream<<"</world>"<<endl;
00840 file.close();
00841 modified = false;
00842 return SUCCESS;
00843 }
00844
00851 Body *
00852 World::importBody(QString bodyType,QString filename)
00853 {
00854 Body *newBody = (Body *) getWorldElementFactory().createElement(bodyType.toStdString(), this, NULL);
00855 if (!newBody) return NULL;
00856 if (newBody->load(filename)==FAILURE) return NULL;
00857 newBody->addToIvc();
00858 addBody(newBody);
00859 return newBody;
00860 }
00861
00867 Body *
00868 World::importBodyFromXml(QString bodyType, const TiXmlElement* child, QString rootPath)
00869 {
00870 Body *newBody = (Body *) getWorldElementFactory().createElement(bodyType.toStdString(), this, NULL);
00871 if (!newBody) return NULL;
00872 if (newBody->loadFromXml(child, rootPath)==FAILURE) return NULL;
00873 newBody->addIVMat();
00874 newBody->addToIvc();
00875 addBody(newBody);
00876 return newBody;
00877 }
00878
00885 void
00886 World::addBody(Body *newBody)
00887 {
00888 newBody->setDefaultViewingParameters();
00889 bodyVec.push_back(newBody);
00890 numBodies++;
00891 if (newBody->inherits("GraspableBody")) {
00892 GBVec.push_back((GraspableBody *)newBody);
00893 if (numGB == 0) {
00894 for (int i=0;i<numHands;i++) {
00895 handVec[i]->getGrasp()->setObject((GraspableBody *)newBody);
00896 }
00897 }
00898 numGB++;
00899 }
00900 IVRoot->addChild(newBody->getIVRoot());
00901 modified = true;
00902 emit numElementsChanged();
00903 }
00904
00909 void
00910 World::addLink(Link *newLink)
00911 {
00912 bodyVec.push_back(newLink);
00913 numBodies++;
00914 }
00915
00923 Robot *
00924 World::importRobot(QString filename)
00925 {
00926 TiXmlDocument doc(filename);
00927 if(doc.LoadFile()==false){
00928 QTWARNING("Could not open " + filename);
00929 return NULL;
00930 }
00931
00932 const TiXmlElement* root = doc.RootElement();
00933 if(root==NULL){
00934 QTWARNING("Empty XML");
00935 return NULL;
00936 }
00937
00938 QString line = root->Attribute("type");
00939 if(line.isNull()){
00940 QTWARNING("Class Type not found");
00941 return NULL;
00942 }
00943 line = line.stripWhiteSpace();
00944
00945 Robot *robot = (Robot *) getWorldElementFactory().createElement(line.toStdString(), this, NULL);
00946
00947 if (!robot) {
00948 QTWARNING("Unable to create robot of class " + line);
00949 return NULL;
00950 }
00951
00952 QString rootPath = filename.section('/',0,-2,QString::SectionIncludeTrailingSep);
00953 robot->setName(filename.section('/',-1).section('.',0,0));
00954 QString myFilename = relativePath(filename,getenv("GRASPIT"));
00955 robot->setFilename(myFilename);
00956 if (robot->loadFromXml(root,rootPath) == FAILURE) {
00957 QTWARNING("Failed to load robot from file");
00958 delete robot;
00959 return NULL;
00960 }
00961 addRobot(robot);
00962 return robot;
00963 }
00964
00975 void
00976 World::addRobot(Robot *robot, bool addToScene)
00977 {
00978 robotVec.push_back(robot);
00979 numRobots++;
00980
00981 if (robot->getBase()) {
00982 addLink(robot->getBase());
00983 }
00984
00985 for (int f=0; f<robot->getNumChains(); f++) {
00986 for (int l=0; l<robot->getChain(f)->getNumLinks(); l++) {
00987 addLink(robot->getChain(f)->getLink(l));
00988 }
00989 }
00990 for (int f=0; f<robot->getNumChains(); f++) {
00991 mCollisionInterface->activatePair(robot->getChain(f)->getLink(0), robot->getBase(), false);
00992 for (int l=0; l<robot->getChain(f)->getNumLinks(); l++) {
00993 for(int l2 = 0; l2<robot->getChain(f)->getNumLinks();l2++) {
00994 if (l==l2) continue;
00995 mCollisionInterface->activatePair(robot->getChain(f)->getLink(l),
00996 robot->getChain(f)->getLink(l2), false);
00997 }
00998 }
00999 }
01000 if (robot->inherits("Hand")) {
01001 handVec.push_back((Hand *)robot);
01002 if (numGB > 0) ((Hand *)robot)->getGrasp()->setObject(GBVec[0]);
01003 numHands++;
01004 if (numHands==1) setCurrentHand((Hand *)robot);
01005 }
01006 for (int d=0;d<robot->getNumDOF();d++) {
01007 robot->getDOF(d)->setDesiredPos(robot->getDOF(d)->getVal());
01008 }
01009
01010 if (addToScene) {
01011 addElementToSceneGraph(robot);
01012 }
01013
01014 modified = true;
01015 emit numElementsChanged();
01016 }
01017
01018
01020 void
01021 World::removeRobot(Robot *robot)
01022 {
01023 std::vector<Robot *>::iterator rp;
01024 std::vector<Hand *>::iterator hp;
01025 for (rp=robotVec.begin();rp!=robotVec.end();rp++) {
01026 if (*rp == robot) {
01027 robotVec.erase(rp);
01028 numRobots--;
01029 break;
01030 }
01031 }
01032 if (robot->inherits("Hand")) {
01033 for (hp=handVec.begin();hp!=handVec.end();hp++) {
01034 if (*hp == robot) {
01035 handVec.erase(hp);
01036 numHands--;
01037 break;
01038 }
01039 }
01040 }
01041 delete robot;
01042 }
01043
01048 void
01049 World::addElementToSceneGraph(WorldElement *e)
01050 {
01051 if (IVRoot->findChild( e->getIVRoot() ) >= 0) {
01052 DBGA("Element is already in scene graph");
01053 return;
01054 }
01055 int i;
01056 if (e->inherits("Robot")) {
01057 for (i=0; i<(int)robotVec.size(); i++) {
01058 if (robotVec[i] == e) break;
01059 }
01060 if ( i==robotVec.size() ) {
01061 DBGA("Robot not a part of the world");
01062 return;
01063 }
01064 } else if (e->inherits("Body")) {
01065 for (i=0; i<(int)bodyVec.size(); i++) {
01066 if (GBVec[i] == e) break;
01067 }
01068 if ( i==GBVec.size() ) {
01069 DBGA("Body not a part of the world");
01070 return;
01071 }
01072 }
01073 IVRoot->addChild( e->getIVRoot() );
01074 }
01075
01080 void
01081 World::removeElementFromSceneGraph(WorldElement *e)
01082 {
01083 int c = IVRoot->findChild( e->getIVRoot() );
01084 if (c<0) {
01085 DBGA("Element not part of the scene graph");
01086 return;
01087 }
01088 e->getIVRoot()->ref();
01089 IVRoot->removeChild(c);
01090 e->getIVRoot()->unrefNoDelete();
01091 }
01092
01097 DynamicBody *
01098 World::makeBodyDynamic(Body *b, double mass)
01099 {
01100 DynamicBody *dynBod = new DynamicBody(*b,mass);
01101 dynBod->addToIvc();
01102 addBody(dynBod);
01103 destroyElement(b, true);
01104 findContacts(dynBod);
01105 return dynBod;
01106 }
01107
01112 void
01113 World::selectElement(WorldElement *e)
01114 {
01115 std::list<WorldElement *>::iterator ep;
01116 int c,l;
01117
01118 DBGP("selecting element "<<e->getName().latin1());
01119 if (e->inherits("Body")) {DBGP(" with collision id " << ((Body*)e)->getId());}
01120
01121 if (e->inherits("Body")) numSelectedBodyElements++;
01122 else if (e->inherits("Robot")) numSelectedRobotElements++;
01123 numSelectedElements++;
01124
01125 selectedElementList.push_back(e);
01126
01127 selectedBodyVec.clear();
01128 for (ep=selectedElementList.begin();ep!=selectedElementList.end();ep++) {
01129 if ((*ep)->inherits("Body")) selectedBodyVec.push_back((Body *)(*ep));
01130 else if ((*ep)->inherits("Robot")) {
01131 Robot *r = (Robot *)(*ep);
01132 selectedBodyVec.push_back(r->getBase());
01133 for (c=0;c<r->getNumChains();c++){
01134 for (l=0;l<r->getChain(c)->getNumLinks();l++) {
01135 selectedBodyVec.push_back(r->getChain(c)->getLink(l));
01136 }
01137 }
01138 }
01139 }
01140 numSelectedBodies = selectedBodyVec.size();
01141
01142 DBGP("selected elements "<<numSelectedElements);
01143 DBGP("selected bodies "<<numSelectedBodies);
01144
01145 emit selectionsChanged();
01146 }
01147
01151 void
01152 World::deselectElement(WorldElement *e)
01153 {
01154 std::list<WorldElement *>::iterator ep;
01155 int c,l;
01156
01157 DBGP("deselecting element "<<e->getName().latin1());
01158 if (e->inherits("Body")) numSelectedBodyElements--;
01159 else if (e->inherits("Robot")) numSelectedRobotElements--;
01160 numSelectedElements--;
01161
01162 selectedElementList.remove(e);
01163
01164 selectedBodyVec.clear();
01165 for (ep=selectedElementList.begin();ep!=selectedElementList.end();ep++) {
01166 if ((*ep)->inherits("Body")) selectedBodyVec.push_back((Body *)(*ep));
01167 else if ((*ep)->inherits("Robot")) {
01168 Robot *r = (Robot *)(*ep);
01169 selectedBodyVec.push_back(r->getBase());
01170 for (c=0;c<r->getNumChains();c++)
01171 for (l=0;l<r->getChain(c)->getNumLinks();l++)
01172 selectedBodyVec.push_back(r->getChain(c)->getLink(l));
01173 }
01174 }
01175 numSelectedBodies = selectedBodyVec.size();
01176 DBGP("selected elements "<<numSelectedElements);
01177 DBGP("selected bodies "<<numSelectedBodies);
01178 emit selectionsChanged();
01179 }
01180
01182 void
01183 World::deselectAll()
01184 {
01185 selectedElementList.clear();
01186 selectedBodyVec.clear();
01187
01188 numSelectedElements = numSelectedBodyElements = numSelectedRobotElements = 0;
01189 numSelectedBodies = 0;
01190 emit selectionsChanged();
01191 }
01192
01196 bool
01197 World::isSelected(WorldElement *e) const
01198 {
01199 std::list<WorldElement *>::const_iterator ep;
01200 for (ep=selectedElementList.begin();ep!=selectedElementList.end();ep++)
01201 if (*ep == e) return true;
01202 return false;
01203 }
01204
01208 void
01209 World::toggleAllCollisions(bool on)
01210 {
01211 DBGA("TOGGLING COLLISIONS");
01212 bool off = !on;
01213 if (numSelectedElements == 0) {
01214 allCollisionsOFF = off;
01215 } else if (numSelectedElements == 2) {
01216 if (off) toggleCollisions(false, selectedElementList.front(), selectedElementList.back());
01217 else toggleCollisions(true, selectedElementList.front(), selectedElementList.back());
01218 } else {
01219 std::list<WorldElement *>::iterator ep;
01220 for (ep=selectedElementList.begin();ep!=selectedElementList.end();ep++) {
01221 if (off) toggleCollisions(false, *ep);
01222 else toggleCollisions(true, *ep);
01223 }
01224 }
01225 findAllContacts();
01226 }
01227
01228 bool
01229 World::robotCollisionsAreOff(Robot *r1, WorldElement *e)
01230 {
01231 if (e->inherits("Body")) {
01232 Body *b1 = (Body*) e;
01233 if (mCollisionInterface->isActive( b1, r1->getBase() ) ) {
01234 return false;
01235 }
01236 for (int f=0; f<r1->getNumChains(); f++) {
01237 for (int l=0; l<r1->getChain(f)->getNumLinks(); l++) {
01238 if ( mCollisionInterface->isActive(b1, r1->getChain(f)->getLink(l)) )
01239 return false;
01240 }
01241 }
01242 return true;
01243 } else if (e->inherits("Robot")) {
01244 Robot *r2 = (Robot*) e;
01245 if ( mCollisionInterface->isActive(r1->getBase(), r2->getBase()) )
01246 return false;
01247
01248 for (int f2=0; f2<r2->getNumChains(); f2++)
01249 for (int l2=0; l2<r2->getChain(f2)->getNumLinks(); l2++)
01250 if ( mCollisionInterface->isActive(r1->getBase(), r2->getChain(f2)->getLink(l2) ) )
01251 return false;
01252
01253 for (int f=0; f<r1->getNumChains(); f++)
01254 for (int l=0; l<r1->getChain(f)->getNumLinks(); l++) {
01255 if ( mCollisionInterface->isActive(r1->getChain(f)->getLink(l),r2->getBase() ) )
01256 return false;
01257 for (int f2=0; f2<r2->getNumChains(); f2++)
01258 for (int l2=0; l2<r2->getChain(f2)->getNumLinks(); l2++)
01259 if ( mCollisionInterface->isActive(r1->getChain(f)->getLink(l), r2->getChain(f2)->getLink(l2) ) )
01260 return false;
01261 }
01262 return true;
01263 }
01264 return true;
01265 }
01266
01270 bool
01271 World::collisionsAreOff(WorldElement *e1,WorldElement *e2)
01272 {
01273 int f,l;
01274 Body *b1,*b2;
01275 Robot *r1,*r2;
01276
01277 if (e1 == NULL) {
01278 assert(e2 == NULL);
01279 return allCollisionsOFF;
01280 }
01281 if (e1->inherits("Body")) {
01282 b1 = (Body *)e1;
01283 if (e2) {
01284 if (e2->inherits("Body")) {
01285 b2 = (Body *)e2;
01286 return !mCollisionInterface->isActive(b1, b2);
01287 } else if (e2->inherits("Robot")) {
01288 r2 = (Robot*)e2;
01289 return robotCollisionsAreOff(r2,e1);
01290 } else {
01291 return false;
01292 }
01293 } else return !mCollisionInterface->isActive(b1);
01294 } else if (e1->inherits("Robot")) {
01295 r1 = (Robot *)e1;
01296 if (e2) {
01297 return robotCollisionsAreOff(r1,e2);
01298 } else {
01299 if ( mCollisionInterface->isActive(r1->getBase()) ) return false;
01300 for (f=0;f<r1->getNumChains();f++)
01301 for (l=0;l<r1->getChain(f)->getNumLinks();l++)
01302 if ( mCollisionInterface->isActive(r1->getChain(f)->getLink(l)) )
01303 return false;
01304 }
01305 }
01306 return true;
01307 }
01308
01313 void
01314 World::toggleCollisions(bool on, WorldElement *e1,WorldElement *e2)
01315 {
01316 int f,l,f2,l2;
01317 Body *b1,*b2;
01318 Robot *r1,*r2;
01319
01320 assert(e1);
01321 if (e1->inherits("Body")) {
01322 b1 = (Body *)e1;
01323 if (e2) {
01324 if (e2->inherits("Body")) {
01325 b2 = (Body *)e2;
01326 mCollisionInterface->activatePair(b1,b2,on);
01327 } else if (e2->inherits("Robot")) {
01328 r2 = (Robot *)e2;
01329 mCollisionInterface->activatePair(b1,r2->getBase(),on);
01330 for (f=0;f<r2->getNumChains();f++)
01331 for (l=0;l<r2->getChain(f)->getNumLinks();l++)
01332 mCollisionInterface->activatePair(b1, r2->getChain(f)->getLink(l), on);
01333 }
01334 }
01335 else mCollisionInterface->activateBody(b1,on);
01336 } else if (e1->inherits("Robot")) {
01337 r1 = (Robot *)e1;
01338 if (e2) {
01339 if (e2->inherits("Body")) {
01340 b2 = (Body *)e2;
01341 mCollisionInterface->activatePair(r1->getBase(), b2, on);
01342 for (f=0;f<r1->getNumChains();f++)
01343 for (l=0;l<r1->getChain(f)->getNumLinks();l++)
01344 mCollisionInterface->activatePair(r1->getChain(f)->getLink(l), b2, on);
01345 }
01346 else if (e2->inherits("Robot")) {
01347 r2 = (Robot *)e2;
01348 mCollisionInterface->activatePair(r1->getBase(), r2->getBase(), on);
01349
01350 for (f2=0;f2<r2->getNumChains();f2++)
01351 for (l2=0;l2<r2->getChain(f2)->getNumLinks();l2++)
01352 mCollisionInterface->activatePair(r1->getBase(), r2->getChain(f2)->getLink(l2),on);
01353
01354 for (f=0;f<r1->getNumChains();f++)
01355 for (l=0;l<r1->getChain(f)->getNumLinks();l++) {
01356 mCollisionInterface->activatePair(r1->getChain(f)->getLink(l), r2->getBase(), on);
01357
01358 for (f2=0;f2<r2->getNumChains();f2++)
01359 for (l2=0;l2<r2->getChain(f2)->getNumLinks();l2++)
01360 mCollisionInterface->activatePair(r1->getChain(f)->getLink(l), r2->getChain(f2)->getLink(l2), on);
01361 }
01362 }
01363 }else {
01364 mCollisionInterface->activateBody(r1->getBase(),on);
01365 for (f=0;f<r1->getNumChains();f++)
01366 for (l=0;l<r1->getChain(f)->getNumLinks();l++)
01367 mCollisionInterface->activateBody(r1->getChain(f)->getLink(l),on);
01368 }
01369 }
01370 }
01371
01376 bool
01377 World::noCollision(WorldElement *e)
01378 {
01379 PROF_TIMER_FUNC(WORLD_NO_COLLISION);
01380 if (allCollisionsOFF) return true;
01381
01382 if (!e) {
01383 if (mCollisionInterface->allCollisions(CollisionInterface::FAST_COLLISION,NULL,NULL)) return false;
01384 return true;
01385 }
01386
01387 std::vector<Body*> interestList;
01388 if (e->inherits("Body")) {
01389 interestList.push_back( (Body*)e );
01390 } else if (e->inherits("Robot")) {
01391 Robot *r = (Robot*)e;
01392 for (int c=0; c < r->getNumChains(); c++) {
01393 for (int l=0; l < r->getChain(c)->getNumLinks(); l++) {
01394 interestList.push_back( r->getChain(c)->getLink(l) );
01395 }
01396 }
01397 interestList.push_back( r->getBase() );
01398 if (r->getMountPiece()) interestList.push_back(r->getMountPiece());
01399 } else {
01400 DBGA("Unknown case in World::noCollision");
01401 }
01402
01403 int col = mCollisionInterface->allCollisions(CollisionInterface::FAST_COLLISION, NULL, &interestList);
01404 if (col) return false;
01405 return true;
01406 }
01407
01413 int
01414 World::getCollisionReport(CollisionReport *colReport, const std::vector<Body*> *interestList)
01415 {
01416 PROF_TIMER_FUNC(WORLD_COLLISION_REPORT);
01417 DBGP("Get COLLISION REPORT")
01418 colReport->clear();
01419 if (allCollisionsOFF) return 0;
01420
01421 int numCols;
01422 numCols = mCollisionInterface->allCollisions(CollisionInterface::ALL_COLLISIONS, colReport, interestList);
01423 return numCols;
01424 }
01425
01426 void
01427 World::getBvs(Body *b, int depth, std::vector<BoundingBox> *bvs)
01428 {
01429 mCollisionInterface->getBoundingVolumes(b, depth, bvs);
01430 }
01431
01437 vec3
01438 World::pointDistanceToBody(position p, Body *b, vec3 *normal)
01439 {
01440 PROF_TIMER_FUNC(WORLD_POINT_TO_BODY_DISTANCE);
01441 position cp; vec3 cn;
01442 mCollisionInterface->pointToBodyDistance(b, p, cp, cn);
01443 if (normal) {
01444 *normal = cn;
01445 }
01446 return cp - p;
01447 }
01448
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01466 double
01467 World::getDist(WorldElement *e1, WorldElement *e2)
01468 {
01469 double dist = -1;
01470 if (e1->inherits("Robot")) {
01471
01472
01473 Robot *r = static_cast<Robot*>(e1);
01474 dist = getDist(e2, r->getBase());
01475 for (int c=0; c<r->getNumChains(); c++) {
01476 for (int l=0; l<r->getChain(c)->getNumLinks(); l++) {
01477
01478 dist = std::min(dist, getDist(e2, r->getChain(c)->getLink(l)));
01479 }
01480 }
01481 } else if (e1->inherits("Body")) {
01482 if (e2->inherits("Robot")) {
01483
01484
01485 return getDist(e2, e1);
01486 } else if (e2->inherits("Body")){
01487
01488
01489 position p1, p2;
01490 Body *b1 = static_cast<Body*>(e1);
01491 Body *b2 = static_cast<Body*>(e2);
01492 PROF_TIMER_FUNC(WORLD_GET_DIST);
01493 return mCollisionInterface->bodyToBodyDistance(b1,b2,p1,p2);
01494 } else {
01495 DBGA("Non-robot and non-body world element in getDist");
01496 return -1;
01497 }
01498 } else {
01499 DBGA("Non-robot and non-body world element in getDist");
01500 return -1;
01501 }
01502 return dist;
01503 }
01504
01509 double
01510 World::getDist(Body *b1,Body *b2, position &p1, position &p2)
01511 {
01512 PROF_TIMER_FUNC(WORLD_GET_DIST);
01513 return mCollisionInterface->bodyToBodyDistance(b1,b2,p1,p2);
01514 }
01515
01516 void
01517 World::findVirtualContacts(Hand *hand, Body *object)
01518 {
01519 PROF_TIMER_FUNC(WORLD_FIND_VIRTUAL_CONTACTS);
01520 ContactReport contactSet;
01521 for (int f=0; f<hand->getNumFingers(); f++) {
01522 for (int l=0; l<hand->getFinger(f)->getNumLinks(); l++) {
01523 Link *link = hand->getFinger(f)->getLink(l);
01524 link->breakVirtualContacts();
01525 ContactData pc = findVirtualContact(link, object);
01526 contactSet.clear();
01527 contactSet.insert( contactSet.begin(), pc);
01528 addVirtualContacts(link, f, l, object, contactSet, false);
01529 }
01530 }
01531
01532 hand->getPalm()->breakVirtualContacts();
01533 ContactData pc = findVirtualContact(hand->getPalm(), object);
01534 contactSet.clear();
01535 contactSet.insert( contactSet.begin(), pc);
01536 addVirtualContacts(hand->getPalm(), -1, 0, object, contactSet, false);
01537 }
01538
01539 ContactData
01540 World::findVirtualContact(Link *link, Body *object)
01541 {
01542 position p1, p2;
01543 getDist(link, object, p1, p2);
01544 vec3 n = p1 * link->getTran() - p2 * object->getTran();
01545 n = normalise(n);
01546 n = n * link->getTran().inverse();
01547
01548 return ContactData(p1, p2, n, -n) ;
01549 }
01550
01554 void
01555 World::updateGrasps()
01556 {
01557 bool graspChanged = false;
01558 for (int i=0;i<numHands;i++) {
01559 if (handVec[i]->contactsChanged()) {
01560 handVec[i]->getGrasp()->update();
01561 graspChanged = true;
01562 }
01563 }
01564 if (graspChanged) {
01565 emit graspsUpdated();
01566 }
01567 }
01568
01579 void
01580 World::findContacts(CollisionReport &colReport)
01581 {
01582 PROF_TIMER_FUNC(WORLD_FIND_CONTACTS);
01583 CollisionReport::iterator it = colReport.begin();
01584 while(it!=colReport.end()) {
01585 CollisionReport::iterator it2;
01586 bool duplicate = false;
01587 for (it2 = colReport.begin(); it2<it; it2++) {
01588 if ( (*it).first == (*it2).first && (*it).second == (*it2).second) {
01589 duplicate = true;
01590 break;
01591 }
01592 }
01593 if (duplicate) {
01594 DBGP("duplicate: " << (*it).first->getName().latin1() << "--" << (*it).second->getName().latin1());
01595 it = colReport.erase(it);
01596 continue;
01597 }
01598
01599 if ( getDist( (*it).first, (*it).second ) > Contact::THRESHOLD ) {
01600 DBGP("no contact: " << (*it).first->getName().latin1() << "--" << (*it).second->getName().latin1());
01601 it = colReport.erase(it);
01602 continue;
01603 }
01604 it++;
01605 }
01606
01607 ContactReport cres;
01608 for (int i=0; i<(int)colReport.size(); i++) {
01609 std::list<Contact*> contacts = colReport[i].first->getContacts();
01610 std::list<Contact*>::iterator it;
01611 for (it = contacts.begin(); it!=contacts.end(); it++) {
01612 if ( (*it)->getBody1() == colReport[i].first && (*it)->getBody2() == colReport[i].second) {
01613 colReport[i].first->removeContact(*it);
01614 }
01615 }
01616 cres.clear();
01617 mCollisionInterface->contact(&cres, Contact::THRESHOLD, colReport[i].first, colReport[i].second);
01618 addContacts(colReport[i].first, colReport[i].second, cres, softContactsAreOn());
01619 }
01620 }
01621
01625 void
01626 World::findContacts(Body *b)
01627 {
01628 PROF_TIMER_FUNC(WORLD_FIND_CONTACTS);
01629 ContactReport contactReport;
01630 for (int i=0;i<numBodies;i++) {
01631 if (bodyVec[i] != b) {
01632 mCollisionInterface->contact(&contactReport, Contact::THRESHOLD, b, bodyVec[i]);
01633 addContacts(b, bodyVec[i], contactReport, softContactsAreOn());
01634 }
01635 }
01636 }
01637
01642 void
01643 World::findAllContacts()
01644 {
01645 PROF_TIMER_FUNC(WORLD_FIND_CONTACTS);
01646 for (int i=0;i<numBodies;i++) {
01647 bodyVec[i]->resetContactList();
01648 }
01649 if (allCollisionsOFF) return;
01650 CollisionReport report;
01651 int numContacts;
01652 numContacts = mCollisionInterface->allContacts(&report, Contact::THRESHOLD, NULL);
01653 DBGP("found " << numContacts << " contacts. Adding...");
01654 for (int i=0;i<numContacts;i++) {
01655 addContacts( report[i].first, report[i].second, report[i].contacts, softContactsAreOn());
01656 DBGP( report[i].first->getName().latin1() << " - " << report[i].second->getName().latin1() );
01657 }
01658 }
01659
01660
01665 void World::FindRegion( const Body *body, position point, vec3 normal, double radius,
01666 Neighborhood *neighborhood)
01667 {
01668 PROF_TIMER_FUNC(WORLD_FIND_REGION);
01669 mCollisionInterface->bodyRegion(body, point, normal, radius, neighborhood);
01670 }
01671
01684 void
01685 World::turnOnDynamics()
01686 {
01687
01688
01689 dynamicsOn = true;
01690 if (idleSensor) delete idleSensor;
01691 idleSensor = new SoIdleSensor(dynamicsCB,this);
01692 idleSensor->schedule();
01693 }
01694
01696 void
01697 World::turnOffDynamics()
01698 {
01699
01700
01701 if (idleSensor) delete idleSensor;
01702 idleSensor = NULL;
01703 dynamicsOn = false;
01704 for (int i=0; i<numRobots; i++) {
01705
01706 robotVec[i]->updateJointValuesFromDynamics();
01707
01708 robotVec[i]->updateDOFFromJoints(NULL);
01709 }
01710 updateGrasps();
01711 }
01712
01719 void World::resetDynamics()
01720 {
01721 int i,d;
01722 std::vector<double> zeroes(6,0.0);
01723
01724 for (i=0;i<numBodies;i++) {
01725 if (bodyVec[i]->isDynamic()) {
01726 ((DynamicBody *)bodyVec[i])->clearState();
01727 ((DynamicBody *)bodyVec[i])->setAccel(&zeroes[0]);
01728 ((DynamicBody *)bodyVec[i])->setVelocity(&zeroes[0]);
01729 }
01730 }
01731
01732
01733 pushDynamicState();
01734
01735 for (i=0;i<numRobots;i++) {
01736
01737 for (d=0;d<robotVec[i]->getNumDOF();d++) {
01738 robotVec[i]->getDOF(d)->setDesiredPos(robotVec[i]->getDOF(d)->getVal());
01739 }
01740 }
01741 }
01742
01743 void
01744 World::dynamicsCB(void *data,SoSensor *)
01745 {
01746 World *myWorld = (World *)data;
01747 myWorld->stepDynamics();
01748 }
01749
01753 void
01754 World::pushDynamicState()
01755 {
01756 for (int i=0;i<numBodies;i++)
01757 if (bodyVec[i]->isDynamic())
01758 ((DynamicBody *)bodyVec[i])->pushState();
01759 }
01760
01762 void
01763 World::popDynamicState()
01764 {
01765 bool stackEmpty = false;
01766 for (int i=0;i<numBodies;i++) {
01767 if (bodyVec[i]->isDynamic()) {
01768 if (!((DynamicBody *)bodyVec[i])->popState()) stackEmpty = true;
01769 }
01770 }
01771 if (stackEmpty) {
01772 DBGA("Resetting dynamics");
01773 resetDynamics();
01774 }
01775 }
01776
01792 double
01793 World::moveDynamicBodies(double timeStep)
01794 {
01795 int i,numDynBodies,numCols,moveErrCode;
01796 std::vector<DynamicBody *> dynBodies;
01797 static CollisionReport colReport;
01798 bool jointLimitHit;
01799 double contactTime,delta,tmpDist,minDist,dofLimitDist;
01800
01801
01802 for (i=0;i<numBodies;i++) {
01803 if (bodyVec[i]->isDynamic()) {
01804 dynBodies.push_back((DynamicBody *)bodyVec[i]);
01805 ((DynamicBody *)bodyVec[i])->markState();
01806 }
01807 }
01808 numDynBodies = dynBodies.size();
01809
01810
01811 DBGP("moving bodies with timestep: " << timeStep);
01812 moveErrCode = moveBodies(numDynBodies,dynBodies,timeStep);
01813 if (moveErrCode == 1){
01814 popDynamicState();
01815 turnOffDynamics();
01816 return -1.0 ;
01817 }
01818
01819
01820 for (i=0;i<numRobots;i++) {
01821 robotVec[i]->updateJointValuesFromDynamics();
01822 }
01823
01824
01825 if (numDynBodies > 0) numCols = getCollisionReport(&colReport);
01826 else numCols = 0;
01827
01828
01829 jointLimitHit = false;
01830 for (i=0;i<numRobots;i++) {
01831 if (robotVec[i]->jointLimitDist() < 0.0) jointLimitHit = true;
01832 }
01833
01834
01835 if (numCols || jointLimitHit) {
01836
01837 for (i=0;i<numDynBodies;i++) {
01838 dynBodies[i]->returnToMarkedState();
01839 }
01840 minDist = 1.0e+255;
01841 dofLimitDist = 1.0e+255;
01842
01843 #ifdef GRASPITDBG
01844 if (numCols) {
01845 std::cout << "COLLIDE!" << std::endl;
01846 for (i=0;i<numCols;i++) {
01847 std::cout << colReport[i].first->getName() << " collided with " <<
01848 colReport[i].second->getName() << std::endl;
01849 }
01850
01851 for (i=0;i<numCols;i++) {
01852 tmpDist = getDist(colReport[i].first,colReport[i].second);
01853 if (tmpDist < minDist) minDist = tmpDist;
01854 std::cout << "minDist: " << tmpDist <<" between " << std::endl;
01855 std::cout << colReport[i].first->getName() << " and " <<
01856 colReport[i].second->getName() << std::endl;
01857 }
01858 }
01859 #endif
01860
01861
01862
01863 bool done = false;
01864 contactTime = timeStep;
01865 delta = contactTime/2;
01866 contactTime -= delta;
01867
01868 while (!done) {
01869 delta /= 2.0;
01870 for (i=0;i<numDynBodies;i++) {
01871 dynBodies[i]->returnToMarkedState();
01872 }
01873 DBGP("moving bodies with timestep: " << contactTime);
01874 moveErrCode = moveBodies(numDynBodies,dynBodies,contactTime);
01875
01876 if (moveErrCode == 1){
01877 popDynamicState();
01878 turnOffDynamics();
01879 return -1.0;
01880 }
01881
01882 const char *min_body_1,*min_body_2;
01883
01884
01885 for (i=0;i<numRobots;i++) {
01886 robotVec[i]->updateJointValuesFromDynamics();
01887 }
01888
01889 if (numCols) {
01890 minDist = 1.0e+255;
01891 for (i=0;i<numCols;i++) {
01892 tmpDist = getDist(colReport[i].first,colReport[i].second);
01893 if (tmpDist < minDist) {
01894 minDist = tmpDist;
01895 min_body_1 = colReport[i].first->getName().latin1();
01896 min_body_2 = colReport[i].second->getName().latin1();
01897 DBGP("minDist: " << minDist << " between " << colReport[i].first->getName() <<
01898 " and " << colReport[i].second->getName());
01899 }
01900 }
01901 }
01902
01903 if (jointLimitHit) {
01904 dofLimitDist = 1.0e10;
01905 for (i=0; i<numRobots; i++) {
01906 dofLimitDist = MIN( dofLimitDist, robotVec[i]->jointLimitDist() );
01907 }
01908 }
01909
01910 if (minDist <= 0.0 || dofLimitDist < -resabs)
01911 contactTime -= delta;
01912 else if (minDist > Contact::THRESHOLD * 0.5 && dofLimitDist > 0.01)
01913 contactTime += delta;
01914 else break;
01915
01916 if (fabs(delta) < 1.0E-15 || contactTime < 1.0e-7) {
01917 if (minDist <= 0) {
01918 fprintf(stderr,"Delta failsafe due to collision: %s and %s\n",min_body_1,min_body_2);
01919 } else {
01920 fprintf(stderr,"Delta failsafe due to joint\n");
01921 }
01922 done = true;
01923 }
01924 }
01925
01926
01927 if (done && contactTime < 1.0E-7) {
01928 DBGP("!! could not find contact time !!");
01929 for (i=0;i<numDynBodies;i++)
01930 dynBodies[i]->returnToMarkedState();
01931 }
01932 worldTime += contactTime;
01933 }
01934 else {
01935 worldTime += timeStep;
01936 contactTime = timeStep;
01937 }
01938
01939 #ifdef GRASPITDBG
01940 std::cout << "CHECKING COLLISIONS AT MIDDLE OF STEP: ";
01941 numCols = getCollisionReport(colReport);
01942
01943 if (!numCols){
01944 std::cout << "None." << std::endl;
01945 }
01946 else {
01947 std::cout << numCols <<" found!!!" << std::endl;
01948 for (i=0;i<numCols;i++) {
01949 std::cout << colReport[i].first->getName() << " collided with " <<
01950 colReport[i].second->getName() << std::endl;
01951 }
01952 }
01953 #endif
01954
01955 if (numDynBodies > 0)
01956 findAllContacts();
01957
01958 for (i=0; i<numRobots; i++){
01959 if ( robotVec[i]->inherits("HumanHand") ) ((HumanHand*)robotVec[i])->updateTendonGeometry();
01960 robotVec[i]->emitConfigChange();
01961 }
01962 emit tendonDetailsChanged();
01963
01964 if (contactTime<1.0E-7) return -1.0;
01965 return contactTime;
01966 }
01967
01978 int
01979 World::computeNewVelocities(double timeStep)
01980 {
01981 bool allDynamicsComputed;
01982 static std::list<Contact *> contactList;
01983 std::list<Contact *>::iterator cp;
01984 std::vector<DynamicBody *> robotLinks;
01985 std::vector<DynamicBody *> dynIsland;
01986 std::vector<Robot *> islandRobots;
01987 int i,j,numLinks,numDynBodies,numIslandRobots,lemkeErrCode;
01988
01989 #ifdef GRASPITDBG
01990 int islandCount = 0;
01991 #endif
01992
01993 do {
01994
01995 for (i=0;i<numBodies;i++)
01996 if (bodyVec[i]->isDynamic() &&
01997 !((DynamicBody *)bodyVec[i])->dynamicsComputed()) {
01998
01999
02000 if (bodyVec[i]->inherits("Link")) {
02001 Robot *robot = ((Robot *)((Link *)bodyVec[i])->getOwner())->getBaseRobot();
02002 robot->getAllLinks(dynIsland);
02003 robot->getAllAttachedRobots(islandRobots);
02004 }
02005 else
02006 dynIsland.push_back((DynamicBody *)bodyVec[i]);
02007 break;
02008 }
02009 numDynBodies = dynIsland.size();
02010 for (i=0;i<numDynBodies;i++)
02011 dynIsland[i]->setDynamicsFlag();
02012
02013
02014 for (i=0;i<numDynBodies;i++) {
02015 contactList = dynIsland[i]->getContacts();
02016 for (cp=contactList.begin();cp!=contactList.end();cp++) {
02017
02018 if ((*cp)->getBody2()->isDynamic() &&
02019 !((DynamicBody *)(*cp)->getBody2())->dynamicsComputed()) {
02020 DynamicBody *contactedBody = (DynamicBody *)(*cp)->getBody2();
02021
02022
02023 if (contactedBody->isA("Link")) {
02024 Robot *robot = ((Robot *)((Link *)contactedBody)->getOwner())->getBaseRobot();
02025 robot->getAllLinks(robotLinks);
02026 robot->getAllAttachedRobots(islandRobots);
02027 numLinks = robotLinks.size();
02028 for (j=0;j<numLinks;j++)
02029 if (!robotLinks[j]->dynamicsComputed()) {
02030 dynIsland.push_back(robotLinks[j]);
02031 robotLinks[j]->setDynamicsFlag();
02032 numDynBodies++;
02033 }
02034 robotLinks.clear();
02035 }
02036 else {
02037 dynIsland.push_back(contactedBody);
02038 contactedBody->setDynamicsFlag();
02039 numDynBodies++;
02040 }
02041 }
02042 }
02043 }
02044
02045 numIslandRobots = islandRobots.size();
02046
02047 #ifdef GRASPITDBG
02048 std::cout << "Island "<< ++islandCount<<" Bodies: ";
02049 for (i=0;i<numDynBodies;i++)
02050 std::cout << dynIsland[i]->getName() <<" ";
02051 std::cout << std::endl;
02052 std::cout << "Island Robots"<< islandCount<<" Robots: ";
02053 for (i=0;i<numIslandRobots;i++)
02054 std::cout << islandRobots[i]->getName() <<" ";
02055 std::cout << std::endl << std::endl;
02056 #endif
02057
02058 for (i=0;i<numDynBodies;i++)
02059 dynIsland[i]->markState();
02060
02061 DynamicParameters dp;
02062 if (numDynBodies > 0) {
02063 dp.timeStep = timeStep;
02064 dp.useContactEps = true;
02065 dp.gravityMultiplier = 1.0;
02066 lemkeErrCode = iterateDynamics(islandRobots,dynIsland,&dp);
02067
02068 if (lemkeErrCode == 1){
02069 std::cerr << "LCP COULD NOT BE SOLVED!"<<std::endl<<std::endl;
02070 turnOffDynamics();
02071 return -1;
02072 }
02073 }
02074
02075 dynIsland.clear();
02076 islandRobots.clear();
02077 allDynamicsComputed = true;
02078 for (i=0;i<numBodies;i++)
02079 if (bodyVec[i]->isDynamic() &&
02080 !((DynamicBody *)bodyVec[i])->dynamicsComputed()) {
02081 allDynamicsComputed = false;
02082 break;
02083 }
02084 } while (!allDynamicsComputed);
02085
02086
02087 for (i=0;i<numBodies;i++)
02088 if (bodyVec[i]->isDynamic())
02089 ((DynamicBody *)bodyVec[i])->resetDynamicsFlag();
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125 emit dynamicStepTaken();
02126 return 0;
02127 }
02128
02129 void
02130 World::resetDynamicWrenches()
02131 {
02132 for (int i=0; i<numBodies; i++) {
02133 if (bodyVec[i]->isDynamic()) {
02134 ((DynamicBody*)bodyVec[i])->resetExtWrenchAcc();
02135 }
02136 }
02137 }
02138
02148 void
02149 World::stepDynamics()
02150 {
02151 resetDynamicWrenches();
02152 double actualTimeStep = moveDynamicBodies(dynamicsTimeStep);
02153 if (actualTimeStep<0) {
02154 turnOffDynamics();
02155 emit dynamicsError("Timestep failsafe reached.");
02156 return;
02157 }
02158
02159 for (int i=0; i<numRobots; i++) {
02160 robotVec[i]->DOFController(actualTimeStep);
02161 robotVec[i]->applyJointPassiveInternalWrenches();
02162 }
02163
02164 if (computeNewVelocities(actualTimeStep)) {
02165 emit dynamicsError("LCP could not be solved.");
02166 return;
02167 }
02168 if (idleSensor) idleSensor->schedule();
02169 }
02170
02171 void World::selectTendon(Tendon *t)
02172 {
02173 if (isTendonSelected)
02174 selectedTendon->deselect();
02175
02176 isTendonSelected = true;
02177 selectedTendon = t;
02178 selectedTendon->select();
02179
02180
02181
02182 if ( getCurrentHand() != (Hand*)selectedTendon->getRobot() ) setCurrentHand( (Hand*)t->getRobot() );
02183
02184 emit tendonSelectionChanged();
02185 }
02186
02187 void World::selectTendon(int i)
02188 {
02189 if (isTendonSelected)
02190 selectedTendon->deselect();
02191
02192
02193 if (!currentHand)
02194 {
02195 printf("ERROR: no hand selected\n");
02196 return;
02197 }
02198 if (! currentHand->inherits("HumanHand") )
02199 {
02200 printf("ERROR: selected hand is not tendon-actuated\n");
02201 return;
02202 }
02203
02204 if ( ((HumanHand*)currentHand)->getNumTendons() <= i)
02205 {
02206 printf("ERROR: selected hand has fewer tendons than passed parameter\n");
02207 return;
02208 }
02209
02210 if (isTendonSelected)
02211 selectedTendon->deselect();
02212
02213 isTendonSelected = true;
02214 selectedTendon = ((HumanHand*)currentHand)->getTendon(i);
02215 selectedTendon->select();
02216 emit tendonSelectionChanged();
02217 }
02218
02219 void World::deselectTendon()
02220 {
02221 isTendonSelected = false;
02222 if (selectedTendon)
02223 selectedTendon->deselect();
02224 selectedTendon = NULL;
02225 emit tendonSelectionChanged();
02226 }
02227
02228 int World::getCurrentHandNumberTendons()
02229 {
02230 if (!currentHand)
02231 return 0;
02232 if (! currentHand->inherits("HumanHand") )
02233 return 0;
02234
02235 return ((HumanHand*)currentHand)->getNumTendons();
02236 }
02237
02238 QString World::getSelectedHandTendonName(int i)
02239 {
02240
02241 if (i>=getCurrentHandNumberTendons())
02242 return QString("Error reading name");
02243
02244 return ((HumanHand*)currentHand)->getTendon(i)->getName();
02245 }