This tutorial will guide you through the creation of a simple simulation where you can control a mobile robot and read data from its sensors.
It makes use of MORSE Builder API: a set of Python functions that allow to define:
During the tutorial, we will write such a Python script that can be executed by MORSE to create your simulation and start it.
If you want, you can get the script resulting from this tutorial here: $MORSE_ROOT/share/morse/examples/tutorials/tutorial-1-sockets.py, where $MORSE_ROOT is your installation prefix (typically /usr/local/).
Create a new script in your favorite Python editor, and give it an appropriate name. For instance: robot_scene.py.
In order to use the API, you must first import the morse.builder module:
from morse.builder import *
Then you will make calls to predefined functions to create and configure the components necessary in your scene.
MORSE knows three main components: the robots, the sensors and the actuators (the robots are mostly supports for sensors or actuators).
All these components live in an environment, which may be any physics-enabled 3D model.
The behaviour of these components can be altered by modifiers and their interactions with softwares running outside the simulator rely on middlewares.
The robot is the base where we will install other sensors and actuators.
atrv = ATRV()
Here, we simply import a standard ATRV 4-wheeled outdoor robot.
The atrv is known by MORSE, as you can see in the component library.
Then, let’s add a v, omega actuator. This one controls the robot by changing the linear and angular velocity of the movement.
motion = MotionVW() motion.translate(z=0.3) atrv.append(motion)
The append method parents the actuator to the robot.
We can now add a Pose sensor, which provides us with the location and rotation of the robot.
The data it sends back is the (x, y, z) coordinates, and the (yaw, pitch, roll) orientation. For any component, you can know what in exported from the documentation page of the component: Pose
pose = Pose() pose.translate(z=0.83) atrv.append(pose)
The simplest way to test MORSE is to use the basic socket to access the data-streams and services provided by the components. This method has no software requirements other than the base MORSE installation.
You need to tell MORSE how each of the components attached to a robot will communicate with the outside world. This is done with these instructions:
pose.add_stream('socket') pose.add_service('socket') motion.add_service('socket')
Each of the components can use a different middleware, enabling the use of MORSE in an heterogeneous environment. You can check the full list of supported middlewares for reference.
Every builder script must finish with an environment description.
The parameter for the Environment method is the name of a Blender .blend file you provide (with its full path) or a pre-defined one.
The Environment object also provides additional options to place and aim the default camera, by using the methods set_camera_rotation and set_camera_location.
env = Environment('indoors-1/indoor-1') env.set_camera_location([5, -5, 6]) env.set_camera_rotation([1.0470, 0, 0.7854])
Now save your script file.
$ morse run robot_scene.py
Alternatively, you can choose to open first your simulation in Blender, and start it from there:
Launch MORSE in edit mode, passing your script in argument:
$ morse edit robot_scene.py
Place your mouse inside the 3D view of the scenario
Press p to start the Game Engine
Using sockets to connect to robot services is the simplest way to interact with the simulation. You can talk with MORSE through a simple telnet connection. On a separate terminal, type:
$ telnet localhost 4000
Port 4000 is the default port used by MORSE to expose the services.
The motion controller we have added to the robot export one service, set_speed: to make the robot move in a circle, with linear speed 2 m/s and angular speed -1 rad/s, type this instruction:
id1 atrv.motion set_speed [2, -1]
the first part of the request, id1 is any identifier you want. It is useful when running asynchronous services (ie, non-blocking) to get notified of the service termination.
the internal name of the component is (here, atrv.motion) is displayed in the MORSE log at the end of the simulation initialisation.
In the same way, you can query the atrv.pose sensor for the data it contains:
id2 atrv.pose get_local_data
The format of these commands is simple, they are composed of four parts:
Try giving the motion controller different speeds, and querying the pose sensor at different locations.
The Pose sensor actually permanently export its data as a stream.
We can use telnet as well to monitor it.
Since many sensors may output their data-stream on the socket interface, each of them is assigned a port at runtime. You can retrieve this port either by looking at MORSE console output, or with the simulation services list_streams and get_stream_port:
id3 simulation list_streams > id3 SUCCESS ["atrv.pose"] id4 simulation get_stream_port ["atrv.pose"] > id4 SUCCESS 60000
So we know that the pose sensor exports its datastream on the port 60000.
Open another telnet session:
$ telnet localhost 60000
Your screen should be filled pretty quickly with the sensor output.
Many actuators also accept a datastream as input to control their behaviour.
To exit the simulation, press esc in the Blender window.
The names you pass to the Builder functions link to the names of the Blender .blend files that contain the components’ meshes. They are provided for each component in the component library.