| Prev: Customizing the environment | Up: Customizing the environment | Next: The Worldsim Library |
|---|---|---|
Table of contents
The Arena component can be used to set-up the environment for experiments involving wheeled robots. It allows the user to easily create a flat planar surface containing objects like walls, cylinders, boxes, target areas (i.e. portion of the floor painted with a specific color) and light bulbs. For an example, see the picture below (the object in the center is a Khepera robot).

The example below show the portion of a configuration file in which the Arena component is declared and configured. The main aspects that can be specified parametrically are the width and the height of the planar surface (expressed in meters) and the method used for handling the collisions. All other aspects should be defined and configured in the source code of the experimental plugin.
:::INI
[Component/GA/Experiment/Arena]
type = Arena
collisionHandler = SimpleCollisions
planeHeight = 8.0
planeWidth = 3.0
The Arena component supports two kind of collision handling, SimpleCollisions and CircleCollisions. The former is a fast and approximate implementation that only handles collisions of robots. When a robot collides, it is simply moved back to the position it had before the collision. CircleCollisions, instead, handles collision among circular objects (both robots and cylinders) and computes the results of the collision taking into account the relative masses of the interested objects. Beware that this algorithm is still experimental and not thoroughly checked.
The source code included below shows how you can create, modify, access and delete the objects located in the environment.
:::C++
// This exemplificative function show how you can (i) create, (ii) modify,
// (iii) access and (iv) delete the objects located in the environment. Here we
// have assumed that the "using namespace farsa;" instruction is included at the
// beginning of the file containing this function
void MyExperiment::setupArena()
{
// ------------- arena ---------------------------
// Acquiring lock on the resources to be able to access the arena component
ResourcesLocker locker(this);
// Getting the arena
// Notice that the size of the arena plane can be set in the .ini file
// throught the planeHeight and planeWidth parameters of the arena component
Arena* arena = getResource<Arena>("arena");
// Set the colour of the arena plane
arena->getPlane()->setColor(Qt::white);
// Create four walls that surrounds a rectangular areas of 96x76cm located in the central part of the arena
// the wall are coloured in yellow, red, green, and black, respectively, have a tickness of 4cm, and a height of 5cm
// walls by default are static object, i.e. object that cannot be moved
// the blackwall variable is a pointer that allows to later access the black wall object
arena->createWall(Qt::yellow, wVector(-0.50, 0.4, 0.0), wVector(0.50, 0.4, 0.0), 0.04, 0.05);
arena->createWall(Qt::red, wVector(-0.50, -0.4, 0.0), wVector(0.50, -0.4, 0.0), 0.04, 0.05);
arena->createWall(Qt::green, wVector(0.48, -0.38, 0.0), wVector(0.48, 0.38, 0.0), 0.04, 0.05);
Box2DWrapper* blackwall;
blackwall = arena->createWall(Qt::black, wVector(-0.48, -0.38, 0.0), wVector(-0.48, 0.38, 0.0), 0.04, 0.05);
// Create a small blue cylinder (radius 1.25 cm) with a height of 8 cm
// Set the object as a static object that cannot be moved (the default is non static)
// Then move the barycentre of the objct in a specific XY postion of the plane
// The smallbluecyl variable is a pointer to the object that can be used to later access and/or vary the object properties
Cylinder2DWrapper* smallbluecyl;
smallbluecyl = arena->createSmallCylinder(Qt::blue, 0.08);
smallbluecyl->setStatic(true);
smallbluecyl->setPosition(0.2, 0.2);
// Create a large red cylinder (radius 2.7 cm) with aheight of 5 cm
// Set the object as a non static object that can be moved
// Then move the barycentre of the objct in a specific XY position of the plane
// The largebrowncyl variable is a pointer to the object that can be used to later access and/or vary the object properties
Cylinder2DWrapper* largeredcyl;
largeredcyl = arena->createBigCylinder(Qt::red, 0.05);
largeredcyl->setStatic(false);
largeredcyl->setPosition(-0.2, -0.2);
// Create a light grey circular target area (a circular portion of the arena with a specific color) with a radius of 20 cm
// Target areas are always static (non movable objects)
// Then set the barycentre of the area in a specific XY position of the plane
Cylinder2DWrapper* circulararea;
circulararea = arena->createCircularTargetArea(0.09, QColor(200,200,200,255));
circulararea->setPosition(0.27, -0.27);
// Create a dark grey rectangular target area (a rectangular portion of the arena with a specific color) 30cmx10cm wide
// Target areas are always static (non movable objects)
// Then set the centre of the area in a specific XY position of the plane
Box2DWrapper* rectangulararea;
rectangulararea = arena->createRectangularTargetArea(0.3, 0.1, QColor(100,100,100,255));
rectangulararea-> setPosition(-0.2, -0.1);
// Create a light bulb (i.e. an object emitting light the can be detected through ambient light sensors)
// Light bulbs are static (non movable) and virtual (non-physical) objects
// Then set the position of the object over the plane
Sphere2DWrapper* lightbulb;
lightbulb = arena->createLightBulb(Qt::yellow);
lightbulb->setPosition(-0.2, -0.3);
// We now show how you can access to objects that has been defined
// (including the robot object) and to they properties
// For objects for which you have a pointer, you can access to the properties of the object directly
// For example below you can see how you can retrive the properties of the circular target area
wVector pos = circulararea->position();
Logger::info(QString("-= circular target area, pos (xyz) %1 %2 %3").arg(pos.x).arg(pos.y).arg(pos.z));
// For all defined objects, for which you have or you have not a local pointer,
// you can retrive them from the arena object list
const QVector<PhyObject2DWrapper*>& objectsList = arena->getObjects();
// foreach is a QT macro
foreach(PhyObject2DWrapper* obj, objectsList) {
switch (obj->type()) {
// the plane of the arena
case PhyObject2DWrapper::Plane: {
Box2DWrapper* plane = dynamic_cast<Box2DWrapper*>(obj);
// Common properties
bool isStatic = plane->getStatic();
wVector pos = plane->position();
QString texture = plane->texture();
QColor color = plane->color();
// Box properties
wVector v0 = plane->vertex(0);
wVector v1 = plane->vertex(1);
wVector v2 = plane->vertex(2);
wVector v3 = plane->vertex(3);
wVector center = plane->centerOnPlane();
Logger::info(QString("-= Plane =- %1, position %2, texture: %3, color: %4, v0: %5, v1: %6, v2: %7, v3: %8, center: %9").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(v0).arg(v1).arg(v2).arg(v3).arg(center));
} break;
// wall objects
case PhyObject2DWrapper::Wall: {
Box2DWrapper* wall = dynamic_cast<Box2DWrapper*>(obj);
// Common properties
bool isStatic = wall->getStatic();
wVector pos = wall->position();
QString texture = wall->texture();
QColor color = wall->color();
// Box properties
wVector v0 = wall->vertex(0);
wVector v1 = wall->vertex(1);
wVector v2 = wall->vertex(2);
wVector v3 = wall->vertex(3);
wVector center = wall->centerOnPlane();
Logger::info(QString("-= Wall =- %1, position %2, texture: %3, color: %4, v0: %5, v1: %6, v2: %7, v3: %8, center: %9").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(v0).arg(v1).arg(v2).arg(v3).arg(center));
} break;
// box object (notice this cannot be used in conjunction with sampled infrared sensors)
case PhyObject2DWrapper::Box: {
Box2DWrapper* box = dynamic_cast<Box2DWrapper*>(obj);
// Common properties
bool isStatic = box->getStatic();
wVector pos = box->position();
QString texture = box->texture();
QColor color = box->color();
// Box properties
wVector v0 = box->vertex(0);
wVector v1 = box->vertex(1);
wVector v2 = box->vertex(2);
wVector v3 = box->vertex(3);
wVector center = box->centerOnPlane();
Logger::info(QString("-= Box =- %1, position %2, texture: %3, color: %4, v0: %5, v1: %6, v2: %7, v3: %8, center: %9").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(v0).arg(v1).arg(v2).arg(v3).arg(center));
} break;
// Cylindrical object (notice this cannot be used in conjunction with sampled infrared sensors)
case PhyObject2DWrapper::Cylinder: {
Cylinder2DWrapper* cylinder = dynamic_cast<Cylinder2DWrapper*>(obj);
// Common properties
bool isStatic = cylinder->getStatic();
wVector pos = cylinder->position();
QString texture = cylinder->texture();
QColor color = cylinder->color();
// Cylinder properties
real radius = cylinder->radius();
Logger::info(QString("-= Cylinder =- %1, position %2, texture: %3, color: %4, radius: %5").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(radius));
} break;
// small cylindrical object
case farsa::PhyObject2DWrapper::SmallCylinder: {
const farsa::Cylinder2DWrapper* smallCylinder = dynamic_cast<const farsa::Cylinder2DWrapper*>(obj);
// Common properties
bool isStatic = smallCylinder->getStatic();
farsa::wVector pos = smallCylinder->position();
QString texture = smallCylinder->texture();
QColor color = smallCylinder->color();
// Cylinder properties
farsa::real radius = smallCylinder->radius();
farsa::Logger::info(QString("-= SmallCylinder =- %1, position %2, texture: %3, color: %4, radius: %5").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(radius));
} break;
// large cylindrical object
case PhyObject2DWrapper::BigCylinder: {
Cylinder2DWrapper* bigCylinder = dynamic_cast<Cylinder2DWrapper*>(obj);
// Common propertiesv
bool isStatic = bigCylinder->getStatic();
wVector pos = bigCylinder->position();
QString texture = bigCylinder->texture();
QColor color = bigCylinder->color();
// Cylinder properties
real radius = bigCylinder->radius();
Logger::info(QString("-= BigCylinder =- %1, position %2, texture: %3, color: %4, radius: %5").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(radius));
} break;
// target area (i.e. painted portion of the floor)
case PhyObject2DWrapper::RectangularTargetArea: {
Box2DWrapper* rectangularTargetArea = dynamic_cast<Box2DWrapper*>(obj);
// Common properties
bool isStatic = rectangularTargetArea->getStatic();
wVector pos = rectangularTargetArea->position();
QString texture = rectangularTargetArea->texture();
QColor color = rectangularTargetArea->color();
// Box properties
wVector v0 = rectangularTargetArea->vertex(0);
wVector v1 = rectangularTargetArea->vertex(1);
wVector v2 = rectangularTargetArea->vertex(2);
wVector v3 = rectangularTargetArea->vertex(3);
wVector center = rectangularTargetArea->centerOnPlane();
Logger::info(QString("-= RectangularTargetArea =- %1, position %2, texture: %3, color: %4, v0: %5, v1: %6, v2: %7, v3: %8, center: %9").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(v0).arg(v1).arg(v2).arg(v3).arg(center));
} break;
// circular target area (i.e. painted portion of the floor)
case PhyObject2DWrapper::CircularTargetArea: {
Cylinder2DWrapper* circularTargetArea = dynamic_cast<Cylinder2DWrapper*>(obj);
// Common properties
bool isStatic = circularTargetArea->getStatic();
wVector pos = circularTargetArea->position();
QString texture = circularTargetArea->texture();
QColor color = circularTargetArea->color();
// Cylinder properties
real radius = circularTargetArea->radius();
Logger::info(QString("-= CircularTargetArea =- %1, position %2, texture: %3, color: %4, radius: %5").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(radius));
} break;
// light bulb
case PhyObject2DWrapper::LightBulb: {
Sphere2DWrapper* lightBulb = dynamic_cast<Sphere2DWrapper*>(obj);
// Common properties
bool isStatic = lightBulb->getStatic();
wVector pos = lightBulb->position();
QString texture = lightBulb->texture();
QColor color = lightBulb->color();
Logger::info(QString("-= LightBulb =- %1, position %2, texture: %3, color: %4").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()));
} break;
// wheeled robot
case PhyObject2DWrapper::WheeledRobot: {
WheeledRobot2DWrapper* wheeledRobot = dynamic_cast<WheeledRobot2DWrapper*>(obj);
// Common properties
bool isStatic = wheeledRobot->getStatic();
wVector pos = wheeledRobot->position();
QString texture = wheeledRobot->texture();
QColor color = wheeledRobot->color();
// Wheeled robot properties
real height = wheeledRobot->getHeight();
real radius = wheeledRobot->getRadius();
Logger::info(QString("-= WheeledRobot =- %1, position %2, texture: %3, color: %4, height: %5, radius: %6").arg(isStatic ? "static" : "not static").arg(pos).arg(texture).arg(color.name()).arg(height).arg(radius));
} break;
default:
Logger::info("Unrecognized object!");
}
}
// For objects for which you have a pointer, you can delete it directly
// For example below you see how you can delete the circular target area
arena->delete2DObject(circulararea);
}
The execution of this function produce the following text output:
-= circular target area, pos (xyz) 0.27 -0.27 0
[04-12-2013 15:57:18.252] INFO : -= Plane =- static, position [0, 0, -0.05, 1], texture: tile2, color: #ffffff, v0: [0.5, 0.5, -0.1, 1], v1: [0.5, -0.5, -0.1, 1], v2: [-0.5, 0.5, -0.1, 1], v3: [-0.5, -0.5, -0.1, 1], center: [0, 0, -0.1, 1]
-= WheeledRobot =- static, position [0, 0, 0, 1], texture: tile2, color: #ffffff, height: 0.0315, radius: 0.035
-= Wall =- static, position [0, 0.4, 0.025, 1], texture: tile2, color: #ffff00, v0: [0.5, 0.02, 0, 1], v1: [0.5, -0.02, 0, 1], v2: [-0.5, 0.02, 0, 1], v3: [-0.5, -0.02, 0, 1], center: [0, 0, 0, 1]
-= Wall =- static, position [0, -0.4, 0.025, 1], texture: tile2, color: #ff0000, v0: [0.5, 0.02, 0, 1], v1: [0.5, -0.02, 0, 1], v2: [-0.5, 0.02, 0, 1], v3: [-0.5, -0.02, 0, 1], center: [0, 0, 0, 1]
-= Wall =- static, position [0.48, 0, 0.025, 1], texture: tile2, color: #00ff00, v0: [0.38, 0.02, 0, 1], v1: [0.38, -0.02, 0, 1], v2: [-0.38, 0.02, 0, 1], v3: [-0.38, -0.02, 0, 1], center: [0, 0, 0, 1]
-= Wall =- static, position [-0.48, 0, 0.025, 1], texture: tile2, color: #000000, v0: [0.38, 0.02, 0, 1], v1: [0.38, -0.02, 0, 1], v2: [-0.38, 0.02, 0, 1], v3: [-0.38, -0.02, 0, 1], center: [0, 0, 0, 1]
-= SmallCylinder =- static, position [0.2, 0.2, 0.04, 1], texture: , color: #0000ff, radius: 0.0125
-= BigCylinder =- not static, position [-0.2, -0.2, 0.025, 1], texture: , color: #ff0000, radius: 0.027
-= CircularTargetArea =- static, position [0.27, -0.27, 0, 1], texture: , color: #c8c8c8, radius: 0.09
-= RectangularTargetArea =- static, position [-0.2, -0.1, 0, 1], texture: , color: #646464, v0: [-0.05, -0.05, -0.005, 1], v1: [-0.05, -0.15, -0.005, 1], v2: [-0.35, -0.05, -0.005, 1], v3: [-0.35, -0.15, -0.005, 1], center: [-0.2, -0.1, -0.005, 1]
-= LightBulb =- not static, position [-0.2, -0.3, 0.01, 1], texture: , color: #ffff00
Manual: CreatingNewExperiment
Manual: CustomizeEnvironment
Manual: Home
Manual: Worldsim
Anonymous