OpenRTM / OpenRTP-aist

OpenRTP-aist: RT-Middleware and OMG RTC based component and system development tools implemented by AIST
Other
1 stars 6 forks source link

スタンドアロンRTCのコードに--instance_name= オプションを追加 #109

Closed n-ando closed 5 years ago

n-ando commented 5 years ago

Feature request related to a problem

XXXComp.exeのようなスタンドアロンコンポーネントで、インスタンス名を変更したい場合、-oオプションで変更できるものの、スタンドアロンコンポーネントは特定のRTCをインスタンス化するのが明確にもかかわらず、カテゴリ名とモジュール名を指定するのは冗長。

https://github.com/OpenRTM/OpenRTM-aist/issues/475

Describe the solution you'd like

マネージャのコールバックを利用し、XXXComp.cpp (C++の場合) のコードでコールバックをセットすることで、最初のインスタンスのみ、--instance_name=<インスタンス名> というオプションで名前を強制的に上書きすることができる。

具体的には、以下の通り、リスナクラスを一つ定義、

class OverwriteInstanceName
  : public RTM::RtcLifecycleActionListener
{
public:
  OverwriteInstanceName(int argc, char** argv)
    : m_name(""), m_count(0)
  {
    for (size_t i = 0; i < argc; ++i)
      {
        std::string opt = argv[i];
        if (opt.find("--instance_name=") == std::string::npos) { continue; }

        coil::replaceString(opt, "--instance_name=", "");
        if (opt.empty()) { continue; }

        m_name = opt;
      }
  }
  virtual ~OverwriteInstanceName() {}
  virtual void preCreate(std::string& args)
  {
    if (m_count != 0 || m_name.empty()) { return; }
    args = args + "?instance_name=" + m_name;
    ++m_count;
  };
  virtual void postCreate(RTC::RTObject_impl*) {};
  virtual void preConfigure(coil::Properties&) {};
  virtual void postConfigure(coil::Properties&) {};
  virtual void preInitialize() {};
  virtual void postInitialize() {};
private:
  std::string m_name;
  int32_t m_count;
};

main関数では、以下のようにリスナをセット。

nt main (int argc, char** argv)
{
  RTC::Manager* manager;
  manager = RTC::Manager::init(argc, argv);
  manager->addRtcLifecycleActionListener(new OverwriteInstanceName(argc, argv),
                                         true);

以上で、一番最初のインスタンスのみ、--instance_name=インスタンス名 で指定された名前でインスタンス化される。

以上の変更をRTCBuilderのC++, Java, Pythonのテンプレートコードに追加する。

n-ando commented 5 years ago

なお、本変更の対象はRELENG_1_2およびmasterとする。

n-ando commented 5 years ago

Python版ではListenerでMaster::createComponentの引数を書き換えられないので、当面以下のような方法で --instance_name=オプションを実現することとする。(正統的な方法ではないが。。。)

 : 中略
def MyModuleInit(manager):
  ConsoleOutInit(manager)
  # create instance_name option for createComponent()
  args = [i for i in sys.argv if "--instance_name=" in i][0].replace("--", "?")
  # Create a component
  comp = manager.createComponent("ConsoleOut" + args)

def main():
  # remove --instance_name= option
  argv = [i for i in sys.argv if not "--instance_name=" in i]
  # Initialize manager
  mgr = OpenRTM_aist.Manager.init(argv)

 : 中略
n-ando commented 5 years ago

Java版でも、Python同様、ListenerがimmutableなString引数をとるため、変更を呼び出し元に返せない。したがって、mainクラスのstatic変数にinstance_nameを保存しておき、Init関数のcreateCompponent()の引数として渡すことでとりあえず同様のことを実現することとする。

import java.util.ArrayList; // 追加
import java.util.Arrays; // 追加
import java.util.List; // 追加

import jp.go.aist.rtm.RTC.Manager;
import jp.go.aist.rtm.RTC.ModuleInitProc;
import jp.go.aist.rtm.RTC.RTObject_impl;
import jp.go.aist.rtm.RTC.util.Properties;

 : 中略

public class StringInComp implements ModuleInitProc {
    static String m_instanceName = new String(""); // 追加

    public void myModuleInit(Manager mgr) {
      Properties prop = new Properties(StringIn.component_conf);
      mgr.registerFactory(prop, new StringIn(), new StringIn());

        // prepare arg for createComponent() // 追加
        String arg = new String("");
        if (!m_instanceName.isEmpty()) {
            arg += "?instance_name=" + m_instanceName;
        }
      // Create a component
      RTObject_impl comp = mgr.createComponent("StringIn" + arg); // 変更
      if( comp==null ) {
          System.err.println("Component create failed.");
          System.exit(0);
      }

 : 中略

    public static void main(String[] args) {
        // store instance_name to static and removed args created // 追加
        List<String> mgrargs = new ArrayList();
        for (int i = 0; i < args.length; ++i) {
            if (args[i].indexOf("--instance_name=") == -1) {
                mgrargs.add(args[i]);
            } else {
                m_instanceName = args[i].replace("--instance_name=", "");
            }
        }
        // Initialize manager
        final Manager manager = Manager.init(mgrargs.toArray(new String[mgrargs.size()]));