00001 #include "arena.h"
00002
00003 #include "arenaelement.h"
00004 #include "arenaelementtype.h"
00005 #include "arenaelementtyperegistry.h"
00006 #include "xmlloadingexception.h"
00007
00008 #include <QFile>
00009 #include <QDomDocument>
00010 #include <QDebug>
00011 #include <QList>
00012 #include <QDomNodeList>
00013 #include <QMessageBox>
00014
00015 Arena::Arena(ArenaElementTypeRegistry* typeRegistry)
00016 : m_typeRegistry(typeRegistry)
00017 {
00018 }
00019
00020 Arena::~Arena()
00021 {
00022 }
00023
00024 void Arena::load(const QString& filename)
00025 {
00026 QFile in(filename);
00027 in.open(QFile::ReadOnly);
00028
00029 QDomDocument doc;
00030 doc.setContent(&in);
00031
00032 in.close();
00033
00034
00035 QList<ArenaElement*> loadedElements;
00036 bool loadingSuccessful = true;
00037
00038 try
00039 {
00040 QDomNodeList nodes = doc.elementsByTagName("element");
00041 for(int i = 0; i < nodes.count(); i++)
00042 {
00043 QDomElement node = nodes.at(i).toElement();
00044 QString type = node.attribute("type");
00045 if (type.isEmpty())
00046 {
00047 qDebug() << "[Rescue Arena Designer] Error: Empty element type"
00048 << "specified in" << filename << ". Ignoring.";
00049 continue;
00050 }
00051
00052 if (!m_typeRegistry->hasElement(type))
00053 {
00054 qDebug() << "[Rescue Arena Designer] Error: Unknown element type"
00055 << type << "in" << filename << ". Ignoring.";
00056 continue;
00057 }
00058 ArenaElement *element = m_typeRegistry->instantiateElement(type);
00059 Q_ASSERT(element);
00060 loadedElements.append(element);
00061
00062 element->load(node);
00063 }
00064 }
00065 catch (XmlLoadingException e)
00066 {
00067 loadingSuccessful = false;
00068 QString msg;
00069 QTextStream(&msg) << "There's an error in the arena XML file in line "
00070 << e.lineNumber() << ", column " << e.columnNumber()
00071 << ":\n" << e.msg();
00072 QMessageBox msgBox(QMessageBox::Critical,
00073 QString("Error while loading arena XML file"),
00074 msg);
00075 msgBox.exec();
00076 }
00077
00078
00079 if (loadingSuccessful)
00080 {
00081 foreach (ArenaElement *element, loadedElements)
00082 {
00083 addElement(element);
00084 }
00085 }
00086 }
00087
00088 void Arena::save(const QString& filename)
00089 {
00090 QFile out(filename);
00091 out.open(QFile::WriteOnly);
00092
00093 if (out.error() != QFile::NoError)
00094 qDebug() << "[Hector Arena Designer] Error saving arena file:" << out.errorString();
00095
00096 QXmlStreamWriter writer(&out);
00097
00098 writer.setAutoFormatting(true);
00099
00100 writer.writeStartDocument();
00101 writer.writeStartElement("elements");
00102
00103 foreach (ArenaElement *element, m_elements)
00104 element->save(writer);
00105
00106 writer.writeEndElement();
00107 writer.writeEndDocument();
00108
00109 out.close();
00110 }
00111
00112 void Arena::saveWorld(const QString& filename)
00113 {
00114 QFile out(filename);
00115 out.open(QFile::WriteOnly);
00116
00117 QXmlStreamWriter writer(&out);
00118
00119 writer.setAutoFormatting(true);
00120
00121 writer.writeStartDocument();
00122
00123 writer.writeStartElement("gazebo:world");
00124 writer.writeAttribute("xmlns:gazebo", "http://playerstage.sourceforge.net/gazebo/xmlschema/#gz");
00125 writer.writeAttribute("xmlns:model", "http://playerstage.sourceforge.net/gazebo/xmlschema/#model");
00126 writer.writeAttribute("xmlns:body", "http://playerstage.sourceforge.net/gazebo/xmlschema/#body");
00127 writer.writeAttribute("xmlns:geom", "http://playerstage.sourceforge.net/gazebo/xmlschema/#geom");
00128 writer.writeAttribute("xmlns:physics", "http://playerstage.sourceforge.net/gazebo/xmlschema/#physics");
00129 writer.writeAttribute("xmlns:rendering", "http://playerstage.sourceforge.net/gazebo/xmlschema/#rendering");
00130
00131 writer.writeStartElement("physics:ode");
00132 writer.writeTextElement("stepTime", "0.001");
00133 writer.writeTextElement("gravity", "0 0 -9.81");
00134
00135
00136 writer.writeTextElement("cfm", "10e-10");
00137
00138
00139 writer.writeTextElement("erp", "0.2");
00140 writer.writeTextElement("stepType", "quick");
00141 writer.writeTextElement("stepIters", "10");
00142 writer.writeTextElement("contactMaxCorrectingVel", "100.0");
00143 writer.writeTextElement("contactSurfaceLayer", "0.001");
00144 writer.writeTextElement("updateRate", "-0.1");
00145
00146 writer.writeEndElement();
00147
00148 writer.writeStartElement("rendering:gui");
00149
00150 writer.writeTextElement("type", "flkt");
00151 writer.writeTextElement("size", "800 600");
00152 writer.writeTextElement("pos", "0 0");
00153
00154 writer.writeStartElement("frames");
00155
00156 writer.writeStartElement("row");
00157 writer.writeAttribute("height", "100%");
00158 writer.writeStartElement("camera");
00159 writer.writeAttribute("width", "100%");
00160
00161 writer.writeTextElement("xyz", "0 0 3");
00162 writer.writeTextElement("rpy", "0 90 90");
00163
00164
00165 writer.writeEndElement();
00166
00167
00168 writer.writeEndElement();
00169
00170
00171 writer.writeEndElement();
00172
00173
00174 writer.writeEndElement();
00175
00176 writer.writeStartElement("rendering:ogre");
00177 writer.writeTextElement("ambient", "0.2 0.2 0.2 1.0");
00178 writer.writeStartElement("sky");
00179 writer.writeTextElement("material", "Gazebo/CloudySky");
00180
00181 writer.writeEndElement();
00182 writer.writeTextElement("grid", "false");
00183
00184 writer.writeEndElement();
00185
00186 writer.writeStartElement("model:renderable");
00187 writer.writeAttribute("name", "point_white");
00188 writer.writeTextElement("xyz", "0 0 20");
00189 writer.writeTextElement("rpy", "0 50 50");
00190 writer.writeTextElement("enableGravity", "false");
00191 writer.writeStartElement("light");
00192 writer.writeTextElement("type", "directional");
00193 writer.writeTextElement("diffuseColor", "0.7 0.7 0.7");
00194 writer.writeTextElement("specularColor", "0.1 0.1 0.1");
00195 writer.writeTextElement("attenuation", "0.2 0.1 0");
00196 writer.writeTextElement("range", "100.0");
00197
00198 writer.writeEndElement();
00199 writer.writeEndElement();
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 writer.writeStartElement("model:physical");
00219 writer.writeAttribute("name", "gplane");
00220
00221 writer.writeTextElement("xyz", "0 0 0");
00222 writer.writeTextElement("rpy", "0 0 0");
00223 writer.writeTextElement("static", "true");
00224
00225 writer.writeStartElement("body:plane");
00226 writer.writeAttribute("name", "plane");
00227
00228 writer.writeStartElement("geom:plane");
00229 writer.writeAttribute("name", "plane");
00230
00231 writer.writeTextElement("laserRetro", "2000.0");
00232 writer.writeTextElement("mu1", "50.0");
00233 writer.writeTextElement("mu2", "50.0");
00234
00235 writer.writeTextElement("kp", "1000000000.0");
00236 writer.writeTextElement("kd", "1.0");
00237
00238 writer.writeTextElement("normal", "0 0 1");
00239 writer.writeTextElement("size", "120 120");
00240
00241 writer.writeTextElement("segments", "10 10");
00242 writer.writeTextElement("uvTile", "100 100");
00243
00244 writer.writeTextElement("material", "Gazebo/GrayGrid");
00245
00246
00247
00248 writer.writeEndElement();
00249
00250 writer.writeEndElement();
00251
00252 writer.writeEndElement();
00253
00254 foreach (ArenaElement *element, m_elements)
00255 element->saveWorld(writer);
00256
00257 writer.writeEndElement();
00258 writer.writeEndDocument();
00259
00260 out.close();
00261 }
00262
00263 void Arena::saveWorldSdf(const QString& filename)
00264 {
00265 QFile out(filename);
00266 out.open(QFile::WriteOnly);
00267
00268 QXmlStreamWriter writer(&out);
00269
00270 writer.setAutoFormatting(true);
00271
00272 writer.writeStartDocument();
00273
00274 writer.writeStartElement("sdf");
00275 writer.writeAttribute("version", "1.3");
00276
00277 writer.writeStartElement("world");
00278 writer.writeAttribute("name", "default");
00279
00280 writer.writeStartElement("scene");
00281 writer.writeTextElement("ambient", "0.5 0.5 0.5 1");
00282 writer.writeTextElement("background","0.5 0.5 0.5 1");
00283 writer.writeTextElement("shadows", "false");
00284 writer.writeEndElement();
00285
00286 writer.writeStartElement("physics");
00287 writer.writeAttribute("type", "ode");
00288
00289 writer.writeTextElement("gravity", "0 0 -9.81");
00290
00291 writer.writeStartElement("ode");
00292
00293 writer.writeStartElement("solver");
00294 writer.writeTextElement("type","quick");
00295 writer.writeTextElement("dt","0.001");
00296 writer.writeTextElement("iters","10");
00297 writer.writeTextElement("sor","1.3");
00298 writer.writeEndElement();
00299
00300 writer.writeStartElement("constraints");
00301 writer.writeTextElement("cfm","0.0");
00302 writer.writeTextElement("erp","0.2");
00303 writer.writeTextElement("contact_max_correcting_vel","100.0");
00304 writer.writeTextElement("contact_surface_layer","0.001");
00305 writer.writeEndElement();
00306
00307 writer.writeEndElement();
00308 writer.writeTextElement("update_rate", "1000");
00309
00310 writer.writeEndElement();
00311
00312 writer.writeStartElement("light");
00313 writer.writeAttribute("type","directional");
00314 writer.writeAttribute("name","directional_light_1");
00315 writer.writeTextElement("cast_shadows","false");
00316
00317 writer.writeTextElement("pose","0 0 30 0.1 0.1 0");
00318 writer.writeTextElement("diffuse", ".5 .5 .5 1");
00319 writer.writeTextElement("specular", ".1 .1 .1 1");
00320
00321 writer.writeStartElement("attenuation");
00322 writer.writeTextElement("range", "300");
00323 writer.writeEndElement();
00324
00325 writer.writeTextElement("direction", "0.1 0.1 -1");
00326 writer.writeEndElement();
00327
00328 writer.writeStartElement("model");
00329 writer.writeAttribute("name", "plane_model");
00330 writer.writeTextElement("static", "true");
00331
00332 writer.writeStartElement("link");
00333 writer.writeAttribute("name","plane_model_link");
00334
00335 writer.writeStartElement("collision");
00336 writer.writeAttribute("name","plane_model_collision");
00337
00338 writer.writeStartElement("geometry");
00339
00340 writer.writeStartElement("plane");
00341 writer.writeTextElement("normal", "0 0 1");
00342 writer.writeEndElement();
00343
00344 writer.writeEndElement();
00345
00346 writer.writeStartElement("surface");
00347
00348 writer.writeStartElement("friction");
00349
00350 writer.writeStartElement("ode");
00351 writer.writeTextElement("mu","10.0");
00352 writer.writeTextElement("mu2","10.0");
00353 writer.writeTextElement("fdir1","0 0 0");
00354 writer.writeTextElement("slip1","0");
00355 writer.writeTextElement("slip2","0");
00356 writer.writeEndElement();
00357
00358 writer.writeEndElement();
00359
00360 writer.writeStartElement("bounce");
00361 writer.writeTextElement("restitution_coefficient","0");
00362 writer.writeTextElement("threshold","1000000.0");
00363 writer.writeEndElement();
00364
00365 writer.writeStartElement("contact");
00366
00367 writer.writeStartElement("ode");
00368 writer.writeTextElement("soft_cfm","0");
00369 writer.writeTextElement("soft_erp","0.2");
00370 writer.writeTextElement("kp","1e10");
00371 writer.writeTextElement("kd","1");
00372 writer.writeTextElement("max_vel","100.0");
00373 writer.writeTextElement("min_depth","0.0001");
00374 writer.writeEndElement();
00375
00376 writer.writeEndElement();
00377
00378 writer.writeEndElement();
00379 writer.writeEndElement();
00380
00381
00382 writer.writeStartElement("visual");
00383 writer.writeAttribute("name","plane_model_visual");
00384 writer.writeTextElement("cast_shadows","false");
00385
00386 writer.writeStartElement("geometry");
00387
00388 writer.writeStartElement("plane");
00389 writer.writeTextElement("normal","0 0 1");
00390 writer.writeEndElement();
00391
00392 writer.writeEndElement();
00393
00394 writer.writeStartElement("material");
00395 writer.writeTextElement("script","Gazebo/Grey");
00396 writer.writeEndElement();
00397
00398
00399
00400
00401
00402
00403 writer.writeEndElement();
00404
00405 writer.writeEndElement();
00406
00407 writer.writeEndElement();
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 foreach (ArenaElement *element, m_elements)
00419 element->saveWorldSdf(writer);
00420
00421
00422 writer.writeEndElement();
00423
00424 writer.writeEndDocument();
00425
00426 out.close();
00427 }
00428
00429 void Arena::slotModified()
00430 {
00431 emit modified();
00432 }
00433
00434 void Arena::addElement(ArenaElement *element)
00435 {
00436 Q_ASSERT(!m_elements.contains(element));
00437 m_elements.append(element);
00438
00439 connect(element, SIGNAL(posChanged(ArenaElement*,QPoint)),
00440 this, SLOT(slotModified()));
00441 connect(element, SIGNAL(rotationChanged(ArenaElement*,int)),
00442 this, SLOT(slotModified()));
00443 connect(element, SIGNAL(modified(ArenaElement*)),
00444 this, SIGNAL(modified()));
00445
00446 element->setArena(this);
00447
00448 emit elementAdded(element);
00449 }
00450
00451 void Arena::removeElement(ArenaElement *element)
00452 {
00453 Q_ASSERT(m_elements.contains(element));
00454 m_elements.removeAll(element);
00455
00456 emit elementRemoved(element);
00457 }
00458
00459 void Arena::clear()
00460 {
00461 foreach (ArenaElement *element, m_elements)
00462 {
00463 m_elements.removeAll(element);
00464 emit elementRemoved(element);
00465 }
00466 m_elements.clear();
00467
00468 emit modified();
00469 }
00470
00471 ArenaElement* Arena::addElement(const QString &elementType)
00472 {
00473 ArenaElement *element = m_typeRegistry->instantiateElement(elementType);
00474 if (element)
00475 addElement(element);
00476 return element;
00477 }
00478
00479 QList<ArenaElement*> Arena::elementsAt(const QPoint &pos) const
00480 {
00481 QList<ArenaElement*> res;
00482 foreach (ArenaElement* e, m_elements)
00483 if (e->pos() == pos)
00484 res.push_back(e);
00485 return res;
00486 }
00487
00488 ArenaElement* Arena::contextElement(ArenaElement *element) const
00489 {
00490 QList<ArenaElement*> elementsAtPos = elementsAt(element->pos());
00491 foreach (ArenaElement *e, elementsAtPos)
00492 if (e != element &&
00493 e->type()->type() == ArenaElementType::WallType &&
00494 e->rotation() == element->rotation())
00495 return e;
00496 return 0;
00497 }