Configuration (Basic)

(G)What is configuration?

Often it is necessary to change the parameters in the program to be created according to the external environment of the system, the usage situation, the characteristics of individual devices, and the robot in constructing the robot system. In a simple program for simple experiments, you may be able to deal with it by hard-coding (padding) the parameters and directly rewriting and compiling each time you change them. By going a little further, reusability will be much higher by reading the parameters from file etc, passing in with the command line argument etc etc. In order to reuse one program depending on the application, externalization without embedding such parameters becomes very important.

In the RT system constructed by the RT component, various components made by various people cooperate, so the user freely defines the parameters used inside the core logic and changes it from the outside at the time of execution A function is provided for. This is called configuration (function). The configuration can have multiple parameter sets and parameter sets can be swapped all at once. By making the parameters changeable in advance, RTC can be easily reused on various systems.

configuration_example_ja.png
Configuration example

In this section, we will explain the structure and actual usage of the configuration which is one of the important functions of the RT component.

(G)How the configuration works

The figure below shows a rough structure of configuration.

configuration_functionality_ja.png
How the configuration works

We call the name and value pair of parameters configuration parameter. A component can define more than one configuration parameter, which is called the configuration set.

Furthermore, one component can have more than one configuration set, only one of which will be the value of the actual parameter. This configuration set is called active configuration . A configuration set can be named and distinguished by its name.

You can use external tools (such as RTSystemEditor or rtshell) to change individual parameters or active configuration sets. The contents of the configuration are reflected in the variables tied to the configuration (parameter variable) and can be used with the logic in the RT component. In this way, it is possible to increase the reusability of the component by making it easy to change the parameters used inside the logic from the outside.

  • Configuration: RTC's ability to externalize parameters in components
  • Configuration Parameters: Parameter actually externalized in the component. It consists of keys and values.
  • Configuration Set: List of parameters, consisting of a list of keys and values. An RTC can have multiple sets.
  • Configuration set name: The name given to the configuration set. Each set is distinguished by name.
  • Active configuration: RTC can have multiple configuration sets, among which the effective set actually reflected in the parameters is called the active configuration.
  • Parameter variable: Variable tied to the configuration parameter. When the content of the configuration is changed, the value assigned to the variable is changed.

In a typed language, the configuration parameters can be used as parameters for any type that is available in that language. Of course, the same is true for languages without type, but the important point is that when setting these parameters externally, that value is given by a string.

The configuration converts the string to each parameter type and sets it to the actual variable. Even data types that can not be easily converted from character strings to data, such as structures and arrays, can be handled in the same way for any type of data by defining the conversion function. This is a big difference from data ports and service ports that require IDL definition in advance.

(G)Define parameters

There are several ways to define the parameters used within the RT component.

  • Define it at component design in RTC Builder
  • Define the configuration parameters with rt-template
  • Write the necessary code manually

Each method will be explained below.

(G)Definition by RTC Builder

The easiest way to define the configuration parameters is to use the RTC design tool RTCBuilder to define the configuration parameters during RTC design.

The figure below shows the definition screen of RTC Builder's configuration. By defining the necessary parameters on this screen, the code necessary for using the configuration parameters is automatically generated regardless of the language.

configuration_rtcb00_ja.png
RTCBuilder setting screen

To use the configuration parameters, press the RTC Builder's Configuration tab and click the Add button next to the parameter list. Then, since one configuration parameter is added, the appropriate

  • Name (required)
  • Data type (required)
  • Default value (required)

As the name (conf_name 0 etc is default by default), please give a descriptive name briefly describing the nature of the parameter. The type names that can be selected from the drop-down list are appropriately converted and defined in each language. In languages that need not explicitly type declarations such as Python, the type name set here may not appear on the code.

As mentioned above, the configuration parameter can correspond to various types of parameters by giving the value as a string and converting the string to a specific type. However, since values are input from the outside as a character string, if there is an incorrect parameter input such as a nontranslatable character string, conversion may be an error. The default value set here is the value to be used instead when the conversion of the set value is illegal.

In addition, the following items are not required. Please enter it as necessary.

  • Variable name: A character string to be used as a variable name. If empty, the name is used.
  • Unit: A unit of this parameter. Currently, it is not used other than human reading.
  • Constraint Condition: Give constraints on this parameter. This condition is used in RTSystemEditor. You can specify inequality in case of continuous value, comma separating in enumerated value.
  • Widget: The control used when manipulating parameters with RTSystemEditor. You can choose from text, slider, spin, radio.
  • Step: Specify the step when the above widget is slider or spin.

    param1_slider_ja.png param2_spin_ja.png
    Slider and spin setting

param3_radio_ja.png param4_text_ja.png
Setting radio buttons and text

For details, refer to the hint on the right side of the screen and the RTCBuilder manual.

(G)Definition by rtc-template

rtc-template is a component template generator to use from the command line. To use the configuration with rtc-template, specify as follows.

    /usr/local/bin/rtc-template -bcxx --module-name=ConfigSample 
    --module-type=DataFlowComponent 
    --module-desc=Configuration example component --module-version=1.0 
    --module-vendor=Noriaki Ando, AIST --module-category=example 
    --module-comp-type=DataFlowComponent --module-act-type=SPORADIC 
    --module-max-inst=10 --config=int_param0:int:0 
    --config=int_param1:int:1 --config=double_param0:double:0.11 
    --config=double_param1:double:9.9 
    --config=str_param0:std::string:hoge 
    --config=std_param:std::string:dara 
    --config=vector_param0:std::vector<double>:0.0,1.0,2.0,3.0,4.0
 
       # In fact, please input on one line, or supplement the continuation character at the end of the line (\, on UNIX ^ on Windows)

This is an example of specification with ConfigSample attached to the sample.

 --config = <name>:<data type>:<default value>

It is specified as follows. For the data type, you specify the data type to be used in that language, but it may not work well with primitive types, or you may need to manually modify it.

(G)Manual definition

Although less recommended, you can manually define the configuration parameters. It is effective when you want to add new parameters etc, but if you do not update the document or RTC.xml file etc., third parties do not have consistency of specification and implementation when using this RTC Please be aware that there is a possibility of confusion.

However, it is meaningful to know how the configuration is declared and used, so I will explain it here.

The following procedure is necessary to use the configuration.

(G)Determine the usage, name and type of configuration parameters (hereafter referred to as parameters)

As mentioned above, decide which part of the component you want to use the parameter, the name that characterizes the parameter, and the type name (for languages with type) at the time of implementation.

(G)Declare the parameter variable to the component's header (private / protected)

If it is a file generated by RTC Builder or rtc-template, there are parts surrounded by the following tags, so declare variables for the configuration parameters here.

  // Configuration variable declaration
  // <rtc-template block="config_declare">
 
  // </rtc-template>

In the above example of ConfigSample, it becomes as follows.

  // Configuration variable declaration
  // <rtc-template block="config_declare">
  int m_int_param0;
  int m_int_param1;
  double m_double_param0;
  double m_double_param1;
  std::string m_str_param0;
  std::string m_str_param1;
  std::vector<double> m_vector_param0;
  
  // </rtc-template>

(G)Add parameter declaration and default value to static variable <component name> _spec [] of component implementation file

Configuration parameters are managed within the component in a data store named Properties. Within this Properties,

 conf.<configuration set name>.<parameter name>

Keeping the configuration parameters with the key. The default value default configuration set name is reserved and all default values are defined as this default configuration set.

For the above ConfigSample, add as follows.

 // Module specification
 // <rtc-template block="module_spec">
 static const char* configsample_spec[] =
   {
     "implementation_id", "ConfigSample",
     "type_name",         "ConfigSample",
     "description",       "Configuration example component",
     "version",           "1.0",
     "vendor",            "Noriaki Ando, AIST",
     "category",          "example",
     "activity_type",     "DataFlowComponent",
     "max_instance",      "10",
     "language",          "C++",
     "lang_type",         "compile",
     // Configuration variables
     "conf.default.int_param0", "0",
     "conf.default.int_param1", "1",
     "conf.default.double_param0", "0.11",
     "conf.default.double_param1", "9.9",
     "conf.default.str_param0", "hoge",
     "conf.default.str_param1", "dara",
     "conf.default.vector_param0", "0.0,1.0,2.0,3.0,4.0",
  
     ""
   };
 // </rtc-template>

Configuration variables The following part is the definition of the default configuration set.

(G)Initialize each variable with an initializer

Variables generated by RTCBuilder and rtc-template are not initialized by the initializer of the constructor, but it is better to initialize all variables with initializers of the constructor, if possible. In addition, since default values are set for each variable after the bindParameter () function in the onInitialize () function is called, in principle it should not be used before that.

(G)Bind parameters and variables with bindParameter() function

Finally, by binding the names of variables and parameters, default values, and further conversion functions, we simply make the variables configuration parameters. We use bindParameter () which is a member function (method) of the RTObject class.

 bindParameter (<parameter name (string)>, variable, <default value (character string)>, <conversion function>)

In the above ConfigSample (C ++ example) it looks like the following.

  // <rtc-template block="bind_config">
  // Bind variables and configuration variable
  bindParameter("int_param0", m_int_param0, "0");
  bindParameter("int_param1", m_int_param1, "1");
  bindParameter("double_param0", m_double_param0, "0.11");
  bindParameter("double_param1", m_double_param1, "9.9");
  bindParameter("str_param0", m_str_param0, "hoge");
  bindParameter("str_param1", m_str_param1, "dara");
  bindParameter("vector_param0", m_vector_param0, "0.0,1.0,2.0,3.0,4.0");
  
  // </rtc-template>

In this way, each variable and configuration parameter are bound, and configuration parameters are made available that can manipulate these variables from RTSystemEditor etc.

Note that the conversion function given to bindParameter () is unnecessary for built-in type as in the above example, and it is not necessary to explicitly give it. However, if you want to use your own structure or complex type etc as configuration parameters, you need to define and give the conversion from these strings to those types. Details of the conversion function will be described later.

(G)Using parameters

Using parameters is very easy. As we have just mentioned, we simply use variables declared as configuration parameters. However, there are some conditions to use, and it is necessary to use it by observing this condition.

(G)Callback function that variables can use

The configuration variable can only be used within a specific callback function (onXXX ()). Changing the configuration variables from outside is done asynchronously. In such cases, it is necessary to control exclusive access to variables with mutex etc. In order to realize this, it is necessary for component developers to mutex protect themselves when accessing each variable. In order to avoid this, OpenRTM-aist makes external configuration changes be done outside the callback function.

The available callback functions are as follows.

  • onInitialize() (※)
  • onActivated()
  • onExecute()
  • onStateUpdate()
  • onDeactivate()
  • onAborting()
  • onError()
  • onReset()
  • onFinalize() (※)

Configuration parameters can be used within almost all callback functions. However, in onInitialize (), of course you can not use the configuration parameter before doing bindParameter (). Also, within onFinalize (), changes made to the configuration parameters may not be reflected immediately before the call.

(G)Variable is read only

The configuration parameter variable is changed from outside the component and its value is assigned to the parameter variable. However, for parameter variables Even if you write it inside a function such as onExecute (), it will not be reflected in the value of the parameter seen from the outside.

In this way, since changing the value of a variable is one way, writing to a variable from inside the component is meaningless. Let's use the configuration variable as read only.

(G)Always check if the value is correct

The value of the configuration parameter is converted to the variable actually used by converting what is given as a character string from the outside by the conversion function as described above. Since it is a character string, it is possible that a character string is assigned to where the value should be assigned originally, or a variable of size larger than the upper limit may be assigned to the variable declared with short int. Therefore, on the receiving side, it is recommended that you always check on the program before use whether it is within the range of the expected value or not assigned an unlikely value.

(G)Set parameters

We mentioned above that the configuration parameters have several sets and can change them at the same time at run time. On the other hand, when designing the component with RTC Builder or rtc-template, only the default configuration set could be defined. This section explains how to use the configuration set.

(G)Component configuration file

The default configuration set is embedded in the source code. In the same way, other configuration sets can also be increased in principle by embedding them in the source code. However, since the purpose of the RTC configuration function was to use one component for various purposes by changing the parameters according to the application without changing the source code, the other configuration set It is totally overwhelmed to embed.

The configuration set can be given in the component's configuration file. There is rtc.conf in the file that configures the component, which is mainly a configuration file for middleware that manages components, and the configuration file for the component is specified in rtc.conf as follows can.

 corba.nameservers: localhost
 naming.formats: %h.host_cxt/%n.rtc
 example.ConfigSample.config_file: configsample.conf

The part of example.ConfigSample.config_file is the specified part of the component's configuration file. The part that specifies the configuration file is as follows.

 <Category name>.<Module name>.config_file: <file name>

You can also give an instance name instead of the module name of the component.

 <Category name>.<Instance name>.config_file: <file name>

Therefore, different configuration files can be given for each instance.

 example.ConfigSample0.config_file: consout0.conf
 example.ConfigSample1.config_file: consout1.conf
 example.ConfigSample2.config_file: consout2.conf

(G)Setting the configuration set

In the configuration file, describe the configuration set you want to use.

 configuration.active_config: mode1
 
 conf.mode0.int_param0: 12345
 conf.mode0.int_param1: 98765
 conf.mode0.double_param0: 3.141592653589793238462643383279
 conf.mode0.double_param1: 2.718281828459045235360287471352
 conf.mode0.str_param0: mode0
 conf.mode0.str_param1: foo
 conf.mode0.vector_param0: 0.0,0.1,0.2,0.3,0.4
 
 conf.mode1.int_param0: -999
 conf.mode1.int_param1: 999
 conf.mode1.double_param0: 297992458
 conf.mode1.double_param1: 2.97992458e+8
 conf.mode1.str_param0: mode1
 conf.mode1.str_param1: AIST
 conf.mode1.vector_param0: 1,2,3,4,5,6,7,8,9
 
 conf.__widget__.int_param0: slider.1
 conf.__widget__.int_param1: spin
 conf.__widget__.double_param0: slider.0.1
 conf.__widget__.double_param1: text
 conf.__widget__.str_param0: radio
 conf.__widget__.str_param1: text
 conf.__widget__.vector_param0: text
 
 conf.__constraints__.int_param0: 0<=x<=150
 conf.__constraints__.int_param1: 0<=x<=1000
 conf.__constraints__.double_param0: 0<=x<=100
 conf.__constraints__.double_param1: 
 conf.__constraints__.str_param0: (default,mode0,mode1,foo,bar,radio)
 conf.__constraints__.str_param1: 
 conf.__constraints__.vector_param0: 

(G)Specifying the active configuration set

In the first line, configuration.active_config specifies the active configuration set name. In this case, it is necessary to specify the existing set name with the set name called mode 1.

 configuration.active_config: mode1

(G)Setting the configuration set

Next is a list of parameters starting with conf.mode 0, which is a list of configuration parameters for set name mode 0 . How to specify is almost the same as source code

 conf.<set name>.<parameter name>:<default value>

Has become. Be sure to specify all the configuration parameters that exist. If not specified, the default value is used. Next, there is a list of parameters starting with conf.mode 1, as well as mode 0, this is the setting of the parameter named mode 1.

(G)Extension

(G)conf._ widget_ setting

Next, there is a setting list that starts with conf._ widget_. This is a special parameter used in RTSystemEditor. I mentioned above that widget can be specified when setting configuration parameters with RTCBuilder, but the contents set here will be set to conf._ widget_. You can set four kinds of slider, radio, spin, text, and when you open the configuration parameter setting dialog in RTSystemEditor, you can control parameters with slider, radio button, spin button, text box respectively .

 conf.__widget __. <parameter name>: widget name

  • When setting slider (slider)
     conf.__widget__.int_param0: slider.5

By setting as above, the step width of the slider can be set to 5. At this time, this step size can not be decimals. However, there is a possibility that it will be improved by future upgrading.

  • When spin button (spin) is set
     conf.__widget__.int_param1: spin

The step width of the spin button is always 1 increment. It is recommended that it be used only for integer value parameters such as int.

  • When radio button (radio) is set
     conf__widget__str_param0: radio
  • When text (text) is set
     conf__widget__.str_param1: text

If these conf._widget_ parameters are set, the conf._ constraints_ parameter must also be set.

(G)conf._constraints_ setting

The conf._constraints_ parameter is a special parameter for setting a range of values. An example of setting is shown below. Be careful when setting invalid parameters because the widget will not be displayed properly.

  • If you set a slider (slider), use the equal sign and inequality signs for the temporary variable x as shown below.
     conf.__constraints__.int_param0: 0<=x<=150
  • When you set the spin button (spin), specify it using the equal sign and the inequality sign of the temporary variable x like the slider.
     conf.__constraints__.int_param0: 0<=x<=1000
  • If you set the radio button (radio), separate the button names in parentheses with commas. Multiple button names can be specified.
     conf.__constraints__.str_param0: (default,mode0,mode1)
  • If you set text (text), specify the character you want to display.
     conf.__constraints__.str_param1: AIST

Below is an example of display in RTSystemEditor according to the above setting.

configuration_constraints_ja.png
display example of conf._constraints_

(G)Conversion function

For C++ and others, you do not need to specify conversion functions, especially for built-in types such as int and double. Meanwhile, we used user-specific types such as structure and STL container There are also cases. In this case, it is necessary to give bindParameter () as a function how to convert from a character string to each type.

Regarding conversion functions, there are rules for each language as follows. The method for each language will be described below.

(G)Conversion function for C++

In C++, the prototype declaration of bindParameter is

 template <typename VarType>
     bool bindParameter(const char* param_name, VarType& var,
                const char* def_val,
                 bool (*trans)(VarType&, const char*) = coil::stringTo)
               
The conversion from the character string to the relevant type is done by giving appropriate function pointer to the trans of the fourth argument. By default, the coil library function stringTo () function is given. You can write a conversion function equivalent to this stringTo () yourself, but you can also give a function pointer, but the coil :: stringTo () function itself is also a function template, and operator >> ( )function

 std::istream& operator>>(std::istream&, T)

If it is defined, it will automatically be used to convert from a string to a specific type.

That is, if std :: cin >> <variable of one type> can be written, operator >> () is defined for that type, and in particular as a configuration parameter without writing a conversion function You can use it.

If there is no conversion function, for example, a comma-separated numeric string

 0.0,1.0,2.0,3.0,4.0

To convert to std :: vector <double>

 #include <istream>
 #include <ostream>
 #include <vector>
 #include <string>
 #include <coil/stringutil.h>
 
 template<typename T>
 std::istream& operator>>(std::istream& is, std::vector<T>& v)
 {
   std::string s;
   std::vector<std::string> sv;
   is >> s;
   sv = coil::split(s ,",");
   v.resize(sv.size());
   for (int i(0), len(sv.size()); i < len; ++i)
     {
       T tv;
       if (coil::stringTo(tv, sv[i].c_str()))
         {
           v[i] = tv;
         }
     }
   return is;
 }

It can be implemented in this way. This is VectorConvert.h included in the source of the OpenRTM-aist C++ version, ConfigSample component.

If we include this in the source called bindParameter () (eg ConfigSample.cpp if it is a ConfigSample component), usually in the implementation source of the component, the compiler will decide at compile time and the appropriate conversion function will be used .

(G)Conversion function for Java

In the case of Java, instead of giving a conversion function separately, describe the conversion from character string to actual type in the stringFrom () method defined in the holder class of the configuration variable.

Below is the conversion function for converting a comma-separated numeric string to Vector type defined in ConfigSampole of OpenRTM-aist Java version.

 package RTMExamples.ConfigSample;
 
 import java.io.Serializable;
 import java.util.Vector;
 
 import jp.go.aist.rtm.RTC.util.ValueHolder;
 
 public class VectorHolder  implements ValueHolder, Serializable {
 
     /**
      * Vector type data setting value
      */
     public Vector value = null;
 
     /**
      * Default constructor
      *
      */
     public VectorHolder() {
     }
 
     /**
      * constructor
      *
      * @param initialValue initial value
      *
      */
     public VectorHolder(Vector initialValue) {
         value = new Vector(initialValue);
     }
 
     /**
      * Convert from character string to Vector type and set
      *
      * @param def_val Set value string representation
      *
      */
     public void stringFrom(String def_val) throws Exception {
         value = new Vector();
         String values[] = def_val.split(",");
         for( int intIdx=0;intIdx<values.length;intIdx++ ) {
             value.add(values[intIdx]);
         }
     }
     /**
      * Acquire setting value
      *
     * @return Setting value
      *
      */
     public Vector getValue(){
         return value;
     }
     /**
      * Convert setting value to character string
      *
     * @return Conversion string
      *
      */
     public String toString(){
         StringBuffer retVal = new StringBuffer();
         while(value.iterator().hasNext()) {
             retVal.append(value.iterator().next());
             if(value.iterator().hasNext()) retVal.append("'");
         }
         return retVal.toString();
     }
 }

(G)Conversion function for Python

In Python version OpenRTM - aist, by default, it corresponds to the basic type and its list, and if other conversion is necessary, define a function such as bool stringTo (type, string) and call the first of bindParameter () 4 Pass the function object as an argument.

(G)What to make as a parameter?

Let's think about what you need to make as a configuration parameter to create an RT component.

There are certain parameters, and there are several ways to change this externally. How to change using the data port, change by using the service port, and change using the configuration.

The configuration function is used to change the parameters inside the component. Therefore, parameters in the logic should be externally changeable as configuration parameters. However, I think that there are cases where it is in doubt whether a certain variable should be used as a configuration parameter or not. Here I will think about a case like that.

(G)Update Frequency

Configuration parameters are usually used to give parameters externally only once the system is running or only when configuration changes are required. If the update frequency is about once or several times on the system life cycle, it is a good idea to use the configuration.

Also as mentioned above, the configuration is given as a string from the tool or application, and it is converted into each type in the component. It takes time to convert to some extent (although it is about several us to several hundreds of us in recent PCs), it is not suitable for use in sending data in 1 ms cycle, for example. How about changing the parameter at that frequency? When actually using it, although it depends on the number of parameters and the speed of the computer and the network, you can change the parameters with practically no problem at frequencies of hundreds of ms or more. However, if you need to change such values periodically, you should use the data port.

(G)Timing of update

The configuration parameters can be updated at any time from tools such as RTSystemEditor and rtshell. However, actually changed parameters are reflected in actual variables at a certain timing before being referenced in functions used in functions such as onExecute and onActivated. The update timing is as follows.

At initialization Immediately after onInitialize ()
When activated Just before onActivated() is called
On error Immediately after onError()
Active state Immediately after onStateUpdate() ≒ After onExecute, immediately before the next onExecute()

(G)Is it data or parameters?

For example, consider a system that periodically sends data from a remote sensor to a central server. Data is sent only once per hour, and the server logs it. Should this data be sent using the data port? Or should I use the service port or should I use the configuration?

Since what is sent is data of the sensor, it can be said that it is best to send using the data port. Since the configuration is a mechanism to set the parameters from the outside, even if the update frequency is once per hour, it is inappropriate to communicate this data to the components in the configuration . However, if you want to realize complicated interactions (such as transactions) between the client and the server that can be realized with the data port, the service port may be used.

(G)Is it a service or parameter?

Whether it should be a data port or a configuration, in practice it will not get lost much. On the other hand, I think that there are many situations where you are at a loss as to whether you should change the parameters in the RTC logic from the service port or as configuration parameters.

If a component provides some sort of typical and somewhat comprehensive functionality, that functionality is provided externally through the interface of the service port. The service interface provides operations to acquire the target state and change the setting · mode · parameters. Apart from acquiring the state, the function of setting up and changing the mode parameter is very similar to the configuration.

As it turns out, it does not matter much which way you set it, but the function of the target RTC has already been defined as a service interface, and it is necessary to acquire and set the state, etc., to provide a somewhat complicated function In that case, it can be said that operation via the service interface is suitable. It is a good idea to use the configuration for setting other simple parameters and modes.

(G)Summary

In this theory, I explained how to define and how to use the configuration function. Parameters in the logic should be externalized using this function as much as possible to improve the reusability of the component. You also need to pay attention to what you should or should not do for the configuration parameters. If you use the configuration function effectively, the components you create will also be highly reusable.

Download

latest Releases : 2.0.0-RELESE

2.0.0-RELESE Download page

Number of Projects

Choreonoid

Motion editor/Dynamics simulator

OpenHRP3

Dynamics simulator

OpenRTP

Integrated Development Platform

AIST RTC collection

RT-Components collection by AIST

TORK

Tokyo Opensource Robotics Association

DAQ-Middleware

Middleware for DAQ (Data Aquisition) by KEK