ExplorationMap


level_3


What is it

An ExplorationMap represents a description of Pepper’s environment, used by Pepper to localize itself relatively to his surroundings.

How to use it

Dumping an ExplorationMap

An ExplorationMap is obtained by dumping a representation of the environment Pepper has explored during the run of a LocalizeAndMap action.

// Build a LocalizeAndMap action.
val localizeAndMap: LocalizeAndMap = ...

// Run it.
localizeAndMap.async().run()

// When localized, dump the current description of the explored environment.
val explorationMap: ExplorationMap = localizeAndMap.dumpMap()
// Build a LocalizeAndMap action.
LocalizeAndMap localizeAndMap = ...;

// Run it.
localizeAndMap.async().run();

// When localized, dump the current description of the explored environment.
ExplorationMap explorationMap = localizeAndMap.dumpMap();

Localizing inside an ExplorationMap

The ExplorationMap can then be used by a Localize action, so that Pepper keeps track of his position relatively to where he was when he started the LocalizeAndMap action.

// Get an exploration map.
val explorationMap: ExplorationMap = ...

// Build a Localize action.
val localize: Localize = LocalizeBuilder.with(qiContext)
                              .withMap(explorationMap)
                              .build()
// Get an exploration map.
ExplorationMap explorationMap = ...;

// Build a Localize action.
Localize localize = LocalizeBuilder.with(qiContext)
                                   .withMap(explorationMap)
                                   .build();

Saving ExplorationMap content for future use

An ExplorationMap can be serialized to text, for example to save it to a file and store it persistently.

// Get an exploration map.
val explorationMap: ExplorationMap = ...

// Serialize the ExplorationMap data.
val mapData: String = explorationMap.serialize()
// Get an exploration map.
ExplorationMap explorationMap = ...;

// Serialize the ExplorationMap data.
String mapData = explorationMap.serialize();

level_7

An ExplorationMap can also be converted to a StreamableBuffer.

// Get an exploration map.
val explorationMap: ExplorationMap = ...

// Convert the ExplorationMap to StreamableBuffer.
val streamableBuffer: StreamableBuffer = explorationMap.serializeAsStreamableBuffer()
// Get an exploration map.
ExplorationMap explorationMap = ...;

// Convert the ExplorationMap to StreamableBuffer.
StreamableBuffer streamableBuffer = explorationMap.serializeAsStreamableBuffer();

Important

The StreamableBuffer conversion should be preferred over the String conversion, as it prevents OutOfMemoryError due to loading the entire ExplorationMap data at once.

Loading an ExplorationMap from its content

To re-use the content of a serialized ExplorationMap, one can build a new ExplorationMap object from the content.

// Retrieve a serialized ExplorationMap.
val mapData: String = ...

// Build a new ExplorationMap.
val explorationMap: ExplorationMap = ExplorationMapBuilder.with(qiContext)
                                          .withMapString(mapData)
                                          .build()
// Retrieve a serialized ExplorationMap.
String mapData = ...;

// Build a new ExplorationMap.
ExplorationMap explorationMap = ExplorationMapBuilder.with(qiContext)
                                                     .withMapString(mapData)
                                                     .build();

level_7

One can also build an ExplorationMap from a StreamableBuffer.

// Retrieve a StreamableBuffer.
val streamableBuffer: StreamableBuffer = ...

// Build a new ExplorationMap.
val explorationMap: ExplorationMap = ExplorationMapBuilder.with(qiContext)
                                          .withStreamableBuffer(streamableBuffer)
                                          .build()
// Retrieve a StreamableBuffer.
StreamableBuffer streamableBuffer = ...;

// Build a new ExplorationMap.
ExplorationMap explorationMap = ExplorationMapBuilder.with(qiContext)
                                                     .withStreamableBuffer(streamableBuffer)
                                                     .build();

Displaying a map

level_7

It is possible to display the result of the ExplorationMap on a UI.

The image is stored in an EncodedImage.

../../../_images/mapGUI.png
val explorationMap: ExplorationMap = ...

// Get the image data
val mapGraphicalRepresentation: MapTopGraphicalRepresentation =
    explorationMap.topGraphicalRepresentation
val encodedImage: EncodedImage = mapGraphicalRepresentation.image
ExplorationMap explorationMap = ...

// Get the image data
MapTopGraphicalRepresentation mapGraphicalRepresentation =
    explorationMap.getTopGraphicalRepresentation();
EncodedImage encodedImage = mapGraphicalRepresentation.getImage();

The coordinates in an image and those in the mapFrame are not in the same frame of reference. To compute the change of one referential to another, 4 parameters are given:

  • x: abscissa of image top left corner in map frame in meters
  • y: ordinate of image top left corner in map frame in meters
  • \(\theta\): rotation of the image x-axis from the map frame x-axis
  • scale: size of one pixel of the image in meters
../../../_images/imageDoc.svg

To get the position in mapFrame of a point from its pixels coordinate \((x_{img}, y_{img})\) , use:

\[x_{map} = scale * (cos(\theta) * x_{img} + sin(\theta) * y_{img}) + x\]
\[y_{map} = scale * (sin(\theta) * x_{img} - cos(\theta) * y_{img}) + y\]

To retrieve pixels coordinates of a point from its coordinates \((x_{map}, y_{map})\) in ExplorationMap, use:

\[x_{img} = 1/scale * (cos(\theta) * (x_{map} - x) + sin(\theta) * (y_{map}-y))\]
\[y_{img} = 1/scale * (sin(\theta) * (x_{map} - x) - cos(\theta) * (y_{map}-y))\]

For example, if you want to display on the image of the map a point which is 2 meters in front of mapFrame, (\(x_{map} = 2.0, y_{map} = 0.0\)), you need to get its coordinates in pixel:

fun getPixelFromMapPosition(xMap: Float, yMap: Float,
    mapGraphicalRepresentation: MapTopGraphicalRepresentation): Pair<Int, Int> {

  val scale: Float = mapGraphicalRepresentation.scale
  val theta: Float = mapGraphicalRepresentation.theta
  val x = mapGraphicalRepresentation.x
  val y = mapGraphicalRepresentation.y

  val xPixel = (1 / scale * (cos(theta) * (xMap - x) + sin(theta) * (yMap - y))).toInt()
  val yPixel = (1 / scale * (sin(theta) * (xMap - x) - cos(theta) * (yMap - y))).toInt()
  return Pair(xPixel, yPixel)
}

val mapGraphicalRepresentation: MapTopGraphicalRepresentation =
    explorationMap.topGraphicalRepresentation
val (xPixel, yPixel) = getPixelFromMapPosition(2.0f, 0.0f, mapGraphicalRepresentation)
public Pair<Integer, Integer> getPixelFromMapPosition(float xMap, float yMap, MapTopGraphicalRepresentation mapGraphicalRepresentation) {
    float scale = mapGraphicalRepresentation.getScale();
    float theta = mapGraphicalRepresentation.getTheta();
    float x = mapGraphicalRepresentation.getX();
    float y = mapGraphicalRepresentation.getY();

    int xPixel = (int) (1 / scale * (cos(theta) * (xMap - x) + sin(theta) * (yMap - y)));
    int yPixel = (int) (1 / scale * (sin(theta) * (xMap - x) - cos(theta) * (yMap - y)));
    return new Pair<>(xPixel, yPixel);
}


MapTopGraphicalRepresentation mapGraphicalRepresentation =
    explorationMap.getTopGraphicalRepresentation();
Pair<Integer, Integer> pixelCoordinates =
    getPixelFromMapPosition(2.0f, 0.0f, mapGraphicalRepresentation);

Performance and limitations

The format of a map is not definitive and may change as improvements are made to this functionality. It is advised to remap the environment after a system upgrade.

A map, made by a robot may be shared with another robot provided that their hardware are fully compatible.

See also