API¶
Vector¶
A type alias for Tuple[float, float] as (x, y)
.
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)
-
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
-
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
- When
-
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
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