ふるお〜と!- FullAuto

AI・ロボットが普及しBI(ベーシックインカム)が早急に実現されることを願う元ニートのブログ

ふるお〜と!-FullAuto

AI・ロボットにネットワーク上から「やれぇ!」という処理方法について

AI・ロボットに対してネットワーク上から「やれぇ!」というコマンドを送信して、そのコマンドに応じて処理を選択していくという流れについて

「これやれぇ!」が値型であれば、

switch cmd:
  case これやれぇ!:
    //これやる
    break;
  case あれやれぇ!:
    //あれやる
    break;

というようにできて、定数時間O(1)で実現できる。

しかし、国際標準的なインターフェース仕様がない状態でこんなプログラムを組むと、ガラケーの組み込みプログラムみたいに闇に葬られる可能性が高い。

というわけで、人間が言語理解できるインターフェースとなる文字列型となるが、文字列はswitch文に対応していないので、

if (cmd == "これやれぇ!")
  //これやる
else if (cmd =="あれやれぇ!")
  //あれやる

というようになる。 しかし、これではO(n)となり、コマンドの数に比例して処理時間が増えてしまう。
(Webotsはこんな感じ)

そこでstd::unordered_mapを使うという方法が出てくる。

std::unordered_map<std::string, std::any> cmdMap:
cmdMap["これやれぇ!"] = func1; //これやるfunction登録
cmdMap["あれやれぇ!"] = func2; //あれやるfunction登録

auto mapIter = cmdMap.find("これやれぇ!");
std::any_cast <void (*) ()> (mapIter->second) (); //これやる

mapIter = cmdMap.find("あれやれぇ!");
std::any_cast <void (*) ()> (mapIter->second) (); //あれやる

これで定数時間O(1)で実現できる。

見つからなかったらSegmentation FaultになるのでイタレーションがEndを指していないかチェックするのが望ましい。

auto mapIter = cmdMap.find(notify.method);
if(mapIter != cmdMap.end())
          std::any_cast <void (*) ()> (mapIter->second) ();
// 戻り値がintの場合
std::any_cast <int (*) ()> (mapIter->second) ();

// 引数がint,intの場合
std::any_cast <void (*) (int, int)> (mapIter->second) (1, 2);

// 引数の参照を渡したい場合
std::any_cast <void (*) (Hoge&)> (mapIter->second) (hoge);

その他の難しくめんどくさい実装

もしかしたら、AI・ロボット上のNodeMap値(ポインタ)を教えてもらい、そのポインタに対して直接実行させるという方法もあるかもしれない。

参考

https://stackoverflow.com/questions/55520876/creating-an-unordered-map-of-stdfunctions-with-any-arguments