At the moment only one robot - Khepera3 - is implemented in pySimiam. Most likely, you will need to customize it for your needs or implement a completely new robot.
A robot from the point of view of the simulator is an drawable object that accepts control inputs from a supervisor. The pair robot-supervisor is a tightly bound entity, and the simulator plays only a messenger role between them.
Start with subclassing robot.Robot and implementing drawing. Two functions have to be implemented: draw() that draws the robot on screen and get_envelope() that returns the bounding rectangle of the robot for collision detection.
The get_envelope() method should return a list of points describing the polygon. By default this polygon is only used for collision detection, and so it does not have to correspond exactly to the drawing of the robot.
The draw() method accepts a Renderer object as parameter, and can use any of its functions to draw the robot. The drawing can be as complicated as you wish, or as easy as:
def draw(self,r):
"""Draw the envelope (shape) filling it with the internal color."""
r.set_pose(self.get_pose())
r.set_brush(self.get_color())
r.draw_polygon(self.get_envelope())
Note the use of set_pose() method. It is much easier to draw the robot in the robot’s internal reference frame, so it is recommended to use this method before drawing. It is also recommended to use the color of the robot set_pose() during drawing, to be able to distinguish different robots.
If you robot has sensors that can be drawn, an additional method draw_sensors() can be implemented. We will revisit this point later, when we talk about sensors.
To move the robot, the simulator calls move() with the time interval as a parameter. When implementing this method, you should update the pose of the robot with set_pose(), depending on its internal state.
The internal state of the robot is set by the supervisor passing parameters into set_inputs(). The format of the parameters is up to the robot implementation, and the supervisor has to conform to this. Please, provide sufficient documentation when implementing this method.
Some of the robot’s parameters are important to understand its state. For example, in case of a differential drive robot, the radius of the wheels and the distance between them is important. There should be also a way to obtain sensor readings. This information is expected to be provided by the get_info() method. As with set_inputs(), the actual structure of the returned object is up to the robot and only matters for the supervisor. You can turn to the Khepera3 code for inspiration.
One thing that is important for the simulator, though, is the set of the external sensors of the robot, as the sensors have to interact with the world. This information should be returned as a list of sensors from the get_external_sensors() method.
For example, if your robot has an IR sensor skirt with five sensors, the list should contain these sensor objects (see sensor.ProximitySensor). You should also implement draw_sensors() in this case, which can be as simple as:
def draw_sensors(self,renderer):
"""Draw the sensors that this robot has"""
for sensor in self.ir_sensors:
sensor.draw(renderer)
Note
At the moment, the only type of sensors that are supported by the simulator are proximity sensors, such as ultrasound and IR sensors. Please contact the developers (or extend the simulator yourself) if you need another kind of external sensors.
Your robot should be ready now. How can you test it? You need two parts - a world and a supervisor . In the beginning, neither of the two has to be very complicated. A simple world can just contain one robot, and your supervisor can work without any controllers. This should be enough to test the drawing, positioning of the sensors and the dynamics.
The pose class allows for a posing of objects in 2D space. The pose uses a right-hand coordinate system with counter-clockwise measurement of theta from the x-axis
There are several ways to create a pose:
Pose(x,y,theta) | A pose at x,y and orientation theta |
Pose(x,y) | Same as Pose(x,y,0) |
Pose() | Same as Pose(0,0,0) |
Pose([x,y,theta]) | Same as Pose(x,y,theta) |
There are several ways to access pose parameters:
x, y, theta = pose
x, y, theta = pose.get_list()
x = pose.x; y = pose.y; theta = pose.theta
Get the pose as a list [x, y, theta]. Equivalent to list(pose).
Get the 3x3 transformation matrix associated with the pose.
Compare this pose to other. Returns True if the relative distance in x, y and theta is smaller than epsilon
Set all or some pose parameters.
Possible arguments are:
set_pose(x, y, theta) | Set all of x, y and theta |
set_pose(another_pose) | Use x, y and theta from another pose |
set_pose(x = 3.0) | Only change the x position |
set_pose(theta = pi, y = 3.0) | Only change the y position and orientation |
set_pose(another_pose, y = 1) | Use x and theta from another pose, use y=1 |
The base class for all objects that can be drawn in the simulator. Every SimObject has a pose, an envelope and a color.
Parameters: |
|
---|
Get the internal color of the object
Set the internal color of the object
Get the pose of the object in world coordinates
Set the pose of the object in world coordinates
Draws the object using renderer (see Renderer).
The object doesn’t have to use only one color. It doesn’t even have to use its internal color while drawing.
Get the envelope of the object in object’s local coordinates.
The envelope is a list of xy pairs, describing the shape of the bounding polygon.
Get the envelope of the object in world coordinates. Used for checking collision.
The envelope is cached, and will be recalculated if recalculate is True.
Get the smallest rectangle that contains the object as a tuple (x, y, width, height).
Check if the object has collided with other. Return True or False
Get a list of contact points with other object. Returns a list of (x, y)
Get the smallest rectangle that contains the object as a tuple (xmin, ymin, xmax, ymax)
The polygon is a simobject that gets the envelope supplied at construction. It draws itself as a filled polygon.
Parameters: |
|
---|
Draw the envelope (shape) filling it with the internal color.
The cloud is a collection of points.
Append a point at pose to the collection. The orientation of the pose is ignored
Draw a polyline with modes at all added points, using the internal color
The path is a simobject that draws itself as a polyline. The line starts at start, and can be continued by adding points using add_point().
Parameters: |
|
---|
The path is used by the simulator to track the history of robot motion
Set the start point to start.x and start.y and remove all other points
Draw a polyline with modes at all added points, using the internal color
This type of robots implements communication with a real-world robot.
Although this is a SimObject, it doesn’t move by itself. Use set_pose() to move the robot.
Stops the robot, saving the state
Restarts the robot from the saved state
Initiate communication with the real robot and get state info back.
The robot is a SimObject that implements drawing and information functions to interface with supervisor.
This class is not intended to be subclassed in user code. Use one of the provided subclasses instead: SimBot for emulated robots or RealBot for physical robots.
Draw the sensors that this robot has
Return the robot information structure, including sensor readings and shape information
Set drive inputs in the format needed by this robot
The robot defined by this class is a simulated robot, and implements its own motion in move().
To implement a new type of robot, subclass SimBot and implement get_info() and get_external_sensors().
To make your robot move, implement move().
To make you robot controllable, implement set_inputs().
If your robot has sensors that can be drawn in the view, implement draw_sensors().
Get the external sensors of the robot as a list. This function is used to update the sensor readings in proximity sensors.
Move the robot for a time interval dt.
Base superclass for sensor objects
Returns the value with an added normal noise
The return value is normally distributed around value with a standard deviation sigma
A sensor that moves together with its parent object.
The sensor is assumed to be attached to parent at pose in local coordinates.
Get the pose of the sensor in the parent (robot) coordinates.
Create a proximity sensor mounted on robot at pose. The geometry is a (rmin, rmax, angle) tuple.
Return the envelope of the sensor
Returns the distance to the value using sensor calculations
Returns the distance instance
Returns the reading value
updates all the distances from the reading
draws the sensor simobject
Gets the distance to another simobject returns distance in meters or None if not in contact