int main(int argc, char *argv[]) { // Create the world Enki::World world(200, 200); // Create a Khepera and position it Enki::EPuck *ePuck = new Enki::EPuck; ePuck->pos = Enki::Point(100, 100); ePuck->leftSpeed = 30; ePuck->rightSpeed = 20; // objects are garbage collected by the world on destruction world.addObject(ePuck); Enki::Polygone p; const double amount = 9; const double radius = 5; const double height = 20; for (double a = 0; a < 2*M_PI; a += 2*M_PI/amount) p.push_back(Enki::Point(radius * cos(a), radius * sin(a))); Enki::PhysicalObject* o = new Enki::PhysicalObject; Enki::PhysicalObject::Hull hull(Enki::PhysicalObject::Part(p, height)); o->setCustomHull(hull, 1); o->pos = Enki::Point(100, 100); o->setColor(Enki::Color(0.4,0.6,0.8)); world.addObject(o); // Run for some times for (unsigned i=0; i<10; i++) { // step of 50 ms world.step(0.05); std::cout << "E-puck pos is (" << ePuck->pos.x << "," << ePuck->pos.y << ")" << std::endl; } }
void TEnkiEnvironment::addCubeWithParameters (double x, double y, Enki::Color color, int objectNumber) { // Создаем полигон, являющийся основнанием куба Enki::Polygone p; p.push_back(Enki::Point(cubeSize/2.0,cubeSize/2.0)); p.push_back(Enki::Point(-cubeSize/2.0,cubeSize/2.0)); p.push_back(Enki::Point(-cubeSize/2.0,-cubeSize/2.0)); p.push_back(Enki::Point(cubeSize/2.0,-cubeSize/2.0)); Enki::PhysicalObject* o = new Enki::PhysicalObject; Enki::PhysicalObject::Hull hull(Enki::PhysicalObject::Part(p, cubeSize)); // Задаем форму куба o->setCustomHull(hull, -100000); // Отрицательная масса - то же, что бесконечная, поэтому куб сдвинуть с места будет невозможно )); o->collisionElasticity = 0; // Все тепло от столкновения поглощается o->setColor(color); o->pos = Enki::Point(x, y); o->objectNumber = objectNumber; world->addObject(o); }
// Меняем местами положение кубов (в том числе и в массиве целей) void TEnkiEnvironment::swapCubesForColors(double r1, double g1, double b1, double r2, double g2, double b2) { // Находим кубы в массиве объектов ENKI по их цвету, а затем перекрашиваем их std::set<Enki::PhysicalObject *>objects = world->objects; std::set<Enki::PhysicalObject *>::iterator someObject; for (someObject=objects.begin(); someObject!=objects.end(); ++someObject) { Enki::PhysicalObject * actualObject = *someObject; Enki::Color color; color = actualObject->getColor(); if ((color.components[0] == r1) && (color.components[1] == g1) && (color.components[2] == b1)) { color.components[0] = r2; color.components[1] = g2; color.components[2] = b2; actualObject->setColor(color); cout << "found first cube" << std::endl; } else if ((color.components[0] == r2) && (color.components[1] == g2) && (color.components[2] == b2)) { color.components[0] = r1; color.components[1] = g1; color.components[2] = b1; actualObject->setColor(color); cout << "found second cube" << std::endl; } } // Находим кубы в массиве объектов среды (который служит для определения достижения целей) и меняем их в нем местами /*int firstIndexToSwap = 0; int secondIndexToSwap = 0; for (int i=0; i<objectsArray.size(); i++) { TEnkiObject someEnkiObject = objectsArray[i]; if ((someEnkiObject.color[0]/255.0 == r1) && (someEnkiObject.color[1]/255.0 == g1) && (someEnkiObject.color[2]/255.0 == b1)) { firstIndexToSwap = i; } else if ((someEnkiObject.color[0]/255.0 == r2) && (someEnkiObject.color[1]/255.0 == g2) && (someEnkiObject.color[2]/255.0 == b2)) { secondIndexToSwap = i; } } TEnkiObject storedObject = objectsArray.at(firstIndexToSwap); objectsArray.at(firstIndexToSwap) = objectsArray.at(secondIndexToSwap); objectsArray.at(secondIndexToSwap) = storedObject;*/ }
int main(int argc, char *argv[]) { Q_INIT_RESOURCE(asebaqtabout); QApplication app(argc, argv); QCoreApplication::setOrganizationName(ASEBA_ORGANIZATION_NAME); QCoreApplication::setOrganizationDomain(ASEBA_ORGANIZATION_DOMAIN); app.setApplicationName("Playground"); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); // Translation support QTranslator qtTranslator; qtTranslator.load("qt_" + QLocale::system().name()); app.installTranslator(&qtTranslator); QTranslator translator; translator.load(QString(":/asebaplayground_") + QLocale::system().name()); app.installTranslator(&translator); QTranslator aboutTranslator; aboutTranslator.load(QString(":/qtabout_") + QLocale::system().name()); app.installTranslator(&aboutTranslator); // create document QDomDocument domDocument("aseba-playground"); QString sceneFileName; // Get cmd line arguments bool ask = true; if (argc > 1) { sceneFileName = argv[1]; ask = false; } // Try to load xml config file do { if (ask) { QString lastFileName = QSettings("EPFL-LSRO-Mobots", "Aseba Playground").value("last file").toString(); sceneFileName = QFileDialog::getOpenFileName(0, app.tr("Open Scenario"), lastFileName, app.tr("playground scenario (*.playground)")); } ask = true; if (sceneFileName.isEmpty()) { std::cerr << "You must specify a valid setup scenario on the command line or choose one in the file dialog." << std::endl; exit(1); } QFile file(sceneFileName); if (file.open(QIODevice::ReadOnly)) { QString errorStr; int errorLine, errorColumn; if (!domDocument.setContent(&file, false, &errorStr, &errorLine, &errorColumn)) { QMessageBox::information(0, "Aseba Playground", app.tr("Parse error at file %1, line %2, column %3:\n%4") .arg(sceneFileName) .arg(errorLine) .arg(errorColumn) .arg(errorStr)); } else { QSettings("EPFL-LSRO-Mobots", "Aseba Playground").setValue("last file", sceneFileName); break; } } } while (true); // Scan for colors typedef QMap<QString, Enki::Color> ColorsMap; ColorsMap colorsMap; QDomElement colorE = domDocument.documentElement().firstChildElement("color"); while (!colorE.isNull()) { colorsMap[colorE.attribute("name")] = Enki::Color( colorE.attribute("r").toDouble(), colorE.attribute("g").toDouble(), colorE.attribute("b").toDouble() ); colorE = colorE.nextSiblingElement ("color"); } // Scan for areas typedef QMap<QString, Enki::Polygon> AreasMap; AreasMap areasMap; QDomElement areaE = domDocument.documentElement().firstChildElement("area"); while (!areaE.isNull()) { Enki::Polygon p; QDomElement pointE = areaE.firstChildElement("point"); while (!pointE.isNull()) { p.push_back(Enki::Point( pointE.attribute("x").toDouble(), pointE.attribute("y").toDouble() )); pointE = pointE.nextSiblingElement ("point"); } areasMap[areaE.attribute("name")] = p; areaE = areaE.nextSiblingElement ("area"); } // Create the world QDomElement worldE = domDocument.documentElement().firstChildElement("world"); Enki::Color worldColor(Enki::Color::gray); if (!colorsMap.contains(worldE.attribute("color"))) std::cerr << "Warning, world walls color " << worldE.attribute("color").toStdString() << " undefined\n"; else worldColor = colorsMap[worldE.attribute("color")]; Enki::World::GroundTexture groundTexture; if (worldE.hasAttribute("groundTexture")) { const QString groundTextureFileName(QFileInfo(sceneFileName).absolutePath() + QDir::separator() + worldE.attribute("groundTexture")); QImage image(groundTextureFileName); if (!image.isNull()) { // flip vertically as y-coordinate is inverted in an image image = image.mirrored(); // convert to a specific format and copy the underlying data to Enki image = image.convertToFormat(QImage::Format_ARGB32); groundTexture.width = image.width(); groundTexture.height = image.height(); const uint32_t* imageData(reinterpret_cast<const uint32_t*>(image.constBits())); std::copy(imageData, imageData+image.width()*image.height(), std::back_inserter(groundTexture.data)); // Note: this works in little endian, in big endian data should be swapped } else { qDebug() << "Could not load ground texture file named" << groundTextureFileName; } } Enki::World world( worldE.attribute("w").toDouble(), worldE.attribute("h").toDouble(), worldColor, groundTexture ); // Create viewer Enki::PlaygroundViewer viewer(&world, worldE.attribute("energyScoringSystemEnabled", "false").toLower() == "true"); if (Enki::simulatorEnvironment) qDebug() << "A simulator environment already exists, replacing"; Enki::simulatorEnvironment.reset(new Enki::PlaygroundSimulatorEnvironment(sceneFileName, viewer)); // Zeroconf support to advertise targets #ifdef ZEROCONF_SUPPORT Aseba::QtZeroconf zeroconf; #endif // ZEROCONF_SUPPORT // Scan for camera QDomElement cameraE = domDocument.documentElement().firstChildElement("camera"); if (!cameraE.isNull()) { const double largestDim(qMax(world.h, world.w)); viewer.setCamera( QPointF( cameraE.attribute("x", QString::number(world.w / 2)).toDouble(), cameraE.attribute("y", QString::number(0)).toDouble() ), cameraE.attribute("altitude", QString::number(0.85 * largestDim)).toDouble(), cameraE.attribute("yaw", QString::number(-M_PI/2)).toDouble(), cameraE.attribute("pitch", QString::number((3*M_PI)/8)).toDouble() ); } // Scan for walls QDomElement wallE = domDocument.documentElement().firstChildElement("wall"); while (!wallE.isNull()) { Enki::PhysicalObject* wall = new Enki::PhysicalObject(); if (!colorsMap.contains(wallE.attribute("color"))) std::cerr << "Warning, color " << wallE.attribute("color").toStdString() << " undefined\n"; else wall->setColor(colorsMap[wallE.attribute("color")]); wall->pos.x = wallE.attribute("x").toDouble(); wall->pos.y = wallE.attribute("y").toDouble(); wall->setRectangular( wallE.attribute("l1").toDouble(), wallE.attribute("l2").toDouble(), wallE.attribute("h").toDouble(), !wallE.attribute("mass").isNull() ? wallE.attribute("mass").toDouble() : -1 // normally -1 because immobile ); if (! wallE.attribute("angle").isNull()) wall->angle = wallE.attribute("angle").toDouble(); // radians world.addObject(wall); wallE = wallE.nextSiblingElement ("wall"); } // Scan for cylinders QDomElement cylinderE = domDocument.documentElement().firstChildElement("cylinder"); while (!cylinderE.isNull()) { Enki::PhysicalObject* cylinder = new Enki::PhysicalObject(); if (!colorsMap.contains(cylinderE.attribute("color"))) std::cerr << "Warning, color " << cylinderE.attribute("color").toStdString() << " undefined\n"; else cylinder->setColor(colorsMap[cylinderE.attribute("color")]); cylinder->pos.x = cylinderE.attribute("x").toDouble(); cylinder->pos.y = cylinderE.attribute("y").toDouble(); cylinder->setCylindric( cylinderE.attribute("r").toDouble(), cylinderE.attribute("h").toDouble(), !cylinderE.attribute("mass").isNull() ? cylinderE.attribute("mass").toDouble() : -1 // normally -1 because immobile ); world.addObject(cylinder); cylinderE = cylinderE.nextSiblingElement("cylinder"); } // Scan for feeders QDomElement feederE = domDocument.documentElement().firstChildElement("feeder"); while (!feederE.isNull()) { Enki::EPuckFeeder* feeder = new Enki::EPuckFeeder; feeder->pos.x = feederE.attribute("x").toDouble(); feeder->pos.y = feederE.attribute("y").toDouble(); world.addObject(feeder); feederE = feederE.nextSiblingElement ("feeder"); } // TODO: if needed, custom color to feeder // Scan for doors typedef QMap<QString, Enki::SlidingDoor*> DoorsMap; DoorsMap doorsMap; QDomElement doorE = domDocument.documentElement().firstChildElement("door"); while (!doorE.isNull()) { Enki::SlidingDoor *door = new Enki::SlidingDoor( Enki::Point( doorE.attribute("closedX").toDouble(), doorE.attribute("closedY").toDouble() ), Enki::Point( doorE.attribute("openedX").toDouble(), doorE.attribute("openedY").toDouble() ), Enki::Point( doorE.attribute("l1").toDouble(), doorE.attribute("l2").toDouble() ), doorE.attribute("h").toDouble(), doorE.attribute("moveDuration").toDouble() ); if (!colorsMap.contains(doorE.attribute("color"))) std::cerr << "Warning, door color " << doorE.attribute("color").toStdString() << " undefined\n"; else door->setColor(colorsMap[doorE.attribute("color")]); doorsMap[doorE.attribute("name")] = door; world.addObject(door); doorE = doorE.nextSiblingElement ("door"); } // Scan for activation, and link them with areas and doors QDomElement activationE = domDocument.documentElement().firstChildElement("activation"); while (!activationE.isNull()) { if (areasMap.find(activationE.attribute("area")) == areasMap.end()) { std::cerr << "Warning, area " << activationE.attribute("area").toStdString() << " undefined\n"; activationE = activationE.nextSiblingElement ("activation"); continue; } if (doorsMap.find(activationE.attribute("door")) == doorsMap.end()) { std::cerr << "Warning, door " << activationE.attribute("door").toStdString() << " undefined\n"; activationE = activationE.nextSiblingElement ("activation"); continue; } const Enki::Polygon& area = *areasMap.find(activationE.attribute("area")); Enki::Door* door = *doorsMap.find(activationE.attribute("door")); Enki::DoorButton* activation = new Enki::DoorButton( Enki::Point( activationE.attribute("x").toDouble(), activationE.attribute("y").toDouble() ), Enki::Point( activationE.attribute("l1").toDouble(), activationE.attribute("l2").toDouble() ), area, door ); world.addObject(activation); activationE = activationE.nextSiblingElement ("activation"); } // load all robots in one loop std::map<std::string, RobotType> robotTypes { { "thymio2", { "Thymio II", createRobotSingleVMNode<Enki::DashelAsebaThymio2> } }, { "e-puck", { "E-Puck", createRobotSingleVMNode<Enki::DashelAsebaFeedableEPuck> } }, }; QDomElement robotE = domDocument.documentElement().firstChildElement("robot"); unsigned asebaServerCount(0); while (!robotE.isNull()) { const auto type(robotE.attribute("type", "thymio2")); auto typeIt(robotTypes.find(type.toStdString())); if (typeIt != robotTypes.end()) { // retrieve informations const auto& cppTypeName(typeIt->second.prettyName); const auto qTypeName(QString::fromStdString(cppTypeName)); auto& countOfThisType(typeIt->second.number); const auto qRobotNameRaw(robotE.attribute("name", QString("%1 %2").arg(qTypeName).arg(countOfThisType))); const auto qRobotNameFull(QObject::tr("%2 on %3").arg(qRobotNameRaw).arg(QHostInfo::localHostName())); const auto cppRobotName(qRobotNameFull.toStdString()); const unsigned port(robotE.attribute("port", QString("%1").arg(ASEBA_DEFAULT_PORT+asebaServerCount)).toUInt()); const int16_t nodeId(robotE.attribute("nodeId", "1").toInt()); // create const auto& creator(typeIt->second.factory); #ifdef ZEROCONF_SUPPORT auto robot(creator(zeroconf, port, cppRobotName, cppTypeName, nodeId)); #else // ZEROCONF_SUPPORT auto robot(creator(port, cppRobotName, cppTypeName, nodeId)); #endif // ZEROCONF_SUPPORT asebaServerCount++; countOfThisType++; // setup in the world robot->pos.x = robotE.attribute("x").toDouble(); robot->pos.y = robotE.attribute("y").toDouble(); robot->angle = robotE.attribute("angle").toDouble(); world.addObject(robot); // log viewer.log(app.tr("New robot %0 of type %1 on port %2").arg(qRobotNameRaw).arg(qTypeName).arg(port), Qt::white); } else viewer.log("Error, unknown robot type " + type, Qt::red); robotE = robotE.nextSiblingElement ("robot"); } // Scan for external processes QList<QProcess*> processes; QDomElement procssE(domDocument.documentElement().firstChildElement("process")); while (!procssE.isNull()) { QString command(procssE.attribute("command")); // create process processes.push_back(new QProcess()); processes.back()->setProcessChannelMode(QProcess::MergedChannels); // make sure it is killed when we close the window QObject::connect(processes.back(), SIGNAL(started()), &viewer, SLOT(processStarted())); QObject::connect(processes.back(), SIGNAL(error(QProcess::ProcessError)), &viewer, SLOT(processError(QProcess::ProcessError))); QObject::connect(processes.back(), SIGNAL(readyReadStandardOutput()), &viewer, SLOT(processReadyRead())); QObject::connect(processes.back(), SIGNAL(finished(int, QProcess::ExitStatus)), &viewer, SLOT(processFinished(int, QProcess::ExitStatus))); // check whether it is a relative command bool isRelative(false); if (!command.isEmpty() && command[0] == ':') { isRelative = true; command = command.mid(1); } // process the command into its components QStringList args(command.split(" ", QString::SkipEmptyParts)); if (args.size() == 0) { viewer.log(app.tr("Missing program in command"), Qt::red); } else { const QString program(QDir::toNativeSeparators(args[0])); args.pop_front(); if (isRelative) processes.back()->start(QCoreApplication::applicationDirPath() + QDir::separator() + program, args, QIODevice::ReadOnly); else processes.back()->start(program, args, QIODevice::ReadOnly); } procssE = procssE.nextSiblingElement("process"); } // Show and run viewer.setWindowTitle(app.tr("Aseba Playground - Simulate your robots!")); viewer.show(); // If D-Bus is used, register the viewer object #ifdef HAVE_DBUS new Enki::EnkiWorldInterface(&viewer); QDBusConnection::sessionBus().registerObject("/world", &viewer); QDBusConnection::sessionBus().registerService("ch.epfl.mobots.AsebaPlayground"); #endif // HAVE_DBUS // Run the application const int exitValue(app.exec()); // Stop and delete ongoing processes foreach(QProcess*process,processes) { process->terminate(); if (!process->waitForFinished(1000)) process->kill(); delete process; }
void TEnkiEnvironment::makeGnuplotScriptAndRunIt(std::string graphFilename, double xmin, double xmax, double ymin, double ymax) { // Чтобы замкнуть линии в гнуплоте std::set<Enki::PhysicalObject *>objects = world->objects; std::set<Enki::PhysicalObject *>::iterator someObject; for (someObject=objects.begin(); someObject!=objects.end(); ++someObject) { Enki::PhysicalObject * actualObject = *someObject; if (actualObject != ePuckBot) { ofstream objectsFile; stringstream buf; buf << "C:/enki-log-files/gnuplotObjects" << actualObject->objectNumber << ".txt"; objectsFile.open(buf.str().c_str()); objectsFile << actualObject->pos.x-cubeSize/2.0 << "\t" << actualObject->pos.y-cubeSize/2.0 << std::endl; objectsFile << actualObject->pos.x-cubeSize/2.0 << "\t" << actualObject->pos.y+cubeSize/2.0 << std::endl; objectsFile << actualObject->pos.x+cubeSize/2.0 << "\t" << actualObject->pos.y+cubeSize/2.0 << std::endl; objectsFile << actualObject->pos.x+cubeSize/2.0 << "\t" << actualObject->pos.y-cubeSize/2.0 << std::endl; objectsFile << actualObject->pos.x-cubeSize/2.0 << "\t" << actualObject->pos.y-cubeSize/2.0 << std::endl; objectsFile.close(); } } ofstream gnuplotGraphFile; gnuplotGraphFile.open((graphFilename).c_str()); gnuplotGraphFile << "set terminal pdf size 10cm," << 10*(ymax-ymin)/(xmax-xmin) << "cm font 'Times-New-Roman,5'" << std::endl; gnuplotGraphFile << "set output '" << graphFilename << ".pdf'" << std::endl; gnuplotGraphFile << "set xtics " << static_cast<int>(xmin) <<",50," << static_cast<int>(xmax) << std::endl; gnuplotGraphFile << "set ytics " << static_cast<int>(ymin) <<",50," << static_cast<int>(ymax) << std::endl; gnuplotGraphFile << "set mxtics 5\nset mytics 5" << std::endl; gnuplotGraphFile << "set grid xtics ytics mytics mxtics lt 1 lw 1 linecolor rgb \"gray\"" << std::endl; gnuplotGraphFile << "set palette defined ( 0 \"#660099\", 1 \"#0000CC\", 2 \"#3399FF\", 3 \"#00CC00\", 4 \"#FFFF33\", 5 \"#FF6600\", 6 \"#CC0000\" )" << std::endl; gnuplotGraphFile << "unset colorbox" << std::endl; std::string objectsColorsStrings[10]; for (someObject=objects.begin(); someObject!=objects.end(); ++someObject) { Enki::PhysicalObject * actualObject = *someObject; if (actualObject->objectNumber >= 0) { const Enki::Color objectColor = actualObject->getColor(); std::string rColor = "00"; if (objectColor.components[0] == 1.0) { rColor = "FF"; } std::string gColor = "00"; if (objectColor.components[1] == 1.0) { gColor = "FF"; } std::string bColor = "00"; if (objectColor.components[2] == 1.0) { bColor = "FF"; } objectsColorsStrings[actualObject->objectNumber] = "#" + rColor + gColor + bColor; /*if ((objectColor.components[0] == 1.0) && (objectColor.components[1] == 0.0) && (objectColor.components[2] == 0.0)) { objectsColorsStrings[actualObject->objectNumber] = "red"; } else if ((objectColor.components[0] == 1.0) && (objectColor.components[1] == 1.0) && (objectColor.components[2] == 0.0)) { objectsColorsStrings[actualObject->objectNumber] = "yellow"; } else if ((objectColor.components[0] == 0.0) && (objectColor.components[1] == 1.0) && (objectColor.components[2] == 0.0)) { objectsColorsStrings[actualObject->objectNumber] = "green"; } else if ((objectColor.components[0] == 0.0) && (objectColor.components[1] == 0.0) && (objectColor.components[2] == 1.0)) { objectsColorsStrings[actualObject->objectNumber] = "blue"; }*/ } } gnuplotGraphFile << "plot " << "[" << static_cast<int>(xmin) << ":" << static_cast<int>(xmax) << "] " << "[" << static_cast<int>(ymin) << ":" << static_cast<int>(ymax) << "] " << "'" << gnuplotOutputString << "'" << " u 1:2:(0.2):3 with circles palette notitle, "; for (int i = 0; i < 10; i++) { if (objectsColorsStrings[i].length()) { if (i>=1) { gnuplotGraphFile << ", "; } gnuplotGraphFile << "'C:/enki-log-files/gnuplotObjects" << i << ".txt' with filledcurves notitle linecolor rgb \"" << objectsColorsStrings[i].c_str() << "\""; } else { break; } } gnuplotGraphFile << std::endl; /*<< "'C:/enki-log-files/gnuplotObjects1.txt' with filledcurves notitle linecolor rgb \"" << objectsColorsStrings[0] << "\", " << "'C:/enki-log-files/gnuplotObjects2.txt' with filledcurves notitle linecolor rgb \"" << objectsColorsStrings[1] << "\", " << "'C:/enki-log-files/gnuplotObjects3.txt' with filledcurves notitle linecolor rgb \"" << objectsColorsStrings[2] << "\", " << "'C:/enki-log-files/gnuplotObjects4.txt' with filledcurves notitle linecolor rgb \"" << objectsColorsStrings[3] << "\", " << std::endl;*/ //gnuplotGraphFile << "__EOF" << std::endl; gnuplotGraphFile.close(); //system(("chmod +x "+graphFilename+".sh").c_str()); system(("gnuplot "+graphFilename).c_str()); }
void TEnkiEnvironment::loadEnvironment(std::string environmentFilename) { // Получаем параметры среды из файла std::ifstream environmentFile; environmentFile.open(environmentFilename.c_str()); string tmp_str; environmentFile >> tmp_str; // Считываем размеры прямоугольной арены xSize = atof(tmp_str.c_str()); environmentFile >> tmp_str; ySize = atof(tmp_str.c_str()); environmentFile >> tmp_str; xBirthMin = atof(tmp_str.c_str()); environmentFile >> tmp_str; xBirthMax = atof(tmp_str.c_str()); environmentFile >> tmp_str; yBirthMin = atof(tmp_str.c_str()); environmentFile >> tmp_str; yBirthMax = atof(tmp_str.c_str()); environmentFile >> tmp_str; // Считываем количество объектов в среде (по умолчанию - кубы) objectsNumber = atoi(tmp_str.c_str()); for (int i=0; i<objectsNumber; i++) { // Заполняем массив объектов, каждый из которых имеет позицию своего центра и цвет TEnkiObject someNewObject = TEnkiObject(); environmentFile >> tmp_str; someNewObject.x = atof(tmp_str.c_str()); environmentFile >> tmp_str; someNewObject.y = atof(tmp_str.c_str()); environmentFile >> tmp_str; someNewObject.color[0] = atof(tmp_str.c_str()); environmentFile >> tmp_str; someNewObject.color[1] = atof(tmp_str.c_str()); environmentFile >> tmp_str; someNewObject.color[2] = atof(tmp_str.c_str()); objectsArray.push_back(someNewObject); } environmentFile >> tmp_str; goalsNumber = atoi(tmp_str.c_str()); // Считываем количество целей for (int i=0; i<goalsNumber; i++) { // Заполняем массив целей, каждая из которых имеет длину последовательности, награду и саму последовательность посещения объектов TEnkiAim someNewAim = TEnkiAim(); environmentFile >> tmp_str; someNewAim.aimComplexity = atoi(tmp_str.c_str()); if (someNewAim.aimComplexity > someNewAim.MAX_AIM_COMPLEXITY) { cout << "Warning in TEnkiEnvironment: aim complexity can't be greater than the MAX_AIM_COMPLEXITY. Setting it to the MAX_AIM_COMPLEXITY by force now to avoid crash."; someNewAim.aimComplexity = someNewAim.MAX_AIM_COMPLEXITY; } environmentFile >> tmp_str; someNewAim.reward = atof(tmp_str.c_str()); for (int j=0; j<someNewAim.aimComplexity; j++) { environmentFile >> tmp_str; someNewAim.actionsSequence[j] = atoi(tmp_str.c_str()); if (someNewAim.actionsSequence[j] > objectsNumber) { cout << "Warning in TEnkiEnvironment: action number can't be greater than the number of objects. Setting it to the number of objects by force now to avoid crash."; someNewAim.actionsSequence[j] = objectsNumber; } } goalsArray.push_back(someNewAim); } //Переходим к постройке мира исходя из параметров, полученных из файла // Создаем саму арену world = new Enki::World(xSize, ySize, Enki::Color(0.1, 0.1, 0.1)); // Создаем объекты Enki::Polygone p2; p2.push_back(Enki::Point(cubeSize/2.0,cubeSize/2.0)); p2.push_back(Enki::Point(-cubeSize/2.0,cubeSize/2.0)); p2.push_back(Enki::Point(-cubeSize/2.0,-cubeSize/2.0)); p2.push_back(Enki::Point(cubeSize/2.0,-cubeSize/2.0)); for (int i = 0; i < objectsNumber; i++) { Enki::PhysicalObject* o = new Enki::PhysicalObject; Enki::PhysicalObject::Hull hull(Enki::PhysicalObject::Part(p2, cubeSize)); o->setCustomHull(hull, -100000); // Отрицательная масса - то же, что бесконечная, поэтому объекты сдвинуть с места будет невозможно o->setColor(Enki::Color(objectsArray.at(i).color[0]/255.0, objectsArray.at(i).color[1]/255.0, objectsArray.at(i).color[2]/255.0 )); o->collisionElasticity = 0; // Все тепло от столкновения поглощается o->pos = Enki::Point(objectsArray.at(i).x, objectsArray.at(i).y); o->objectNumber = i; world->addObject(o); //objectsInTheWorld.push_back(o); } // Создаем E-PUCK и размещаем его в среде ePuckBot = new Enki::EPuck(); ePuckBot->pos = Enki::Point(4.0, 4.0); ePuckBot->angle = 0; ePuckBot->leftSpeed = 0; ePuckBot->rightSpeed = 0; ePuckBot->objectNumber = -1; ePuckBot->setColor(Enki::Color(1, 0, 0)); world->addObject(ePuckBot); }