= Tutorial: Writing the demo Module =

This page aims to describe how to write and then run the demo module with GenoM3 either for ros and pocolibs.

== Needs ==

Check this [[genom3/tutorial/install|instruction page]] to install GenoM3 and associated templates and tools.

== Demo module with pocolibs ==

The final result of this tutorial module can be obtained from here. But this tutorial will walk you thru getting your own copy! Still, you can grab it if you want avoiding typing all the code.

{{{
       git clone git://trac.laas.fr/robots/demo-genom demo-genom-final 
       cd demo-genom-final
       git checkout genom3
}}}

= part 1: How to write your first module ? =
This section will illustrate a concrete use of genom3. The demo module will control a virtual mobile that can move in a 1D world. Some of the services the module offers are:

 * read and set the current speed at any moment
 * move the mobile to a given position
 * move the mobile of a given distance (from its current position)
 * monitor when the mobile passes a given position
 * stop the motion

Moreover, the demo module export a port with the current state of the mobile (position and speed).

To implement this, we first create a directory named demo-genom.

{{{
mkdir demo-genom
cd demo-genom
}}}
== Write .gen File ==
In that directory, we will write the description file demo.gen. The file demo.gen is made up of several parts, each of them being identified with a keyword:

 * {{{component}}} module declaration
 * {{{ids}}}
 * {{{port}}}
 * {{{exception}}}
 * {{{task}}}
 * {{{attribute}}}
 * {{{function}}}
 * {{{activity}}}

The entire file will look like this:

{{{
/* The special / * / marker will copy the associated comment block (here, the
 * license) in the generated files. */

/*/
 * Copyright (c) 1996-2013 CNRS/LAAS
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "demoStruct.idl"

/* ---- component declaration ---- */

component demo {
  version	"1.1";
  email		"openrobots@laas.fr";
  lang		"c";
  require	"genom3 >= 2.99.20";

  /* ---- Data structures and IDS ---- */

  ids {
    demo::state	state;		/* Current state */
    demo::speed	speedRef;	/* Speed reference */
    double	posRef;
  };


  /* ---- Port declaration ---- */

  port out demo::state Mobile;


  /* ---- exception declaration ---- */

  exception TOO_FAR_AWAY {double overshoot;};

  exception INVALID_SPEED;

  /* ---- Execution task declaration ---- */

  task motion {
    period	demo::task_period ms;
    priority	100;
    stack	4000;
    codel <start>	InitDemoSDI(out ::ids, port out Mobile) yield ether;
  };


  /* ---- Services declarations ---- */

  attribute SetSpeed(in speedRef = demo::SLOW	:"Mobile speed")
  {
    doc		"To change speed";
    validate	controlSpeed (local in speedRef);
    throw	INVALID_SPEED;
  };

  attribute GetSpeed(out speedRef =	:"Mobile speed")
  {
    doc		"To get current speed value";
  };

  function Stop()
  {
    doc		"Stops motion and interrupts all motion requests";
    interrupts	MoveDistance, GotoPosition;
  };


  activity MoveDistance(in double distRef = 0	:"Distance in m")
  {
    doc		"Move of the given distance";
    validate	controlDistance(in distRef, in state.position);

    codel <start>	mdStartEngine(in distRef, in state.position,
                              out posRef) yield exec, ether;
    codel <exec>	mdGotoPosition(in speedRef, in posRef, inout state,
                               port out Mobile) yield exec, end;
    codel <end, stop>	mdStopEngine() yield ether;
    interrupts	MoveDistance, GotoPosition;
    task	motion;
    throw	TOO_FAR_AWAY;
  };

  activity GotoPosition (in double posRef = 0	:"Goto position in m")
  {
    doc		"Move to the given position";

    validate	controlPosition (local in posRef);

    codel <start>	gpStartEngine() yield exec, ether;
    codel <exec>	gpGotoPosition(local in posRef,
                               inout ::ids, port out Mobile) yield exec, end;
    codel <end, stop>	gpStopEngine() yield ether;
    interrupts	MoveDistance, GotoPosition;
    task	motion;
    throw	TOO_FAR_AWAY;
  };

  activity Monitor (in double monitor = 0 :"Monitored absolute position in m",
                    out double position)
  {
    doc		"Monitor the passage on the given position";
    validate	controlPosition (in monitor);

    codel <start>	monitor(in monitor, in ::ids) yield start, stop;
    codel <stop>	monitorStop(in ::ids, out position) yield ether;
    task		motion;
    throw		TOO_FAR_AWAY;
  };
};

}}}
== Data Structure Definition ==
The #include "demoStruct.idl" statement works as a header file in C and includes idl data structure. This file contains all the necessary declarations for the definition of the internal database. These structures are then used in the .gen file.  In this example, the file "demoStruct.idl" contains the definition of the position and the speed. This file is preferably located in the same directory as {{{demo.gen}}}, since it contributes to the definition of the module interface.

{{{
/*
 * Copyright (c) 1996-2013 CNRS/LAAS
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ifndef IDL_DEMO_STRUCT
#define IDL_DEMO_STRUCT

module demo {

  const unsigned long task_period = 400;
  const double millisecond = 0.001;

  struct state {
    double position;  /* current position (m) */
    double speed;     /* current speed (m/s) */
  };

  enum speed {
    SLOW,
    FAST
  };
};

#endif /* IDL_DEMO_STRUCT */
}}}
== Module generation ==
Once your description file (.gen and .idl) are ready, you need to generate your module:

{{{
gupta[demo-genom] genom3 skeleton demo.gen
creating ./codels/demo_motion_codels.c
creating ./codels/demo_codels.c
creating ./demo-genom3.pc.in
creating ./demo-genom3-uninstalled.pc.in
creating ./bootstrap.sh
creating ./autoconf/ag_templates.m4
creating ./configure.ac
creating ./Makefile.am
creating ./codels/Makefile.am
}}}
From now on, the module is ready to be compiled and run, but let's look at the result of the execution of the command:

{{{
gupta[demo-genom] ls
autoconf      configure.ac       demo-genom3-uninstalled.pc.in
bootstrap.sh  demo.gen           demoStruct.idl
codels        demo-genom3.pc.in  Makefile.am

}}}
{{{GenoM3}}} created two new directories {{{codels/}}} and {{{autoconf/}}}, and several new files.

 * Algorithms (or a part of them) are grouped in the directory {{{codels/}}}. The files in that directory give you template to start from, and also let {{{GenoM3}}} produce a module even if you still do not have written a single line of code.
 * The Makefile.am and configure.ac files are also under your control. These are the main files which are used for the compilation of the module.

== Codels writing ==
Let's have a look in the codels directory.

{{{
gupta[codels] ls
demo_codels.c  demo_motion_codels.c  Makefile.am
}}}
=== demo_codels.c ===
In this file, we will found codels executed by the control task such as the validateones , e.g. controlSpeed (Validation codel of attribute SetSpeed), controlPosition (Validation codel of activity GotoPosition) and  controlDistance (Validation codel of activity MoveDistance)..

At the beginning, the template will look like:

{{{
gupta[codels] more demo_codels.c
/*
 * Copyright (c) 1996-2013 CNRS/LAAS
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "acdemo.h"

#include "demo_c_types.h"


/* --- Attribute SetSpeed ----------------------------------------------- */

/** Validation codel controlSpeed of attribute SetSpeed.
 *
 * Returns genom_ok.
 * Throws demo_INVALID_SPEED.
 */
genom_event
controlSpeed(demo_speed speedRef)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return genom_ok;
}


/* --- Activity MoveDistance -------------------------------------------- */

/** Validation codel controlDistance of activity MoveDistance.
 *
 * Returns genom_ok.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
controlDistance(double distRef, double position)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return genom_ok;
}


/* --- Activity GotoPosition -------------------------------------------- */

/** Validation codel controlPosition of activity GotoPosition.
 *
 * Returns genom_ok.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
controlPosition(double posRef)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return genom_ok;
}


/* --- Activity Monitor ------------------------------------------------- */

/** Validation codel controlPosition of activity Monitor.
 *
 * Returns genom_ok.
 * Throws demo_TOO_FAR_AWAY.
 */
/* already defined in service GotoPosition validation */

}}}

You notice that all the codels are empty and return genom_ok. Still the parameters are the corect ones. Here are possible code to include in these functions:

=== controlSpeed ===
{{{
genom_event
controlSpeed(demo_speed speedRef)
{
  /* insert your code */
  if(speedRef != demo_SLOW && speedRef != demo_FAST)
       return demo_INVALID_SPEED();
  return genom_ok;
}
}}}

=== controlDistance ===
{{{
genom_event
controlDistance(double distRef, double position)
{
  double lposRef;
  demo_TOO_FAR_AWAY_detail tfa;

  lposRef = position + distRef;
  if (lposRef > DEMO_MACHINE_LENGTH/2 || lposRef < -DEMO_MACHINE_LENGTH/2) {
       tfa.overshoot = fabs(lposRef) - fabs(DEMO_MACHINE_LENGTH/2);
       return demo_TOO_FAR_AWAY(&tfa);
  }

  return genom_ok;
}
}}}

=== controlPosition ===
{{{
genom_event
controlPosition(double posRef)
{
  demo_TOO_FAR_AWAY_detail tfa;

  if (posRef > DEMO_MACHINE_LENGTH/2 || posRef < -DEMO_MACHINE_LENGTH/2) {
       tfa.overshoot = fabs(posRef) - fabs(DEMO_MACHINE_LENGTH/2);
       return demo_TOO_FAR_AWAY(&tfa);
  }
  return genom_ok;
}
}}}

Note the exception TOO_FAR_WAY for which we return the length we overshoot the maximum/minimum distance acceptable. Such information can be retrieve by the client/supervisor to take appropriate corrective actions.

=== demo_motion_codels.c ===
In this file, we will found codels attached to the '''motion''' task, such as : 
 * InitDemoSDI: which is the <start> codel of the task 
 * gpStartEngine, gpGotoPosition, gpStopEngine: which are <start>, <exec> and <stop> codels of the '''!GotoPosition''' activity
 * etc

{{{
gupta[codels] more demo_motion_codels.c
/*
 * Copyright (c) 1996-2013 CNRS/LAAS
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "acdemo.h"

#include "demo_c_types.h"


/* --- Task motion ------------------------------------------------------ */


/** Codel InitDemoSDI of task motion.
 *
 * Triggered by demo_start.
 * Yields to demo_ether.
 */
genom_event
InitDemoSDI(demo_ids *ids, const demo_Mobile *Mobile)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_ether;
}


/* --- Activity MoveDistance -------------------------------------------- */

/** Codel mdStartEngine of activity MoveDistance.
 *
 * Triggered by demo_start.
 * Yields to demo_exec, demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdStartEngine(double distRef, double position, double *posRef)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_exec;
}

/** Codel mdGotoPosition of activity MoveDistance.
 *
 * Triggered by demo_exec.
 * Yields to demo_exec, demo_end.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdGotoPosition(demo_speed speedRef, double posRef, demo_state *state,
               const demo_Mobile *Mobile)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_exec;
}

/** Codel mdStopEngine of activity MoveDistance.
 *
 * Triggered by demo_end, demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdStopEngine(void)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_ether;
}


/* --- Activity GotoPosition -------------------------------------------- */

/** Codel gpStartEngine of activity GotoPosition.
 *
 * Triggered by demo_start.
 * Yields to demo_exec, demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpStartEngine(void)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_exec;
}

/** Codel gpGotoPosition of activity GotoPosition.
 *
 * Triggered by demo_exec.
 * Yields to demo_exec, demo_end.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpGotoPosition(double posRef, demo_ids *ids,
               const demo_Mobile *Mobile)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_exec;
}

/** Codel gpStopEngine of activity GotoPosition.
 *
 * Triggered by demo_end, demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpStopEngine(void)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_ether;
}


/* --- Activity Monitor ------------------------------------------------- */

/** Codel monitor of activity Monitor.
 *
 * Triggered by demo_start.
 * Yields to demo_start, demo_stop.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
monitor(double monitor, const demo_ids *ids)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_start;
}

/** Codel monitorStop of activity Monitor.
 *
 * Triggered by demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
monitorStop(const demo_ids *ids, double *position)
{
  /* skeleton sample: insert your code */
  /* skeleton sample */ return demo_ether;
}
}}}
Let's have a look on how we can write such functions:
{{{
/*
 * Copyright (c) 1996-2013 CNRS/LAAS
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "acdemo.h"

#include <stdio.h>
#include <math.h>
#include "demoConst.h"

#include "demo_c_types.h"

#define SIGN(x) ((x)<0.?-1.0:1.0)

/* --- Task motion ------------------------------------------------------ */


/** Codel InitDemoSDI of task motion.
 *
 * Triggered by demo_start.
 * Yields to demo_ether.
 */
genom_event
InitDemoSDI(demo_ids *ids, const demo_Mobile *Mobile)
{
  ids->state.position = 0.0;
  ids->state.speed = 0;
  Mobile->data()->position = ids->state.position;
  Mobile->data()->speed =   ids->state.speed;
  Mobile->write();		/* write the poster. */
  ids->speedRef = demo_SLOW;
  printf ("InitDemoSDI done.\n");
  return demo_ether;
}


/* --- Activity MoveDistance -------------------------------------------- */

/** Codel mdStartEngine of activity MoveDistance.
 *
 * Triggered by demo_start.
 * Yields to demo_exec, demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdStartEngine(double distRef, double position, double *posRef)
{
  *posRef = position + distRef;
  printf("starting engine\n");
  return demo_exec;
}

/** Codel mdGotoPosition of activity MoveDistance.
 *
 * Triggered by demo_exec.
 * Yields to demo_exec, demo_end.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdGotoPosition(demo_speed speedRef, double posRef, demo_state *state,
               const demo_Mobile *Mobile)
{
  double distRemain;
  double dDist;
  double v;

  distRemain = posRef - state->position;
  v = (speedRef == demo_SLOW) ?
    DEMO_DEFAULT_MAX_SPEED/4. : DEMO_DEFAULT_MAX_SPEED;
  dDist = v * demo_task_period * demo_millisecond* SIGN(distRemain);

  if (fabs(distRemain) < fabs(dDist)) {
       Mobile->data()->position = state->position = posRef;
       Mobile->data()->speed = state->speed = 0;
       Mobile->write();		/* write the poster. */
       return demo_end;
  }

  Mobile->data()->position = state->position += dDist;
  Mobile->data()->speed = state->speed = v;
  Mobile->write();		/* write the poster. */
#ifdef VERBOSE
  printf ("speed %g m/s  pos %g m\n", v, state->position);
#endif
  return demo_exec;
}

/** Codel mdStopEngine of activity MoveDistance.
 *
 * Triggered by demo_end, demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
mdStopEngine(void)
{
  printf ("stop engine\n");
  return demo_ether;
}


/* --- Activity GotoPosition -------------------------------------------- */

/** Codel gpStartEngine of activity GotoPosition.
 *
 * Triggered by demo_start.
 * Yields to demo_exec, demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpStartEngine(void)
{
  printf("starting engine\n");
  return demo_exec;
}

/** Codel gpGotoPosition of activity GotoPosition.
 *
 * Triggered by demo_exec.
 * Yields to demo_exec, demo_end.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpGotoPosition(double posRef, demo_ids *ids,
               const demo_Mobile *Mobile)
{
  return mdGotoPosition(ids->speedRef, posRef, &ids->state, Mobile);
}

/** Codel gpStopEngine of activity GotoPosition.
 *
 * Triggered by demo_end, demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
gpStopEngine(void)
{
  return mdStopEngine();
}


/* --- Activity Monitor ------------------------------------------------- */

/** Codel monitor of activity Monitor.
 *
 * Triggered by demo_start.
 * Yields to demo_start, demo_stop.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
monitor(double monitor, const demo_ids *ids)
{
  double dDist;

  dDist = ids->state.speed * demo_task_period * demo_millisecond;
  if (fabs (monitor - ids->state.position) < dDist) {
    printf ("dist %f mon %f pos %f\n", dDist, monitor, ids->state.position);
    return demo_stop;
  }
  return demo_start;
}

/** Codel monitorStop of activity Monitor.
 *
 * Triggered by demo_stop.
 * Yields to demo_ether.
 * Throws demo_TOO_FAR_AWAY.
 */
genom_event
monitorStop(const demo_ids *ids, double *position)
{
  *position = ids->state.position;
  return demo_ether;
}
}}}

Note that we include a demoConst.h file which you should also create in the same directory than the codels and containing:
{{{
#ifndef DEMO_CONST_H
#define DEMO_CONST_H

#define DEMO_MACHINE_LENGTH	2.0   /* m */
#define DEMO_DEFAULT_MAX_SPEED	0.5   /* m/s */ 

#define VERBOSE

#endif
}}}
== Module compilation ==
We are now ready to compile the module. Note that you could have done it with the empty codels just after generating the skeleton. The result would have been a valid GenoM3 module, runnable, but not doing anyhing of course.

There are two steps in compilation of the module:

 * ''configuration'' of the module by running the configure script
 * ''compilation'' itself, controlled by the Makefile generated in the previous step.

=== Bootstrap ===
 * bootstrap the autotools build system
 {{{
gupta[demo-genom] ./bootstrap.sh
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal -I autoconf
autoreconf: configure.ac: tracing
autoreconf: running: libtoolize --install --copy
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `autoconf'.
libtoolize: copying file `autoconf/config.guess'
libtoolize: copying file `autoconf/config.sub'
libtoolize: copying file `autoconf/install-sh'
libtoolize: copying file `autoconf/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `autoconf'.
libtoolize: copying file `autoconf/libtool.m4'
libtoolize: copying file `autoconf/ltoptions.m4'
libtoolize: copying file `autoconf/ltsugar.m4'
libtoolize: copying file `autoconf/ltversion.m4'
libtoolize: copying file `autoconf/lt~obsolete.m4'
autoreconf: running: /usr/bin/autoconf
autoreconf: running: /usr/bin/autoheader
autoreconf: running: automake --add-missing --copy --no-force
configure.ac:24: installing `autoconf/missing'
codels/Makefile.am: installing `autoconf/depcomp'
autoreconf: Leaving directory `.'
}}}

=== Build directory ===
In order to keep objects files separated from the sources, for instance when you want to generate the module for several different architectures, or just in order to have a simple mean to clean up everything that was produced during the building phase, it is strongly recommended to create a separate ''build'' directory and run every command from there.

{{{
gupta[demo-genom] mkdir build
gupta[demo-genom] cd build
}}}
=== Configuration ===
All the OpenRobots software and tools are generally installed in a specific directory (for instance {{{${HOME}/openrobots}}}). This is the main information that needs to be specified to the {{{configure}}} script. Don't forget to run {{{configure}}} from the build directory. Then, the options will be different given the templates you want to generate, you have several possibilities:

 * pocolibs ($TEMPLATES=pocolibs/server,pocolibs/client/c)
  * pocolibs/server is the genom pocolibs module itself
  * pocolibs/client/c is the pocolibs C client library
 * ros ($TEMPLATES=ros/server,ros/client/c,ros/client/ros)
  * ros/server is the genom ros module itself
  * ros/client/c is the ros C client library
 * openprs ($TEMPLATES=openprs/client), you can mix openprs template with the others (e.g.: $TEMPLATES=pocolibs/server,pocolibs/client/c,openprs/client)

e.g. here, if we set $TEMPLATES=pocolibs/server,pocolibs/client/c

{{{
gupta[build] ../configure --prefix=$INSTALL_DIR --with-templates=$TEMPLATES
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
...
...
...
checking for pocolibs... yes
checking for genom3_pocolibs... yes
checking for genom3... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating demo-c-client.pc
config.status: creating demo-c-client-uninstalled.pc
config.status: creating autoconf/acheader.h
config.status: executing depfiles commands
config.status: executing libtool commands
configure: done configuring for pocolibs/client/c
}}}
=== Compilation ===
To compile the module, just run {{{make}}} from the {{{build}}} directory. The GNU make utility is required, but this is the standard make on linux systems.

{{{
 make
}}}
=== Installation ===
The built binaries and libraries (and some associated files) need to be copied to their final locations. This is achieved by executing {{{make install}}}. Depending of the {$INSTALL_PATH} you used, this may require ''root'' privilege.

{{{
 make install
}}}
== Module execution ==
Once compiled, the module is ready to be executed. The module is located in the {{{bin}}} subdirectory of the directory specified as {{{prefix}}} in the configuration step. This is an executable whose name will depend of the $TEMPLATE you choose. E.g., in our case, if we use pocolibs template, we will have {{{demo-pocolibs}}} executable and if you use ros template, we will have {{{demo-ros}}}.

=== pocolibs ===
You need to initialise pocolibs, to do so type:
{{{
h2 init
Initializing pocolibs devices: OK
}}}

at this point, you can start the module:

{{{
demo-pocolibs -b
pocolibs execution environment version 2.13
Copyright (c) 1999-2011 CNRS-LAAS
demo: created outport demo/genom_state
demo: created outport demo/genom_metadata
demo: created outport demo/Mobile
InitDemoSDI done.
demo: spawned motion exec task
demo: spawned control task
demo: setup and running
}}}

the -b argument is to start the module in background. -h will indicate the other options available.

Now that your module is running, you need to control it, to send request, get report, read the port, etc.

For this you need a client, let's start with a tcl client.
==== tcl ====

To control the module with tcl, you need to start the genomixd program, then launch eltclsh which is an interactive tcl shell.

{{{
genomixd &
eltclsh
                        eltclsh1.14 - Copyright (C) 2001-2012 LAAS-CNRS

eltclsh > package require genomix
1.2
eltclsh > genomix::connect 
genomix1
eltclsh > genomix1 load demo
pocolibs execution environment version 2.13
Copyright (c) 1999-2011 CNRS-LAAS
demo
}}}

You can use completion (tab) at any point to get help on the available commands. Exemple:

{{{
eltclsh > demo<tab><tab>
::demo::GetSpeed       ::demo::MoveDistance   ::demo::connect_port   
::demo::GotoPosition   ::demo::SetSpeed       ::demo::connect_remote 
::demo::Mobile         ::demo::Stop           ::demo::genom_state    
::demo::Monitor        ::demo::abort_activity ::demo::kill           
}}}

Note that all the services, port and some default services are provided. You can now play with your module. If you have started the module in the same window, you will see the following results.

{{{
eltclsh > ::demo::GetSpeed 
speedRef ::demo::SLOW
eltclsh > ::demo::GotoPosition -h
Usage:
	 demo::GotoPosition [-id var] [-s|-send] [-a|-ack] [-t|-timeout milli] 
		 [-f|-flat] [-h] [--] input [& ?script?] 

Input dictionary:
double posRef: Goto position in m (0)
eltclsh > ::demo::GotoPosition 1
starting engine
speed 0.125 m/s  pos 0.05 m
speed 0.125 m/s  pos 0.1 m
speed 0.125 m/s  pos 0.15 m
speed 0.125 m/s  pos 0.2 m
speed 0.125 m/s  pos 0.25 m
speed 0.125 m/s  pos 0.3 m
speed 0.125 m/s  pos 0.35 m
speed 0.125 m/s  pos 0.4 m
speed 0.125 m/s  pos 0.45 m
speed 0.125 m/s  pos 0.5 m
speed 0.125 m/s  pos 0.55 m
speed 0.125 m/s  pos 0.6 m
speed 0.125 m/s  pos 0.65 m
speed 0.125 m/s  pos 0.7 m
speed 0.125 m/s  pos 0.75 m
speed 0.125 m/s  pos 0.8 m
speed 0.125 m/s  pos 0.85 m
speed 0.125 m/s  pos 0.9 m
speed 0.125 m/s  pos 0.95 m
stop engine
eltclsh > ::demo::SetSpeed 
enum speedRef: Mobile speed (::demo::SLOW) > ::demo::FAST 
eltclsh > ::demo::Monitor 0 &
demo::0
eltclsh > ::demo::GotoPosition 
double posRef: Goto position in m (0) > -1
starting engine
speed 0.5 m/s  pos 0.8 m
speed 0.5 m/s  pos 0.6 m
speed 0.5 m/s  pos 0.4 m
speed 0.5 m/s  pos 0.2 m
speed 0.5 m/s  pos 5.55112e-17 m
dist 0.200000 mon 0.000000 pos 0.000000
speed 0.5 m/s  pos -0.2 m
speed 0.5 m/s  pos -0.4 m
speed 0.5 m/s  pos -0.6 m
speed 0.5 m/s  pos -0.8 m
stop engine
}}}

Note the monitor which reported when the mobile passes in 0.

You can also read the port Mobile:
{{{
eltclsh > ::demo::Mobile 
Mobile {position -1 speed 0}
eltclsh > 
}}}

To kill the module:
{{{
eltclsh > ::demo::kill 
demo: terminating on Terminated signal request
eltclsh > demo: shutting down motion exec task
demo: shutting down control task
demo: destroyed outport genom_state
demo: destroyed outport genom_metadata
demo: destroyed outport Mobile
demo: shutdown complete
eltclsh >
}}}

You can also kill genomixd, and clean up h2.
{{{
pkill genomixd
h2 end
}}}

=== ros ===

NB: If you want to run the ros version, you need to have configure your system with ros Templates. 

If you have already configure with another template, you need to restart at the configure command. It is probably better to erase the build directory or make another one:
{{{
mkdir build-ros
cd build-ros
../configure --prefix=$INSTALL_DIR --with-templates=ros/server,ros/client/c
make install
}}}

If you have not configure yet your module, you should follow Module Compilation instruction from the beginning.

If you have configure your module with ros template:

You will need to start roscore.
{{{
roscore &
}}}

The ros module has a different name.
{{{
demo-ros -b
demo: advertising ports
demo: initialized outport genom_state
demo: motion task initialized and running
demo: advertising services
demo: control task initialized and running
}}}

From now on, you can control this module exactly the same way you did with the pocolibs version.


You can also see that your ROS based demo module can be seen as a regular ROS node, with its topics, services and actions.

{{{
rosnode info demo
--------------------------------------------------------------------------------
Node [/demo]
Publications: 
 * /demo/GotoPosition/status [actionlib_msgs/GoalStatusArray]
 * /demo/MoveDistance/result [demo/MoveDistanceActionResult]
 * /demo/Mobile [demo/demo_state]
 * /rosout [rosgraph_msgs/Log]
 * /demo/genom_state [demo/genom_state_component]
 * /demo/Monitor/feedback [demo/MonitorActionFeedback]
 * /demo/MoveDistance/feedback [demo/MoveDistanceActionFeedback]
 * /demo/MoveDistance/status [actionlib_msgs/GoalStatusArray]
 * /demo/GotoPosition/feedback [demo/GotoPositionActionFeedback]
 * /demo/Monitor/result [demo/MonitorActionResult]
 * /demo/GotoPosition/result [demo/GotoPositionActionResult]
 * /demo/Monitor/status [actionlib_msgs/GoalStatusArray]

Subscriptions: 
 * /demo/Monitor/cancel [actionlib_msgs/GoalID]
 * /demo/GotoPosition/goal [demo/GotoPositionActionGoal]
 * /demo/MoveDistance/goal [demo/MoveDistanceActionGoal]
 * /demo/MoveDistance/cancel [actionlib_msgs/GoalID]
 * /demo/GotoPosition/cancel [actionlib_msgs/GoalID]
 * /demo/Monitor/goal [demo/MonitorActionGoal]

Services: 
 * /demo/connect_port
 * /demo/kill
 * /demo/GetSpeed
 * /demo/get_loggers
 * /demo/abort_activity
 * /demo/set_logger_level
 * /demo/Stop
 * /demo/SetSpeed
 * /demo/connect_remote
...
...
...
}}}

== Demo module with openprs ==

If you want to control this module with [[openprs]], you will need to install [[transgen3]], and follow this [[transgen3/tutorial/demo-transgen3|tutorial]] to create it.