MCA2 Puma Tutorial Chapter 4

From Mca2
Revision as of 09:32, 14 August 2009 by Karaman (talk | contribs) (Check and use program parameters)
Jump to navigationJump to search

GO BACK HOME

Using Parameters

A part is the interface to the external environment for modules and groups. This also includes command line parameter input. There are many standard parameters in order to configure the program behaviour, but the programmer is also able to define application specific parameters. The standard command line parameters are explained in section 3.3 of the programmers guide .

In this chapter we learn how to use command line parameters inside a part (section 4.1 and 4.2). These parameters are then forwarded to the module which is executed inside our part (section 4.3). In section 4.4 it is explained what the default method parameters of the module constructor mean.

Note that it is important to distinguish between the different types of parameters: First of all we have the method parameters as usually used in C++. Additionally MCA provides internal part parameters and internal module parameters which can be used to adjust the behaviour to a specific configuration.

Define program parameters

Program parameters can be easily defined using the tPartParameter struct. We also recommend to use enumerations as for all array definitions in MCA. The following example defines parameters for setting name, min and max angle values and angular velocity for our example program pJointSimulation.C. Add the following lines just before void initPartDescription() in the file pJointSimulation.C:

> enum {
>   eOPT_NAME,
>   eOPT_MIN_ANGLE,
>   eOPT_MAX_ANGLE,
>   eOPT_ANGULAR_VELOCITY,
>   eOPT_DIMENSION
> };
>
> tPartParameter parameter[eOPT_DIMENSION+1]={
>   {"name:", "set the module name"},
>   {"min:","set the minimum joint angle"},
>   {"max:","set the maximum joint angle"},
>   {"v:","set the angular velocity"},
>   {0,0}
> };

Our part uses these parameter definitions if we add an additional entry into the function initPartDescription():

> void initPartDescription()
> {
>   SetProgramDescription("\n This Program simulates a single joint.\n");
>   SetProgramParameter(parameter);
> }

Save the changed pJointSimulation.C as pJointSimulation2.C, copy and change the entry in SConscript and compile everything:

> # this is a -*- python -*- file
> # -----------------------------
> Import('*')
>
>
> # ------------------
> # joint_simulation
> # simulate one joint
> # ------------------
> jointsimulation = MCAProgram('joint_simulation')
> jointsimulation.addSourceFiles("""
> pJointSimulation.C
> mJointSimulation.C
> """)
>
> jointsimulation.addLibs('mca2_kernel')
> jointsimulation.BuildIt()
> 
> # ------------------
> # joint_simulation with parameters
> # simulate one joint
> # ------------------
> jointsimulation2 = MCAProgram('joint_simulation2',jointsimulation.BuildEnv())
> jointsimulation2.AddSourceFiles("""
> pJointSimulation2.cpp
> mJointSimulation2.cpp
> """)
>
> jointsimulation2.Build()

Check and use program parameters

We defined the parameters and our program will accept parameter settings on startup. (Just call joint_simulation2 --name=hello and the program will accept it.)

But now we want to check whether the user set a parameter on startup or not. And of course we want to read the specified values and use it. A part has two simple functions that provide this functionality: ParamSet(index) returns true if the user specified a values for the parameter with given index. ParamOpt returns a pointer to a character (string) that contains the specified values. The following example shows how to check and read the parameters within the startup function of our main program pJointSimulation2.C:

> int startup( tPart* part )
> {
>     float min = 0;
>     float max = 2 * M_PI;
>     float v = 0.1;
>     char *name = 0;
> 
>     if ( part->ParamSet( eOPT_NAME ) )
>         name = part->ParamOpt( eOPT_NAME );
> 
>     // Read other parameter values
>     if ( part->ParamSet( eOPT_MIN_ANGLE ) )
>         min = atof( part->ParamOpt( eOPT_MIN_ANGLE ) );
> 
>     if ( part->ParamSet( eOPT_MAX_ANGLE ) )
>         max = atof( part->ParamOpt( eOPT_MAX_ANGLE ) );
> 
>     if ( part->ParamSet( eOPT_ANGULAR_VELOCITY ) )
>         v = atof( part->ParamOpt( eOPT_ANGULAR_VELOCITY ) );
> 
>     // Here we can use the parameters
>     // when creating mJointSimulation
> 
>     // Execute as usual
>     return part->Execute( tTime().FromMSec( 30 ) );
> }

Setting module parameters

In the previous section we checked and read program parameters. As already mentioned in the comment there, we have to create our module. But this time we want to use the new parameters. How to use the name (given by the command line parameter) is explained in this section, we just have to use it as parameter of our constructor.

The internal parameters of a module can bet set using the function SetParameters. As it is defined using ellipses, it first needs the number of values the user wants to set. If you want to set all of them, you can use the enum value ePAR_DIMENSION. Then you have to specify pairs of indices and values for each parameter that is to be set. Again, we recommend to use the enumeration values as index. The values' variables have to be of the same kind as the corresponding parameters are defined (bool,int,float,string). Here's how we do it for our example (pJointSimulation2.C):

>     // Create the module
>     mJointSimulation *joint = new mJointSimulation( part, name );
>     // Set module parameter values
>     joint->SetParameters( mJointSimulation::ePAR_DIMENSION,
>                           mJointSimulation::ePAR_MIN_ANGLE, min,
>                           mJointSimulation::ePAR_MAX_ANGLE, max,
>                           mJointSimulation::ePAR_ANGULAR_VELOCITY, v );

After compilation the joint_simulation2 example now accepts our new parameters (start the following in a shell):

> joint_simulation2 --name=waist --min=0 --max=5.585 --v=1.117 &
> joint_simulation2 --name=shoulder --min=0 --max=5.236 --v=1.047 &
> joint_simulation2 --name=elbow --min=0 --max=4.712 --v=0.942 &
> joint_simulation2 --name=wrist_rot --min=0 --max=5.236 --v=1.047 &
> joint_simulation2 --name=wrist_bend --min=0 --max=3.491 --v=0.698 &
> joint_simulation2 --name=flange --min=0 --max=4.712 --v=0.942 &

Start MCAbrowser and look at the differences: Every module has an individual name and the internal parameters are individually set to the specified values.

joint_simulation2 is better than joint_simulation but not good enough: There remain some problems: From mcagui's point of view the IOs did not change and it is difficult to distinguish between them. Moreover we have to start all parts individually and write the parameters again and again. To make things easier MCA offers mechanisms to arrange several modules in one group which is then executed in only one part.

Tip: Another advantage of executing only one part is that there is a fixed synchronisation mechanism inside a part which is not the case between parts.

The usage of groups is explained in section 5.