Create your first simulation :tag:`builder` :tag:`socket`
=========================================================

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 :doc:`Builder API <../../../../user/builder>`: a set of
Python functions that allow to define:

- The robots to use
- The components attached to them
- The middleware bindings used for communication
- The environment of the simulation

During the tutorial, we will write such a Python script that can be executed by MORSE to
create your simulation and start it.

.. note:: 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 the script
-----------------

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:

.. code-block:: python

    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**.


Add a robot to the scene
++++++++++++++++++++++++

The robot is the base where we will install other sensors and actuators.

.. code-block:: python

    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 :doc:`component library
<../../components_library>`.


Append an actuator
++++++++++++++++++

Then, let's add a :doc:`v, omega <../actuators/v_omega>` actuator. This one
controls the robot by changing the linear and angular velocity of the movement.

.. code-block:: python

    motion = MotionVW()
    motion.translate(z=0.3)
    atrv.append(motion)

The ``append`` method *parents* the actuator to the robot.

Append a sensor
+++++++++++++++

We can now add a :doc:`Pose <../sensors/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: :doc:`Pose <../sensors/pose>` 

.. code-block:: python

    pose = Pose()
    pose.translate(z=0.83)
    atrv.append(pose)

Configuring the middlewares
---------------------------

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:

.. code-block:: python

    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 :doc:`full list of
supported middlewares <../integration>` for reference.

Finalising the scene
--------------------

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 :doc:`pre-defined one
<../../environments>`.

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``.

.. code-block:: python

    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.


Running the simulation
----------------------

Starting the simulation
+++++++++++++++++++++++

Simply run::

    $ 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 :kbd:`p` to start the Game Engine

Control the simulation with services
++++++++++++++++++++++++++++++++++++

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]

.. note::
    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.

.. note::
    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.

Accessing the sensors data streams
++++++++++++++++++++++++++++++++++

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 :kbd:`esc` in the Blender window.

What's next?
------------


- You can try to add different components to the robot, by experimenting with
  the various objects available in the :doc:`MORSE component library
  <../../components_library>`.  This is the main reference of robots,
  actuators, sensors that are available *out of the box* in MORSE.

.. note:: 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.


- You can also discover how you can :doc:`extend MORSE <../../contributing>` to
  add your own sensors, actuators or robots.

- If you want to learn more about the MORSE *Builder API*, see the
  :doc:`builder documentation <../../../../user/builder>`.

- Finally, you can go back to the :doc:`list of tutorials <../../tutorials>`.

