Tutorial - Making Module
SkyAI
/
Documentation
/ Tutorial - Making Module
-- Use page as template --
Demonstrations
Developers
Developers/akihikoy
Documentation
Documentation/Architecture Overview
Documentation/Installation Guide
Documentation/Installation Guide/Debian and Ubuntu
Documentation/Installation Guide/Mac
Documentation/Introduction
Documentation/Keywords
Documentation/Modular Architecture
Documentation/Running Demos
Documentation/Running Demos/Common Usage
Documentation/Running Demos/bioloid
Documentation/Running Demos/humanoid01
Documentation/Running Demos/maze2d
Documentation/Script Language
Documentation/Tutorial - Example - Maze
Documentation/Tutorial - Example - Mountain Car
Documentation/Tutorial - Making Executable
Documentation/Tutorial - Making Module
Documentation/Tutorial - Making Original Domain
Documentation/Tutorial - Making RL Module
Documentation/Tutorial - Writing Agent Script
FormattingRules
Help
InterWikiName
License
MenuBar
Recent Changes
Recent Changes/0.2.0
RecentDeleted
SandBox
SkyAI
''Table of Contents'' #contents * Overview [#w6685947] Making a module can be done through the following steps: + Create a configuration class [optional] -- Copy and paste the template -- Add some variables + Create a memory class [optional] -- Copy and paste the template -- Add some variables + Create the module class -- Copy and paste the template -- Add ports (signal, slot, in, out) + Write a SkyAI module declaration -- Just write a single line macro You can easily modify any parts later; take it easy! * Include [#q5ca70df] The header skyai/skyai.h is needed: #codeh(cpp){{ #include <skyai/skyai.h> }} * Configuration Class [#u98bbe9f] + Copy and paste the template #codeh(cpp){{ //=========================================================================================== class TXxConfigurations //=========================================================================================== { public: TReal TestC; TXxConfigurations (var_space::TVariableMap &mmap) : TestC (0.0l) { Register(mmap); } void Register (var_space::TVariableMap &mmap) { #define ADD(x_member) AddToVarMap(mmap, #x_member, x_member) ADD( TestC ); #undef ADD } }; //------------------------------------------------------------------------------------------- }} + Add some variables -- In the above template, a variable ''TestC'' is added. Remove it and add your configuration variables. -- You need to write each variable three times: +++ Declaration (e.g. TReal TestC;) +++ Initialization at the constructor [optional] (e.g. TestC(0.0l)) +++ Register (e.g. ADD(TestC);) :Note| If you want to add std::vector etc., include lora/variable_space_impl.h. #codeh(cpp){{ #include <lora/variable_space_impl.h> }} * Memory Class [#t5fd156f] + Copy and paste the template #codeh(cpp){{ //=========================================================================================== class TXxMemory //=========================================================================================== { public: TReal TestM; TXxMemory (var_space::TVariableMap &mmap) : TestM (0.0l) { Register(mmap); } void Register (var_space::TVariableMap &mmap) { #define ADD(x_member) AddToVarMap(mmap, #x_member, x_member) ADD( TestM ); #undef ADD } }; //------------------------------------------------------------------------------------------- }} + Add some variables -- Same as the configuration class * Module class [#ff1a8bc9] + Copy and paste the template&br; Simple template: #codeh(cpp){{ //=========================================================================================== //!\brief XX module class MXxModule : public MParentModule //=========================================================================================== { public: typedef MParentModule TParent; typedef MXxModule TThis; SKYAI_MODULE_NAMES(MXxModule) MXxModule (const std::string &v_instance_name) : TParent (v_instance_name), conf_ (TParent::param_box_config_map()), mem_ (TParent::param_box_memory_map()) { } protected: TXxConfigurations conf_; TXxMemory mem_; }; // end of MXxModule //------------------------------------------------------------------------------------------- }} Verbose template: #codeh(cpp){{ //=========================================================================================== //!\brief XX module class MXxModule : public MParentModule //=========================================================================================== { public: typedef MParentModule TParent; // optional typedef MXxModule TThis; // optional SKYAI_MODULE_NAMES(MXxModule) // mandatory MXxModule (const std::string &v_instance_name) : TParent (v_instance_name), // mandatory conf_ (TParent::param_box_config_map()), mem_ (TParent::param_box_memory_map()), slot_slot1 (*this), // optional signal_signal1 (*this), // optional out_out1 (*this), // optional in_in1 (*this) // optional { add_slot_port (slot_slot1); // optional add_signal_port (signal_signal1); // optional add_out_port (out_out1); // optional add_in_port (in_in1); // optional } protected: TXxConfigurations conf_; // optional TXxMemory mem_; // optional MAKE_SLOT_PORT(slot_slot1, TOutType, (const TInType &x), (x), TThis); // optional MAKE_SIGNAL_PORT(signal_signal1, const TOutType& (const TInType &), TThis); // optional MAKE_OUT_PORT(out_out1, const TOutType&, (const TInType &x), (x), TThis); // optional MAKE_IN_PORT(in_in1, const TOutType& (const TInType &), TThis); // optional virtual TOutType slot_slot1_exec (const TInType &x) // optional { ... } virtual const TOutType& out_out1_get (const TInType &x) const // optional { ... } }; // end of MXxModule //------------------------------------------------------------------------------------------- }} + If you do not use the configuration box or the memory box, you can remove conf_ or mem_ (of course, remove the declaration). Otherwise, replace TXxConfigurations and/or TXxMemory by your own class name. + Replace every MXxModule by the name of your module. + Replace every MParentModule by the parent module (usually, use TModuleInterface). + Add ports -- Adding a ''slot port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_SLOT_PORT(slot_slot1, TOutType, (const TInType &x), (x), TThis); // change slot1 to the name of the slot port // change TOutType to the return type of the callback function // change const TInType &x to the parameter list of the callback function // change x to the argument list of the callback function // e.g. MAKE_SLOT_PORT(slot_action, void, (const TReal &x,const TReal &y), (x,y), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... slot_slot1 (*this), // like this ... }} +++ Use the add_slot_port function at the constructor: #codeh(cpp){{ add_slot_port (slot_slot1); }} +++ Implement the callback function: #codeh(cpp){{ // change slot1 to the name of the slot port virtual TOutType slot_slot1_exec (const TInType &x) { ... } }} -- Adding a ''signal port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_SIGNAL_PORT(signal_signal1, const TOutType& (const TInType &), TThis); // change signal1 to the name of the signal port // change TOutType to the return type of the callback function // change const TInType & to the parameter list of the callback function // e.g. MAKE_SIGNAL_PORT(signal_action, void (const TReal &x,const TReal &y), TThis) }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... signal_signal1 (*this), // like this ... }} +++ Use the add_signal_port function at the constructor: #codeh(cpp){{ add_signal_port (signal_signal1); }} -- Adding an ''out port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_OUT_PORT(out_out1, const TOutType&, (const TInType &x), (x), TThis); // change out1 to the name of the out port // change TOutType to the return type of the function // change const TInType &x to the parameter list of the function // change x to the argument list of the function // e.g. MAKE_OUT_PORT(out_state, const TRealVector&, (void), (), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... out_out1 (*this), // like this ... }} +++ Use the add_out_port function at the constructor: #codeh(cpp){{ add_out_port (out_out1); }} +++ Implement the function: #codeh(cpp){{ // change out1 to the name of the out port virtual const TOutType& out_out1_get (const TInType &x) const { ... } }} -- Adding an ''in port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_IN_PORT(in_in1, const TOutType& (const TInType &), TThis); // change in1 to the name of the in port // change TOutType to the return type of the function // change const TInType &x to the parameter list of the function // e.g. MAKE_IN_PORT(in_state, const TRealVector& (void), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... in_in1 (*this), // like this ... }} +++ Use the add_in_port function at the constructor: #codeh(cpp){{ add_in_port (in_in1); }} * SkyAI Module Declaration [#sfeabb06] + Just write a single line macro at the source code (do not write in a header) #codeh(cpp){{ SKYAI_ADD_MODULE(MXxModule) }} * Implementing Functions [#u58a602b] In the member functions of a module including the callbacks of slot ports and the functions of out ports, the following elements are important: ** Emit Signal [#wb00f568] In order to emit a signal at a signal port, write as follows: #codeh(cpp){{ signal_signal1.ExecAll(x,y); }} The member function ExecAll emits a signal to every slot ports connected to the signal port. The return values are ignored. If no slot port is connected, nothing happens. ** Call Function [#o37d37cc] In order to use a function connected to an in port, write as follows: #codeh(cpp){{ TRealVector y= in_in1.GetFirst(x); }} Here, the member function GetFirst execute the function of the first out port connected to the in port with an argument x, whose return is stored in y. Recall that in default, only one out port can be connected to an in port. If no out port is connected, GetFirst causes an error. In order to avoid the error, you need to check the size of connections by: #codeh(cpp){{ in_in1.ConnectionSize() }} this returns the number of connected out ports. We suggest to wrap the GetFirst by using a macro as follows: #codeh(cpp){{ MAKE_IN_PORT(in_state, const TRealVector& (void), TThis); MAKE_IN_PORT(in_func, const TReal& (const TReal &x), TThis); #define GET_FROM_IN_PORT(x_in,x_return_type,x_arg_list,x_param_list) \ x_return_type get_##x_in x_arg_list const \ { \ if (in_##x_in.ConnectionSize()==0) \ {LERROR("in "<<ModuleUniqueCode()<<", in_" #x_in " must be connected."); lexit(df);} \ return in_##x_in.GetFirst x_param_list; \ } GET_FROM_IN_PORT(state, const TRealVector&, (void), ()) GET_FROM_IN_PORT(func, const TReal&, (const TReal &x), (x)) #undef GET_FROM_IN_PORT }} Then, we can use get_state and get_func like a normal function; e.g. #codeh(cpp){{ TRealVector x= get_state(); TReal y= get_func(1.2); }} The macro GET_FROM_IN_PORT is generic, so you can copy and paste it in your code as is. Do not forget to un-define it (i.e. #undef GET_FROM_IN_PORT).
Do not change timestamp
''Table of Contents'' #contents * Overview [#w6685947] Making a module can be done through the following steps: + Create a configuration class [optional] -- Copy and paste the template -- Add some variables + Create a memory class [optional] -- Copy and paste the template -- Add some variables + Create the module class -- Copy and paste the template -- Add ports (signal, slot, in, out) + Write a SkyAI module declaration -- Just write a single line macro You can easily modify any parts later; take it easy! * Include [#q5ca70df] The header skyai/skyai.h is needed: #codeh(cpp){{ #include <skyai/skyai.h> }} * Configuration Class [#u98bbe9f] + Copy and paste the template #codeh(cpp){{ //=========================================================================================== class TXxConfigurations //=========================================================================================== { public: TReal TestC; TXxConfigurations (var_space::TVariableMap &mmap) : TestC (0.0l) { Register(mmap); } void Register (var_space::TVariableMap &mmap) { #define ADD(x_member) AddToVarMap(mmap, #x_member, x_member) ADD( TestC ); #undef ADD } }; //------------------------------------------------------------------------------------------- }} + Add some variables -- In the above template, a variable ''TestC'' is added. Remove it and add your configuration variables. -- You need to write each variable three times: +++ Declaration (e.g. TReal TestC;) +++ Initialization at the constructor [optional] (e.g. TestC(0.0l)) +++ Register (e.g. ADD(TestC);) :Note| If you want to add std::vector etc., include lora/variable_space_impl.h. #codeh(cpp){{ #include <lora/variable_space_impl.h> }} * Memory Class [#t5fd156f] + Copy and paste the template #codeh(cpp){{ //=========================================================================================== class TXxMemory //=========================================================================================== { public: TReal TestM; TXxMemory (var_space::TVariableMap &mmap) : TestM (0.0l) { Register(mmap); } void Register (var_space::TVariableMap &mmap) { #define ADD(x_member) AddToVarMap(mmap, #x_member, x_member) ADD( TestM ); #undef ADD } }; //------------------------------------------------------------------------------------------- }} + Add some variables -- Same as the configuration class * Module class [#ff1a8bc9] + Copy and paste the template&br; Simple template: #codeh(cpp){{ //=========================================================================================== //!\brief XX module class MXxModule : public MParentModule //=========================================================================================== { public: typedef MParentModule TParent; typedef MXxModule TThis; SKYAI_MODULE_NAMES(MXxModule) MXxModule (const std::string &v_instance_name) : TParent (v_instance_name), conf_ (TParent::param_box_config_map()), mem_ (TParent::param_box_memory_map()) { } protected: TXxConfigurations conf_; TXxMemory mem_; }; // end of MXxModule //------------------------------------------------------------------------------------------- }} Verbose template: #codeh(cpp){{ //=========================================================================================== //!\brief XX module class MXxModule : public MParentModule //=========================================================================================== { public: typedef MParentModule TParent; // optional typedef MXxModule TThis; // optional SKYAI_MODULE_NAMES(MXxModule) // mandatory MXxModule (const std::string &v_instance_name) : TParent (v_instance_name), // mandatory conf_ (TParent::param_box_config_map()), mem_ (TParent::param_box_memory_map()), slot_slot1 (*this), // optional signal_signal1 (*this), // optional out_out1 (*this), // optional in_in1 (*this) // optional { add_slot_port (slot_slot1); // optional add_signal_port (signal_signal1); // optional add_out_port (out_out1); // optional add_in_port (in_in1); // optional } protected: TXxConfigurations conf_; // optional TXxMemory mem_; // optional MAKE_SLOT_PORT(slot_slot1, TOutType, (const TInType &x), (x), TThis); // optional MAKE_SIGNAL_PORT(signal_signal1, const TOutType& (const TInType &), TThis); // optional MAKE_OUT_PORT(out_out1, const TOutType&, (const TInType &x), (x), TThis); // optional MAKE_IN_PORT(in_in1, const TOutType& (const TInType &), TThis); // optional virtual TOutType slot_slot1_exec (const TInType &x) // optional { ... } virtual const TOutType& out_out1_get (const TInType &x) const // optional { ... } }; // end of MXxModule //------------------------------------------------------------------------------------------- }} + If you do not use the configuration box or the memory box, you can remove conf_ or mem_ (of course, remove the declaration). Otherwise, replace TXxConfigurations and/or TXxMemory by your own class name. + Replace every MXxModule by the name of your module. + Replace every MParentModule by the parent module (usually, use TModuleInterface). + Add ports -- Adding a ''slot port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_SLOT_PORT(slot_slot1, TOutType, (const TInType &x), (x), TThis); // change slot1 to the name of the slot port // change TOutType to the return type of the callback function // change const TInType &x to the parameter list of the callback function // change x to the argument list of the callback function // e.g. MAKE_SLOT_PORT(slot_action, void, (const TReal &x,const TReal &y), (x,y), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... slot_slot1 (*this), // like this ... }} +++ Use the add_slot_port function at the constructor: #codeh(cpp){{ add_slot_port (slot_slot1); }} +++ Implement the callback function: #codeh(cpp){{ // change slot1 to the name of the slot port virtual TOutType slot_slot1_exec (const TInType &x) { ... } }} -- Adding a ''signal port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_SIGNAL_PORT(signal_signal1, const TOutType& (const TInType &), TThis); // change signal1 to the name of the signal port // change TOutType to the return type of the callback function // change const TInType & to the parameter list of the callback function // e.g. MAKE_SIGNAL_PORT(signal_action, void (const TReal &x,const TReal &y), TThis) }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... signal_signal1 (*this), // like this ... }} +++ Use the add_signal_port function at the constructor: #codeh(cpp){{ add_signal_port (signal_signal1); }} -- Adding an ''out port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_OUT_PORT(out_out1, const TOutType&, (const TInType &x), (x), TThis); // change out1 to the name of the out port // change TOutType to the return type of the function // change const TInType &x to the parameter list of the function // change x to the argument list of the function // e.g. MAKE_OUT_PORT(out_state, const TRealVector&, (void), (), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... out_out1 (*this), // like this ... }} +++ Use the add_out_port function at the constructor: #codeh(cpp){{ add_out_port (out_out1); }} +++ Implement the function: #codeh(cpp){{ // change out1 to the name of the out port virtual const TOutType& out_out1_get (const TInType &x) const { ... } }} -- Adding an ''in port'': +++ Declare at the protected section: #codeh(cpp){{ MAKE_IN_PORT(in_in1, const TOutType& (const TInType &), TThis); // change in1 to the name of the in port // change TOutType to the return type of the function // change const TInType &x to the parameter list of the function // e.g. MAKE_IN_PORT(in_state, const TRealVector& (void), TThis); }} +++ Write the initialization at the constructor: #codeh(cpp){{ MXxModule (const std::string &v_instance_name) : ... in_in1 (*this), // like this ... }} +++ Use the add_in_port function at the constructor: #codeh(cpp){{ add_in_port (in_in1); }} * SkyAI Module Declaration [#sfeabb06] + Just write a single line macro at the source code (do not write in a header) #codeh(cpp){{ SKYAI_ADD_MODULE(MXxModule) }} * Implementing Functions [#u58a602b] In the member functions of a module including the callbacks of slot ports and the functions of out ports, the following elements are important: ** Emit Signal [#wb00f568] In order to emit a signal at a signal port, write as follows: #codeh(cpp){{ signal_signal1.ExecAll(x,y); }} The member function ExecAll emits a signal to every slot ports connected to the signal port. The return values are ignored. If no slot port is connected, nothing happens. ** Call Function [#o37d37cc] In order to use a function connected to an in port, write as follows: #codeh(cpp){{ TRealVector y= in_in1.GetFirst(x); }} Here, the member function GetFirst execute the function of the first out port connected to the in port with an argument x, whose return is stored in y. Recall that in default, only one out port can be connected to an in port. If no out port is connected, GetFirst causes an error. In order to avoid the error, you need to check the size of connections by: #codeh(cpp){{ in_in1.ConnectionSize() }} this returns the number of connected out ports. We suggest to wrap the GetFirst by using a macro as follows: #codeh(cpp){{ MAKE_IN_PORT(in_state, const TRealVector& (void), TThis); MAKE_IN_PORT(in_func, const TReal& (const TReal &x), TThis); #define GET_FROM_IN_PORT(x_in,x_return_type,x_arg_list,x_param_list) \ x_return_type get_##x_in x_arg_list const \ { \ if (in_##x_in.ConnectionSize()==0) \ {LERROR("in "<<ModuleUniqueCode()<<", in_" #x_in " must be connected."); lexit(df);} \ return in_##x_in.GetFirst x_param_list; \ } GET_FROM_IN_PORT(state, const TRealVector&, (void), ()) GET_FROM_IN_PORT(func, const TReal&, (const TReal &x), (x)) #undef GET_FROM_IN_PORT }} Then, we can use get_state and get_func like a normal function; e.g. #codeh(cpp){{ TRealVector x= get_state(); TReal y= get_func(1.2); }} The macro GET_FROM_IN_PORT is generic, so you can copy and paste it in your code as is. Do not forget to un-define it (i.e. #undef GET_FROM_IN_PORT).
View Text Formatting Rules