API

Vector

A type alias for Tuple[float, float] as (x, y).

Polygon

A type alias for Iterable[Vector], where points should be ordered counter-clockwise.

Part

A type alias for Union[Tuple[Polygon, float], Tuple[Polygon, float, Iterable[Color]]] representing a convex right prism as (base, height) or (base, heigh, side_color), where side_color and base must have the same length.

Warning

At the moment textures (side_color) are used to compute the sensors (cameras) response but are ignored when displaying the object.

Color

class pyenki.Color(r: float = 0.0, g: float = 0.0, b: float = 0.0, a: float = 1.0)

An RGBA color with values between 0.0 and 1.0.

Parameters
  • r (float) – Red channel, in [0, 1], optional (default 0.0)

  • g (float) – Green channel, in [0, 1], optional (default 0.0)

  • b (float) – Blue channel, in [0, 1], optional (default 0.0)

  • a (float) – Alpha channel, in [0, 1], optional (default 1.0)

black

Black color (readonly)

Type

Color

gray

Gray color (readonly)

Type

Color

white

White color (readonly)

Type

Color

red

Red color (readonly)

Type

Color

green

Green color (readonly)

Type

Color

blue

Blue color (readonly)

Type

Color

r

Red channel, in [0, 1]

Type

float

g

Green channel, in [0, 1]

Type

float

b

Blue channel, in [0, 1]

Type

float

a

Alpha channel, in [0, 1]

Type

float

components

Components, in [0, 1]

Type

Tuple[float, float, float, float]

PhysicalObject

class pyenki.PhysicalObject

The superclass of objects that can be simulated.

position

The position in the world frame in centimeters

Type

Tuple[float, float]

angle

The orientation in the world frame in radians

Type

float

velocity

The velocity in the world frame in centimeters per second

Type

Tuple[float, float]

angular_speed

The angular speed in the world frame in radians per second

Type

float

radius

The radius of the object’s enclosing circle in centimeters

Type

float

height

The object height in centimeters

Type

float

is_cylindric

True if the object is cylindrical shaped.

Type

bool

mass

The object mass in kilograms. If below zero, the object is static.

Type

float

moment_of_inertia

The obejct moment of inertial [Note: this is a symmetrical simplification.]

Type

float

color

The object color.

Type

Color

collision_elasticity

Elasticity of collisions of this object. If 0, soft collision, 100% energy dissipation; if 1, elastic collision, 0% energy dissipation. Actual elasticity is the product of the elasticity of the two colliding objects. Walls are fully elastics

Type

float

dry_friction_coefficient

The dry friction coefficient mu

Type

float

viscous_friction_coefficient

The viscous friction coefficient. Premultiplied by mass. A value of k applies a force of -k * speed * mass

Type

float

viscous_moment_friction_coefficient
Type

float

RectangularObject

class pyenki.RectangularObject(l1: float, l2: float, height: float, mass: float, color: pyenki.Color = None)

Create a PhysicalObject box with a given mass and color.

Parameters
  • l1 (float) – Depth in centimeters

  • l2 (float) – Width in centimeters

  • height (float) – Height in centimeters

  • mass (float) – Mass in kilograms

  • color (Color) – Color (default is black)

CircularObject

class pyenki.CircularObject(radius: float, height: float, mass: float, color: pyenki.Color = None)

Create a PhysicalObject cylinder with a given mass and color.

Parameters
  • radius (float) – Radius in centimeters

  • height (float) – Height in centimeters

  • mass (float) – Mass in kilograms

  • color (Color) – Color (default is black)

ConvexObject

class pyenki.ConvexObject(shape: Iterable[Tuple[float, float]], height: float, mass: float, color: pyenki.Color = None, side_color: Optional[Iterable[pyenki.Color]] = None)

Create a PhysicalObject with the shape of a right prism, specified by a convex polygonal base, height, mass and color.

The initializer does not check that the base is convex.

Parameters
  • shape (Polygon) – The shape of the convex base, specified by a counter-clockwise ordered points in centimeters.

  • height (float) – Height in centimeters

  • mass (float) – Mass in kilograms

  • color (Color) – Color (default is black)

  • side_color (Iterable[Color]) – Optional specification of one color per shape side (default is None): if the sizes do not correpond, color is used instead.

Example of a yellow, static, right triangular prism of height 1 cm:

import pyenki
triangle_shape = [(0.0, 0.0), (1.0, -1.0), (1.0, 1.0)]
triangle_object = pyenki.ConvexObject(triangle_shape, 1, -1, pyenki.Color(0.5, 0.5))

Example of a static, right triangular prism of height 1 cm with red, green, and blue sides:

import pyenki
triangle_shape = [(0.0, 0.0), (1.0, -1.0), (1.0, 1.0)]
triangle_colors = [pyenki.Color.red, pyenki.Color.green, pyenki.Color.blue]
triangle_object = pyenki.ConvexObject(triangle_shape, 1, -1, side_color=triangle_colors)

Warning

At the moment textures (side_color) are used to compute the sensors (cameras) response but are ignored when displaying the object.

CompositeObject

class pyenki.CompositeObject(parts: Iterable[Tuple[float, float]], height: float, mass: float, color: pyenki.Color = None)

Create a PhysicalObject as a collection of convex right prisms.

The initializer does not check that the prisms are all convex.

Parameters
  • parts (Iterable[Part]) – each part is defined by the convex base, the height in centimeters, and optionally the specification of one color per side. The shape of the convex bases are specified by counter-clockwise ordered points in centimeters.

  • mass (float) – Mass in kilograms

  • color (Color) – Color (default is black)

Example of a blue, static, C-shaped prism of constant height 1 cm:

import pyenki
c_parts = [
    ([(0, 1), (0, 0.5), (2, 0.5), (2, 1)], 1.0),
    ([(0, -0.5), (0, -1), (2, -1), (2, -0.5)], 1.0),
    ([(0, 0.5), (0, -0.5), (0.5, -0.5), (0.5, 0.5)], 1.0)
    ]
c_object = pyenki.CompositeObject(c_parts, -1, pyenki.Color(0, 0, 0.5))

Example of a static, right triangular prism of height 1 cm with red, green, and blue sides:

import pyenki
triangle_shape = [(0.0, 0.0), (1.0, -1.0), (1.0, 1.0)]
triangle_colors = [pyenki.Color.red, pyenki.Color.green, pyenki.Color.red]
triangle_object = pyenki.CompositeObject([(triangle_shape, 1, triangle_colors)], -1)

Warning

At the moment textures (side_color) are used to compute the sensors (cameras) response but are ignored when displaying the object.

IRCommEvent

class pyenki.IRCommEvent

An IRCommEvent is returned each time a message is received by at least one proximity sensor. The sensors that do not receive the message, have the corresponding payloads and intensities set to zero.

rx

The received message payload (readonly)

Type

int

payloads

A list of 7 payloads, one for each sensors (readonly). The first 5 entries are from frontal sensors ordered from left to right. The last two entries are from rear sensors ordered from left to right.

Type

List[int]

intensities

A list of 7 intensities, one for each sensors (readonly). The first 5 entries are from frontal sensors ordered from left to right. The last two entries are from rear sensors ordered from left to right.

Type

List[int]

DifferentialWheeled

class pyenki.DifferentialWheeled

The virtual base class of all enki robots.

{left,right}_wheel_target_speed

The target {left,right} wheel speed in centimeters per second.

Type

float

{left,right}_wheel_encoder_speed

The {left,right} wheel speed measured by simulated wheel encoders in centimeters per second (readonly).

Type

float

{left,right}_wheel_odometry

The {left,right} wheel odometry intergrated from measured wheel speeds in centimeters (readonly).

Type

float

max_wheel_speed

The maximal wheel speed in centimeters per second (readonly).

Type

float

wheel_speed_noise

The relative noise applied to the target wheel speed at each control step (readonly).

Type

float

wheel_axis

The distance between the wheels in centimeters (readonly).

Type

float

E-puck

class pyenki.Epuck

Create a DifferentialWheeled e-puck robot.

The robots has a 60 pixels frontal looking camera placed at a height of 2.2 cm and with a fov of 60 degrees, and 8 infrared proximity sensors (maximal range 12 cm) placed at a height of 2.5 cm and at angles: -18, -45, -90, -142, 142, 90, 45, 18 [degrees].

Example:

>>> import pyenki
>>> world = pyenki.World()
>>> epuck = pyenki.EPuck()
>>> world.add_object(epuck)
>>> epuck.position = (-10, 0)
>>> epuck.set_led_ring(True)
>>> world.add_object(pyenki.CircularObject(2.0, 5.0, -1, pyenki.Color(0.3, 0.7, 0)))
>>> world.step(0.1)
>>> epuck.prox_values
[104.60820372038921, ...
>>> epuck.camera_image
[(0.5, 0.5, 0.5), ...
prox_values

A list of (8) proximity sensor readings, one for each sensors (readonly).

Type

List[float]

prox_distances

A list of (8) distances between proximity sensor and nearest obstancle, one for each sensors; please note that this value would not directly be accessible by a real robot (readonly).

Type

List[float]

camera_image

A list of (180) rgb color values between 0 and 1.

Type

List[Tuple[float, float, float]]

controlStep(dt: float) → None

Perform one control step. This method should be overwritten by any subclass to control the robot.

Parameters

dt (float) – The control step duration.

set_led_ring(value: bool) → None

Toggle the (red) led ring. The real robot has 8 independelty controllable LEDs that compose the ring, while the simulated robot exposes a single value for the whole ring.

Parameters

value (bool) – The desired LED status.

Marxbot

class pyenki.Marxbot(scanner_range: float = 150.0)

Create a DifferentialWheeled Marbot robot. The robot has a planar, omnidirectional scanner, placed centrally at a height of 11 cm, which detects surrondings objects (distance and color).

Parameters

scanner_range (float) – the maximal sensing range of the scanner (default 150.0).

Example:

>>> import pyenki
>>> # create a world surrondded by a cylindrical wall.
>>> world = pyenki.World(r=20.0, walls_color=pyenki.Color(0.8, 0.2, 0.1))
>>> marxbot = pyenki.Marxbot()
>>> world.add_object(marxbot)
>>> marxbot.position = (0.0, 0.0)
>>> marxbot.angle = 0.0
>>> # Spin the robot on itself
>>> marxbot.left_wheel_target_speed = 5.0
>>> marxbot.right_wheel_target_speed = -5.0
>>> # Read the omnidirectional rgbd camera
>>> # Distances
>>> marxbot.scanner_distances
[19.68757743875876, ...
>>> # Image
>>> marxbot.scanner_image
[[(0.8, 0.2, 0.1), ...
scanner_distances

A list of (180) radial distances measured by the scanner, ordered from -180 degrees to 180 degrees in centimeters.

Type

List[float]

scanner_image

A list of (180) rgb color value between 0 and 1 measured by the scanner,

Type

List[Tuple[float, float, float]]

controlStep(dt: float) → None

Perform one control step. This method should be overwritten by any subclass to control the robot.

Parameters

dt (float) – The control step duration.

Thymio2

class pyenki.Thymio2(use_aseba_units: bool = False)

Create a DifferentialWheeled Thymio2 robot. Attribute names mimic the aseba interface, see http://wiki.thymio.org/en:thymioapi.

Parameters

use_aseba_units (bool) – use the same units and type as Aseba (default False).

Example (non aseba units):

>>> import pyenki
>>> thymio = pyenki.Thymio2(use_aseba_units=False)
>>> thymio.position = (3.2, 5.6)
>>> thymio.angle = 1.3
>>> # Spin the robot on itself
>>> thymio.motor_left_target = 10.2
>>> thymio.motor_right_target = -10.2
>>> # Switch the top LED yellow
>>> thymio.set_led_top(0.5, 0.5, 0.0)
>>> thymio.prox_values
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

Example (equivalent with aseba units):

>>> import pyenki
>>> thymio = pyenki.Thymio2(use_aseba_units=True)
>>> thymio.position = (3.2, 5.6)
>>> thymio.angle = 1.3
>>> # Spin the robot on itself
>>> thymio.motor_left_target = 307
>>> thymio.motor_right_target = -307
>>> # Switch the top LED yellow
>>> thymio.set_led_top(15, 15, 0)
>>> thymio.prox_values
[0, 0, 0, 0, 0, 0, 0]
use_aseba_units

whenever the robot should use the same units and type as the Aseba interface.

When use_aseba_units=False, the robot
  • uses floating point numbers,

  • measures the space in centimeters

  • normalizes color values between 0.0 and 1.0.

Instead, when use_aseba_units=True, the robot
  • uses integers numbers,

  • measures the space in discrete steps such that 500 steps ~= 16.6 cm,

  • normalizes (LED) color values in between 0 and 31.

Type

bool

prox_values

A list of (7) proximity sensor readings, one for each sensors (readonly). The first 5 entries are from frontal sensors ordered from left to right. The last two entries are from rear sensors ordered from left to right.

Type

List[number]

prox_distances

A list of (7) distances between proximity sensor and nearest obstancle, one for each sensors; please note that this value would not directly be accessible by a real robot (readonly). The first 5 entries are from frontal sensors ordered from left to right. The last two entries are from rear sensors ordered from left to right.

Type

List[float]

prox_comm_tx

The integer payload to be sent. The real robot can only send 11 bits, therefore to be compliant we should limit the value between 0 and 2047.

Type

int

prox_comm_enable

Enable/disable proximity communication.

Type

bool

prox_comm_events

A list of events, one for every received message during the last control step.

Type

List[IRCommEvent]

ground_values

A list of (2) ground sensor readings, one for each sensors (readonly)

Type

List[number]

motor_{left,right}_target

The target {left,right} wheel speed

Type

number

motor_{left,right}_speed

The {left,right} wheel speed measured by simulated wheel encoders (readonly)

Type

number

motor_{left,right}_odometry

The {left,right} wheel odometry intergrated from measured wheel speeds.

Type

number

controlStep(dt: float) → None

Perform one control step. This method should be overwritten by any subclass to control the robot.

Parameters

dt (float) – The control step duration.

set_led_bottom_left(red: float = 0, green: float = 0, blue: float = 0) → None

Control the bottom-left RGB LED color

Parameters
  • red (number) – the value of the red channel

  • green (number) – the value of the green channel

  • blue (number) – the value of the blue channel

set_led_bottom_right(red: float = 0, green: float = 0, blue: float = 0) → None

Control the bottom-right RGB LED color

Parameters
  • red (number) – the value of the red channel

  • green (number) – the value of the green channel

  • blue (number) – the value of the blue channel

set_led_buttons(index: int, value: float) → None

Control one of the 4 red LED near to the arrow buttons.

Parameters
  • index (int) – the index of the led (between 0 and 3)

  • value (number) – the intensity of the color.

set_led_circle(index: int, value: float) → None

Control one of the 8 yellow LED that forms a circle on top of the robot.

Parameters
  • index (int) – the index of the led (between 0 and 7)

  • value (number) – the intensity of the color.

set_led_left_blue(value: float) → None

Control the blue LED on the left side.

Parameters

value (number) – the intensity of the color.

set_led_left_red(value: float) → None

Control the red LED on the left side.

Parameters

value (number) – the intensity of the color.

set_led_prox(index: int, value: float) → None

Control one of the 8 red LED near to the proximity sensors.

Parameters
  • index (int) – the index of the led (between 0 and 7)

  • value (number) – the intensity of the color.

set_led_right_blue(value: float) → None

Control the blue LED on the right side.

Parameters

value (number) – the intensity of the color.

set_led_right_red(value: float) → None

Control the red LED on the right side.

Parameters

value (number) – the intensity of the color.

set_led_top(red: float = 0, green: float = 0, blue: float = 0) → None

Control the top RGB LED color

Parameters
  • red (number) – the value of the red channel

  • green (number) – the value of the green channel

  • blue (number) – the value of the blue channel

World

class pyenki.World(**kwds)

The world is the container of all objects and robots. It is either

  • a rectangular arena with walls at all sides:

    World(width: float, height: float, walls_color: Color = Color.gray)
    
  • a circular area with walls:

    World(width: float, height: float, walls_color: Color = Color.gray)
    
  • or an infinite surface:

    World()
    
Parameters
  • width (float) – The rectangular world width in centimeters

  • height (float) – The rectangular world height in centimeters

  • radius (float) – The circular world radius in centimeters

  • walls_color (Color) – Optional wall color, default is Color.gray

Example:

import pyenki

world = pyenki.World()
thymio = Thymio2()
world.add_object(thymio)
wall = pyenki.RectangularObject(l1=10, l2=50, height=5, mass=1,
                                color=pyenki.Color(0.5, 0.3, 0.3))
world.add_object(wall)
# Run 100 times a 0.1 s long simulation step
for _ in range(100):
    world.step(0.1)
add_object(item: pyenki.PhysicalObject) → None

Add a physical object to the simulation.

Parameters

item (PhysicalObject) – the object to add.

remove_object(item: pyenki.PhysicalObject) → None

Remove a physical object from the simulation.

Parameters

item (PhysicalObject) – the object to remove.

run(steps: int) → None

Run for a number of steps, using a step of 1/30 s and physics_oversampling of 3.

Parameters

steps (int) – The number of steps to perform

run_in_viewer(cam_position: Tuple[float, float] = (0, 0), cam_altitude: float = 0, cam_yaw: float = 0, cam_pitch: float = 0, walls_height: float = 10, orthographic: bool = False, period: float = 0.03) → None

Launch a QApplication to visualize the world from a (camera) viewpoint. The application run loop will keep real time while calling World.step at the appropriate time.

Parameters
  • cam_position (Tuple[float, float]) – the position of the viewpoint in centimeters

  • cam_altitude (float) – the altitude of the viewpoint in centimeters

  • cam_yaw (float) – the yaw of the viewpoint in radians

  • cam_pitch (float) – the pitch of the viewpoint in radians

  • walls_height (float) – the height of (visualized) walls in centimeters

  • orthographic (bool) – whetever to use a down looking camera with ortographic projection (default False)

  • period (float) – the period [s] at which to run world.step if run_world_update is enabled (default 0.03)

set_random_seed(seed: int) → None

Set the random seed

Note: Not sure that it is working as expected.

step(dt: float, physics_oversampling: int = 1) → None

Simulate a timestep

Parameters
  • dt (float) – the update timestep in seconds, should be below 1 (typically .02-.1)

  • physics_oversampling (int) – the amount of time the physics is run per step,

  • usual collisions require a more precise simulation than the sensor-motor loop frequency (as) –

WorldView

class pyenki.WorldView(world: pyenki.World, run_world_update: bool = False, cam_position: Tuple[float, float] = (0, 0), cam_altitude: float = 0, cam_yaw: float = 0, cam_pitch: float = 0, walls_height: float = 10, orthographic: bool = False, period: float = 0.03)

A QWidget subclass to display the world that automatically refreshes 30 times per second. It requires that a QApplication has already been instantiated.

Parameters
  • world (World) – the world to be displayed

  • run_world_update (bool) – whetever to run or not world.step at each view refresh (default False)

  • cam_position (Tuple[float, float]) – the position of the viewpoint in centimeters (default (0, 0))

  • cam_altitude (float) – the altitude of the viewpoint in centimeters (default 0)

  • cam_yaw (float) – the yaw of the viewpoint in radians (default 0)

  • cam_pitch (float) – the pitch of the viewpoint in radians (default 0)

  • walls_height (float) – the height of world boundary walls in centimeters (default 10)

  • orthographic (bool) – whetever to use a down looking camera with ortographic projection (default False)

  • period (float) – the period [s] at which to run world.step if run_world_update is enabled (default 0.03)

run_world_update

whetever to run or not world.step at each view refresh.

Type

bool

cam_position

the position of the viewpoint in centimeters

Type

Tuple[float, float]

cam_altitude

the altitude of the viewpoint in centimeters

Type

float

cam_yaw

the yaw of the viewpoint in radians

Type

float

cam_pitch

the pitch of the viewpoint in radians

Type

float

orthographic

whetever to use a down looking camera with ortographic projection. If enabled, cam_pitch is fixed to \(-\pi/2\).

Type

bool

Example (in an IPython qtconsole/notebook):

>>> import pyenki
>>> world = pyenki.World()
>>> %gui qt5
>>> view = pyenki.WorldView()
>>> view.show()
hide() → None

Hide the view

show() → None

Show the view