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:

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:

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.

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 :

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:

Bootstrap

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:

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 tutorial to create it.