MCA2 Puma Tutorial Chapter 3

From Mca2
Revision as of 10:02, 13 August 2009 by Karaman (talk | contribs) (Simulating a single joint)
Jump to navigationJump to search


Simulating a single joint

Until now we have learned how to use the tool mcagui to create a user interface (front end). Now we shall have a look at how to implement back end controller software. So far the robot model does not really move in a realistic way. Real motors have a limited maximum velocity such that the joints cannot follow our slider movements instantaneously. Therefore we will now replace the guitest programmes with our first self-made back end. In this chapter we will develop a programme which simulates one joint of the robot. By starting this programme six times we yield the simulation of a complete 6-DOF robot.

Well prepared ?

The project directory is hopefully prepared as described at the beginning of this tutorial. We change into the main MCA2.4 directory and create our first module by:

> -C projects/puma JointSimulation

The script newModule creates the two files mJointSimulation.h and mJointSimulation.C in the puma project directory (the leading "m" indicates that the files contain a MCA2 module). These files contain the definition and implementation of the class mJointSimulation, which is derived from tModule. Every module offers five IO interfaces: ControllerInput, ControllerOutput, SensorInput, SensorOutput and Parameters.


After creation new module files contain some default definitions and default code. This code has to be deleted in most cases, but is helpful as it shows how to use the interfaces and define parameters. Do not forget to delete the defaults when continuing the tutorial.

MCA2 parameters are used to change internal module operand during runtime. They are manipulated using the tool mcabrowser. We will learn how to use these later. At the moment we only need the interfaces ControllerInput and SensorOutput.

Well understandable descriptions

All MCA2 IO interfaces are represented by vectors. Particular values of these vectors can be accessed using indices. As our code should be maintained readable for others as well we will define all input and output indices in terms of enumerations. These enumerations are already prepared in the generated file mJointSimulation.h. You only need to add the necessary values for ControllerInputs (eCI) and SensorOutputs (eSO) of our new module:

>    /*!
>     Anonymous enumeration type which contains the indices of the
>     controller inputs.
>   */
>   _DESCR_( static, mJointSimulation::ci_description, 4, Natural, cDATA_VECTOR_END_MARKER );
>   enum {
>       eCI_DESIRED_JOINT_ANGLE,  /*!< desired angle value of joint */
>       eCI_DIMENSION             /*!< Endmarker and Dimension */
>   };
>   /*!
>     Anonymous enumeration type which contains the indices of the
>     sensor outputs.
>   */
>   _DESCR_( static, mJointSimulation::so_description, 4, Natural, cDATA_VECTOR_END_MARKER );
>   enum {
>       eSO_CURRENT_JOINT_ANGLE,  /*!< simulated joint angle value */
>       eSO_DIMENSION             /*!< Endmarker and Dimension */
>   };

Now our module can receive one controller input value and set one sensor output value.

As we don't need any sensor input or controller output we remove the entries in the according enumerations:

>   /*!
>     Anonymous enumeration type which contains the indices of the
>     controller outputs.
>    */
>   _DESCR_( static, mJointSimulation::co_description, 4, Natural, cDATA_VECTOR_END_MARKER );
>   enum {
>       eCO_DIMENSION /*!< Endmarker and Dimension */
>   };
>   /*!
>     Anonymous enumeration type which contains the indices of the
>     sensor inputs.
>    */
>   _DESCR_( static, mJointSimulation::si_description, 4, Natural, cDATA_VECTOR_END_MARKER );
>   enum {
>       eSI_DIMENSION /*!< Endmarker and Dimension */
>   };

Additionally we will define parameters (ePAR) which represent the joint's boundary values (minimal and maximal joint angle) and its angular velocity. For now only the names of the parameters have to be defined in mJointSimulation.h (do not forget to delete the default parameter definitions):

>   /*!
>   Anonymous enumeration type which contains the indices of the
>   parameters.
>   */
>   enum {
>       ePAR_MIN_ANGLE,          /*!< Minimum joint angle */
>       ePAR_MAX_ANGLE,          /*!< Maximum joint angle */
>       ePAR_ANGULAR_VELOCITY,   /*!< angular velocity of the joint */
>       ePAR_DIMENSION          /*!< Endmarker and Dimension */
>   };

If you wonder what eCI_DIMENSION, eSO_DIMENSION, and ePAR_DIMENSION are for: As they are always the last entry they specify the number of ControllerInputs, SensorOutputs, and Parameters respectively.

How to create and read in parameters will be explained in the next section.

All modules implement the methods Control and Sense which are invoked by the MCA2 main loop (See MCA Introduction). Method Control is meant to retrieve information from the ControllerInputs and compute the ControllerOutputs. Its counterpart Sense computes SensorOutput values from the module's SensorInputs. Both methods may modify the internal state of the module. At this point we want to implement a puma robot simulation which represents a virtual compound of sensors and actors. The simulation is passed ControllerInput values from which it computes simulated SensorOutput values which we will visualise in mcagui. This results in a shortened sensorimotor cycle in which we do not consider the SensorInputs and we need not compute ControllerOutputs. That way ControllerInput and SensorOutput are linked via the internal state of the module to be implemented.

Preparing parameters

Parameters can be manipulated using external tools like mcabrowser. In order to prevent accidental setting of inappropriate values parameters are well defined. The definition of numerical parameters (e.g. ParameterInt and ParameterFloat) requires the specification of a minimum and a maximum value. String parameters need to be limited to in length. In our example we only need floating point values. These parameters are created within the constructor of our module which is implemented in src/mJointSimulation.C. The order of the creation sequence has to match the enumeration definitions for the parameters in the header file (do not forget to delete the default code for creating parameters at this point).

>   InitParameter( ePAR_DIMENSION,
>                  new tParameterFloat( "min angle value", 0, 2 * M_PI, 0 ),        //min,max,value
>                  new tParameterFloat( "max angle value", 0, 2 * M_PI, 2 * M_PI ), //min,max,value
>                  new tParameterFloat( "angular velocity", 0, 100, 1 )             //min,max,value
>                );

Whenever a parameter value is changed the method Exception is invoked by the main programme with type eET_ParameterChanged as parameter. The module code frame already defines method Exception. The parameter transfer has to be implemented as listed below (here the default-code for reading parameters has to be deleted as well).

>       case eET_ParameterChanged:
>           INFOMSG( "%s>> Parameter changed.\n", Description() );
>           min_angle_value = ParameterFloat( ePAR_MIN_ANGLE );
>           max_angle_value = ParameterFloat( ePAR_MAX_ANGLE );
>           angular_velocity = ParameterFloat( ePAR_ANGULAR_VELOCITY );
>           ClearParameter();
>           break;

In our example we only use floating point parameters which are read out using method ParameterFloat. For different parameter types MCA provides methods ParameterBool, ParameterString, etc.

Now that we have defined the interface of our class we can start to write the joint simulation code.