[openrtm-commit:00657] r2302 - in trunk/OpenRTM-aist: etc src/lib/rtm

openrtm @ openrtm.org openrtm @ openrtm.org
2012年 2月 4日 (土) 03:57:45 JST


Author: n-ando
Date: 2012-02-04 03:57:44 +0900 (Sat, 04 Feb 2012)
New Revision: 2302

Modified:
   trunk/OpenRTM-aist/etc/component.conf
   trunk/OpenRTM-aist/etc/rtc.conf.sample
   trunk/OpenRTM-aist/src/lib/rtm/RTObject.cpp
   trunk/OpenRTM-aist/src/lib/rtm/RTObject.h
Log:
[incompat,header/imple,func] The method to create EC has been changed. Now zero or more EC can be attached to RTC. Configuration options for EC have been changed changed. refs #2349

Modified: trunk/OpenRTM-aist/etc/component.conf
===================================================================
--- trunk/OpenRTM-aist/etc/component.conf	2012-02-03 17:45:45 UTC (rev 2301)
+++ trunk/OpenRTM-aist/etc/component.conf	2012-02-03 18:57:44 UTC (rev 2302)
@@ -44,6 +44,99 @@
 # exec_cxt.event_driven.type: [specify event driven type EC]
 #
 
+#
+# State transition mode settings YES/NO
+#
+# Default: YES (efault setting is recommended.)
+#
+# Activating, deactivating and resetting of RTC performs state
+# transition. Some execution contexts might execute main logic in
+# different thread. If these flags are set to YES, activation,
+# deactivation and resetting will be performed synchronously. In other
+# words, if these flags are YES,
+# activation/deactivation/resetting-operations must be returned after
+# state transition completed.
+#
+# "sync_transition" will set synchronous transition flags to all other
+# synchronous transition flags sync_activation/deactivation/reset.
+#
+# exec_cxt.sync_transition: YES
+# exec_cxt.sync_activation: YES
+# exec_cxt.sync_deactivation: YES
+# exec_cxt.sync_reset: YES
+
+#
+# Timeout of synchronous state transition [s]
+#
+# Default: 0.5 [s]
+#
+# When synchronous transition flags are set to YES, the following
+# timeout settings are valid. If "transition_timeout" is set, the
+# value will be set to all other timeout of activation/deactivation
+# and resetting
+#
+# exec_cxt.transition_timeout: 0.5
+# exec_cxt.activation_timeout: 0.5
+# exec_cxt.deactivation_timeout: 0.5
+# exec_cxt.reset_timeout: 0.5
+
+#
+# Specifying Execution Contexts
+#
+# Default: No default
+#
+# execution_contexts: None or <EC0>,<EC1>,...
+# <EC?>: ECtype(ECname)
+#
+# RTC can be attached with zero or more Execution
+# Contexts. "execution_contexts" option specifies RTC-specific
+# attached ECs and its name. If the option is not specified, the
+# internal global options or rtc.conf options related to EC will be
+# used. If None is specified, no EC will be created.
+#
+# Availabilities in OpenRTM-aist
+#
+# - ExtTrigExecutionContext: External triggered EC. It is embedded in
+#                            OpenRTM library.
+# - OpenHRPExecutionContext: External triggred paralell execution
+#                            EC. It is embedded in OpenRTM
+#                            library. This is usually used with
+#                            OpenHRP3.
+# - RTPreemptEC:             Real-time execution context for Linux
+#                            RT-preemptive pathed kernel.
+# - ArtExecutionContext:     Real-time execution context for ARTLinux
+#                            (http://sourceforge.net/projects/art-linux/)
+#
+# execution_contexts: PeriodicExecutionContext(pec1000Hz), \
+#                     PeriodicExecutionContext(pec500Hz)
+
+#
+# EC specific configurations
+#
+# Default: No default
+#
+# Each EC can have its own configuration. Individual configuration can
+# be specified by using EC type name or EC instance name. Attached ECs
+# would be specified in execution_context option like <EC type
+# name>(<EC instance name>), ...  EC specific option can be specified
+# as follows.
+#
+# ec.<EC type name>.<option>
+# ec.<EC instance name>.<option>
+#
+# Example:
+# ec.PeriodicExecutionContext.sync_transition: NO
+# ec.pec1000Hz.rate: 1000
+# ec.pec1000Hz.synch_transition: YES
+# ec.pec1000Hz.transition_timeout: 0.5
+# ec.pec500Hz.rate: 500
+# ec.pec500Hz.synch_activation: YES
+# ec.pec500Hz.synch_deactivation: NO
+# ec.pec500Hz.synch_reset: YES
+# ec.pec500Hz.activation_timeout: 0.5
+# ec.pec500Hz.reset_timeout: 0.5
+
+
 #============================================================
 # port configurations
 #

Modified: trunk/OpenRTM-aist/etc/rtc.conf.sample
===================================================================
--- trunk/OpenRTM-aist/etc/rtc.conf.sample	2012-02-03 17:45:45 UTC (rev 2301)
+++ trunk/OpenRTM-aist/etc/rtc.conf.sample	2012-02-03 18:57:44 UTC (rev 2302)
@@ -383,12 +383,51 @@
 #                            (http://sourceforge.net/projects/art-linux/)
 #
 exec_cxt.periodic.type: PeriodicExecutionContext
+# exec_cxt.event_driven_type: to be implemented
 
 #
 # The execution cycle of ExecutionContext
 #
 exec_cxt.periodic.rate: 1000
 
+#
+# State transition mode settings YES/NO
+#
+# Default: YES (efault setting is recommended.)
+#
+# Activating, deactivating and resetting of RTC makes state
+# transition.  Some execution contexts execute main logic in different
+# thread.  If these flags set to YES, activation, deactivation and
+# resetting will be performed synchronously.  In other words, if these
+# flags are YES, activation/deactivation/resetting-operations must be
+# returned after state transition completed.
+#
+# "synchronous_transition" will set synchronous transition flags to
+# all other synchronous transition flags
+# (synchronous_activation/deactivation/resetting.
+#
+exec_cxt.sync_transition: YES
+exec_cxt.sync_activation: YES
+exec_cxt.sync_deactivation: YES
+exec_cxt.sync_reset: YES
+
+#
+# Timeout of synchronous state transition [s]
+#
+# Default: 1.0 [s]
+#
+# When synchronous transition flags are set to YES, the following
+# timeout settings are valid. If "transition_timeout" is set, the
+# value will be set to all other timeout of activation/deactivation
+# and resetting
+#
+exec_cxt.transition_timeout: 0.5
+exec_cxt.activation_timeout: 0.5
+exec_cxt.deactivation_timeout: 0.5
+exec_cxt.reset_timeout: 0.5
+
+
+
 #============================================================
 # SDO service settings
 #============================================================

Modified: trunk/OpenRTM-aist/src/lib/rtm/RTObject.cpp
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/RTObject.cpp	2012-02-03 17:45:45 UTC (rev 2301)
+++ trunk/OpenRTM-aist/src/lib/rtm/RTObject.cpp	2012-02-03 18:57:44 UTC (rev 2302)
@@ -311,61 +311,40 @@
     throw (CORBA::SystemException)
   {
     RTC_TRACE(("initialize()"));
-    std::string ec_type;
-    std::string ec_args;
 
-    ec_type = m_properties["exec_cxt.periodic.type"];
-    ec_args += m_properties["exec_cxt.periodic.type"];
-    ec_args += "?";
-    ec_args += "rate=" + m_properties["exec_cxt.periodic.rate"];
-
-    RTC::ExecutionContextBase* ec;
-    ec = RTC::ExecutionContextFactory::instance().createObject(ec_type.c_str());
-    if (ec == NULL)
+    // EC creation
+    std::vector<coil::Properties> ec_args;
+    if (getContextOptions(ec_args) != RTC::RTC_OK)
       {
-        RTC_ERROR(("EC (%s) creation failed.", ec_type.c_str()));
-        coil::vstring ecs;
-        ecs = RTC::ExecutionContextFactory::instance().getIdentifiers();
-        RTC_DEBUG(("Available EC list: %s",
-                   coil::flatten(ecs).c_str()));
-        return RTC::RTC_ERROR;
+        RTC_ERROR(("Valid EC options are not available. Aborting"));
+        return RTC::BAD_PARAMETER;
       }
-    RTC_DEBUG(("EC (%s) created.", ec_type.c_str()));
-
-    m_eclist.push_back(ec);
-    ExecutionContextService_var ecv;
-    ecv = RTC::ExecutionContextService::_duplicate(ec->getObjRef());
-    if (CORBA::is_nil(ecv))
+    if (createContexts(ec_args) != RTC::RTC_OK)
       {
-        RTC_ERROR(("Getting object reference of ec failed."));
-        return RTC::RTC_ERROR;
+        RTC_ERROR(("EC creation failed. Maybe out of resources. Aborting."));
+        return RTC::OUT_OF_RESOURCES;
       }
-    double ec_rate;
-    coil::stringTo(ec_rate, m_properties["exec_cxt.periodic.rate"].c_str());
-    ecv->set_rate(ec_rate);
-    RTC_DEBUG(("Execution context rate is set to %f.", ec_rate));
 
-    ec->bindComponent(this);
     // -- entering alive state --
-    // at least one EC must be attached
-    if (m_ecMine.length() == 0)
-      {
-        RTC_ERROR(("No EC of this RTC."));
-        return RTC::PRECONDITION_NOT_MET;
-      }
-
+    RTC_INFO(("%d execution context%s created.",
+              m_ecMine.length(),
+              (m_ecMine.length() == 1) ? " was" : "s were"));
     ReturnCode_t ret;
     ret = on_initialize();
     m_created = false;
-    if (ret != RTC::RTC_OK) return ret;
-
+    if (ret != RTC::RTC_OK)
+      {
+        RTC_ERROR(("on_initialize() failed."));
+        return ret;
+      }
+    RTC_DEBUG(("on_initialize() was properly done."));
     for (::CORBA::ULong i(0), len(m_ecMine.length()); i < len; ++i)
       {
         RTC_DEBUG(("EC[%d] starting.", i));
         m_ecMine[i]->start();
       }
-
     // ret must be RTC_OK
+    assert(ret == RTC::RTC_OK);
     return ret;
   }
  
@@ -907,11 +886,11 @@
     try
       {
         preOnShutdown(ec_id);
-	ret = onShutdown(ec_id);
+        ret = onShutdown(ec_id);
       }
     catch (...)
       {
-	ret = RTC::RTC_ERROR;
+        ret = RTC::RTC_ERROR;
       }
     postOnShutdown(ec_id, ret);
     return ret;
@@ -932,13 +911,13 @@
     try
       {
         preOnActivated(ec_id);
-	m_configsets.update();
-	ret = onActivated(ec_id);
+        m_configsets.update();
+        ret = onActivated(ec_id);
         m_portAdmin.activatePorts();
       }
     catch (...)
       {
-	ret = RTC::RTC_ERROR;
+        ret = RTC::RTC_ERROR;
       }
     postOnActivated(ec_id, ret);
     return ret;
@@ -960,7 +939,7 @@
       {
         preOnDeactivated(ec_id);
         m_portAdmin.deactivatePorts();
-	ret = onDeactivated(ec_id);
+        ret = onDeactivated(ec_id);
       }
     catch (...)
       {
@@ -2440,7 +2419,7 @@
   {
     m_configsets.addConfigurationSetListener(type, listener, autoclean);
   }
-  
+
   /*!
    * @if jp
    * @brief ConfigurationSetListener を削除する
@@ -2454,7 +2433,7 @@
   {
     m_configsets.removeConfigurationSetListener(type, listener);
   }
-  
+
   /*!
    * @if jp
    * @brief ConfigurationSetNameListener を追加する
@@ -2469,7 +2448,7 @@
   {
     m_configsets.addConfigurationSetNameListener(type, listener, autoclean);
   }
-  
+
   /*!
    * @if jp
    * @brief ConfigurationSetNameListener を削除する
@@ -2497,14 +2476,14 @@
     RTC_TRACE(("shutdown()"));
     try
       {
-	finalizePorts();
+        finalizePorts();
         finalizeContexts();
         PortableServer::ObjectId_var oid1;
         oid1 = m_pPOA->servant_to_id(m_pSdoConfigImpl);
         PortableServer::ObjectId_var oid2;
         oid2 = m_pPOA->servant_to_id(this);
-	m_pPOA->deactivate_object(oid1);
-	m_pPOA->deactivate_object(oid2);
+        m_pPOA->deactivate_object(oid1);
+        m_pPOA->deactivate_object(oid2);
       }
     catch (PortableServer::POA::ServantNotActive &e)
       {
@@ -2519,7 +2498,7 @@
         // never throws exception
         RTC_ERROR(("Unknown exception caught."));
       }
-    
+
     if (m_pManager != NULL)
       {
         RTC_DEBUG(("Cleanup on Manager"));
@@ -2527,6 +2506,231 @@
       }
   }
 
+  ReturnCode_t RTObject_impl::
+  getInheritedECOptions(coil::Properties& default_opts)
+  {
+    const char* inherited_opts[] =
+      {
+        "sync_transition",
+        "sync_activation",
+        "sync_deactivation",
+        "sync_reset",
+        "transition_timeout",
+        "activation_timeout",
+        "deactivation_timeout",
+        "reset_timeout",
+        ""
+      };
+    coil::Properties* p = m_properties.findNode("exec_cxt");
+    if (p == NULL)
+      {
+        RTC_WARN(("No exec_cxt option found."));
+        return RTC::RTC_ERROR;
+      }
+    RTC_DEBUG(("Copying inherited EC options."));
+    for (size_t i(0); inherited_opts[i][0] != '\0'; ++i)
+      {
+        if ((*p).findNode(inherited_opts[i]) != NULL)
+          {
+            RTC_PARANOID(("Option %s exists.", inherited_opts[i]));
+            default_opts[inherited_opts[i]] = (*p)[inherited_opts[i]];
+          }
+      }
+    return RTC::RTC_OK;
+  }
 
+  /*!
+   * @brief getting individual EC options from RTC's configuration file
+   */
+  ReturnCode_t RTObject_impl::
+  getPrivateContextOptions(std::vector<coil::Properties>& ec_args)
+  {
+    RTC_TRACE(("getPrivateContextOptions()"));
+    // Component specific multiple EC option available
+    if (m_properties.findNode("execution_contexts") == NULL)
+      {
+        RTC_DEBUG(("No component specific EC specified."));
+        return RTC::RTC_ERROR;
+      }
+    std::string& args(m_properties["execution_contexts"]);
+    coil::vstring ecs_tmp = coil::split(args, ",", true);
+    if (ecs_tmp.empty()) { return RTC::RTC_ERROR; }
+    RTC_DEBUG(("Component specific e EC option available,"));
+    RTC_DEBUG(("%s", args.c_str()));
 
+    coil::Properties default_opts;
+    getInheritedECOptions(default_opts);
+    for (size_t i(0); i < ecs_tmp.size(); ++i)
+      {
+        if (coil::normalize(ecs_tmp[i]) == "none")
+          {
+            RTC_INFO(("EC none. EC will not be bound to the RTC."));
+            ec_args.clear();
+            return RTC::RTC_OK;
+          }
+        coil::vstring type_and_name = coil::split(ecs_tmp[i], "(", true);
+        if (type_and_name.size() > 2)
+          {
+            RTC_DEBUG(("Invalid EC type specified: %s", ecs_tmp[i].c_str()));
+            continue;
+          }
+        coil::Properties p = default_opts;
+        // create EC's properties
+        p["type"] = type_and_name[0];
+        RTC_DEBUG(("p_type: %s", p["type"].c_str()));
+        coil::Properties* p_type = m_properties.findNode("ec." + p["type"]);
+        if (p_type != NULL)
+          {
+            RTC_DEBUG(("p_type props:"));
+            RTC_DEBUG_STR((*p_type));
+            p << *p_type;
+          }
+        else { RTC_DEBUG(("p_type none")); }
+
+        // EC name specified
+        RTC_DEBUG(("size: %d, name: %s", type_and_name.size(),
+                   type_and_name[1].c_str()))
+        if (type_and_name.size() == 2 &&
+            type_and_name[1].at(type_and_name[1].size() - 1) == ')')
+          {
+            type_and_name[1].erase(type_and_name[1].size() - 1);
+            p["name"] = type_and_name[1];
+            coil::Properties* p_name = m_properties.findNode("ec." + p["name"]);
+            if (p_name != NULL)
+              {
+                RTC_DEBUG(("p_name props:"));
+                RTC_DEBUG_STR((*p_name));
+                p << *p_name;
+              }
+            else { RTC_DEBUG(("p_name none")); }
+          }
+        ec_args.push_back(p);
+        RTC_DEBUG(("New EC properties stored:"));
+        RTC_DEBUG_STR((p));
+      }
+    return RTC::RTC_OK;
+  }
+
+  /*!
+   * @brief getting global EC options from rtc.conf
+   */
+  ReturnCode_t RTObject_impl::
+  getGlobalContextOptions(coil::Properties& global_ec_props)
+  {
+    // exec_cxt option is obsolete
+    RTC_TRACE(("getGlobalContextOptions()"));
+
+    coil::Properties* prop = m_properties.findNode("exec_cxt.periodic");
+    if (prop == NULL)
+      {
+        RTC_WARN(("No global EC options found."));
+        return RTC::RTC_ERROR;
+      }
+    RTC_DEBUG(("Global EC options are specified."));
+    RTC_DEBUG_STR((*prop));
+    getInheritedECOptions(global_ec_props);
+    global_ec_props << *prop;
+    return RTC::RTC_OK;
+  }
+
+  /*!
+   * @brief getting EC options
+   */
+  ReturnCode_t RTObject_impl::
+  getContextOptions(std::vector<coil::Properties>& ec_args)
+  {
+    RTC_DEBUG(("getContextOptions()"));
+    coil::Properties global_props;
+    ReturnCode_t ret_global  = getGlobalContextOptions(global_props);
+    ReturnCode_t ret_private = getPrivateContextOptions(ec_args);
+
+    // private(X), global(X) -> error
+    // private(O), global(O) -> private
+    // private(X), global(O) -> global
+    // private(O), global(X) -> private
+    if (ret_global != RTC::RTC_OK && ret_private != RTC::RTC_OK)
+      {
+        return RTC::RTC_ERROR;
+      }
+    if (ret_global == RTC::RTC_OK && ret_private != RTC::RTC_OK)
+      {
+        ec_args.push_back(global_props);
+      }
+    return RTC::RTC_OK;
+  }
+  
+  /*!
+   * @brief finding existing EC from the factory
+   */
+  ReturnCode_t RTObject_impl::
+  findExistingEC(coil::Properties& ec_arg,
+                 RTC::ExecutionContextBase*& ec)
+  {
+    std::vector<RTC::ExecutionContextBase*> eclist;
+    eclist = RTC::ExecutionContextFactory::instance().createdObjects();
+    for (size_t i(0); i < eclist.size(); ++i)
+      {
+        if (eclist[i]->getProperties()["type"] == ec_arg["type"] &&
+            eclist[i]->getProperties()["name"] == ec_arg["name"])
+          {
+            ec = eclist[i];
+            return RTC::RTC_OK;
+          }
+      }
+    return RTC::RTC_ERROR;
+  }
+
+  /*!
+   * @brief creating, initializing and binding context
+   */
+  ReturnCode_t RTObject_impl::
+  createContexts(std::vector<coil::Properties>& ec_args)
+  {
+    ReturnCode_t ret(RTC::RTC_OK);
+    coil::vstring avail_ec
+      = RTC::ExecutionContextFactory::instance().getIdentifiers();
+
+    for (size_t i(0); i < ec_args.size(); ++i)
+      {
+        std::string& ec_type(ec_args[i]["type"]);
+        std::string& ec_name(ec_args[i]["name"]);
+        RTC::ExecutionContextBase* ec;
+        if (!ec_name.empty() &&
+            findExistingEC(ec_args[i], ec) == RTC::RTC_OK)
+          { // if EC's name exists, find existing EC in the factory.
+            RTC_DEBUG(("EC: type=%s, name=%s already exists.",
+                       ec_type.c_str(), ec_name.c_str()));
+          }
+        else
+          { // If EC's name is empty or no existing EC, create new EC.
+            if (std::find(avail_ec.begin(), avail_ec.end(), ec_type)
+                == avail_ec.end())
+              {
+                RTC_WARN(("EC %s is not available.", ec_type.c_str()));
+                RTC_DEBUG(("Available ECs: %s",
+                           coil::flatten(avail_ec).c_str()));
+                continue;
+              }
+            ec = RTC::ExecutionContextFactory::
+              instance().createObject(ec_type.c_str());
+          }
+
+        if (ec == NULL)
+          { // EC factory available but creation failed. Resource full?
+            RTC_ERROR(("EC (%s) creation failed.", ec_type.c_str()));
+            RTC_DEBUG(("Available EC list: %s",
+                       coil::flatten(avail_ec).c_str()));
+            ret = RTC::RTC_ERROR;
+            continue;
+          }
+        RTC_DEBUG(("EC (%s) created.", ec_type.c_str()));
+
+        ec->init(ec_args[i]);
+        m_eclist.push_back(ec);
+        ec->bindComponent(this);
+      }
+    return ret;
+  }
+
+
 }

Modified: trunk/OpenRTM-aist/src/lib/rtm/RTObject.h
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/RTObject.h	2012-02-03 17:45:45 UTC (rev 2301)
+++ trunk/OpenRTM-aist/src/lib/rtm/RTObject.h	2012-02-03 18:57:44 UTC (rev 2302)
@@ -4542,7 +4542,38 @@
     {
       m_actionListeners.ecaction_[EC_DETACHED].notify(ec_id);
     }
+
+    ReturnCode_t getInheritedECOptions(coil::Properties& default_opts);
+
+    /*!
+     * @brief getting individual EC options from RTC's configuration file
+     */
+    ReturnCode_t
+    getPrivateContextOptions(std::vector<coil::Properties>& ec_args);
+
+    /*!
+     * @brief getting global EC options from rtc.conf
+     */
+    ReturnCode_t
+    getGlobalContextOptions(coil::Properties& global_ec_props);
+
+    /*!
+     * @brief getting EC options
+     */
+    ReturnCode_t
+    getContextOptions(std::vector<coil::Properties>& ec_args);
+
+    /*!
+     * @brief fiding existing EC from the factory
+     */
+    ReturnCode_t findExistingEC(coil::Properties& ec_arg,
+                                RTC::ExecutionContextBase*& ec);
+    /*!
+     * @brief creating, initializing and binding context
+     */
+    ReturnCode_t createContexts(std::vector<coil::Properties>& ec_args);
     
+    
   protected:
     /*!
      * @if jp



openrtm-commit メーリングリストの案内