gggggraziegrazie

graizegrazieさんのやったこと、学んだことを記録する雑記帳です

コマンドライン中で指定したパラメータ名をノード中で取得する方法(C++)

結論から言うと、2種類の方法があります。

  1. ros::names::remap : 返り値としてremapされたパラメータ名が取得できます。
  2. resolveName : 返り値としてremapされたパラメータ名が取得できます。第二引数でremapが成功したかをboolで取得できます。
ros::names::remap

remapされた名前は返り値として返されます。また返された名前は、絶対パスで返されます。つまり、

std::string remapped_name = ros::names::remap("hoge")
std::cout << remapped_name << std::endl;

というコードがノード中に書いてあり、さらに

rosrun node node hoge:=fuga

を実行すると、

/fuga

が表示されます。これはros::names::remapがノードハンドルのメンバ関数ではないためと考えれます。

resolveName

remapされた値は、ノードハンドルのNameSpaceによって変化します。例えば
コード中に

ros::Nodehandle n;
bool resolve_result;
std::string remap = n.resolveName("hoge", resolve_result);
std::cout << remap << std::endl;

と書いてあり、

rosrun node node hoge:=fuga

を実行すると、

/fuga

が表示されます。また

ros::init(argc, argv, "node_name");
ros::Nodehandle n(~);
bool resolve_result;
std::string remap = n.resolveName("hoge", resolve_result);
std::cout << remap << std::endl;

と記載がある状態で

rosrun node node hoge:=fuga

を実行すると、

/node_name/fuga

が表示されます。こちらはノードハンドルのメンバ関数のため、ノードハンドルの持つNameSpaceの影響を受けることがわかります。

ご参考になりましたら幸いです。

ROSにおけるシャットダウン処理の書き方

ROSのノードを動かした時、Ctrl-Cでそのノードを落としたいのに、落ちてくれない場合ありますよね。また落ちたとしても、下記の様なexceptionが発生したりするなどして、キレイに落ちてくれなかったりします。

terminate called after throwing an instance of 'boost::exception_detail::clone_impl >'
what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
Aborted (core dumped)

これは[1]にもありますが、callbackやtimerが動いているのが問題です。そのため[1]に記載の様にシグナルハンドラを設定し、そのコールバック中でtimer[3]やsubscriber[2]を止め、さらにノードのshutdownを行なう必要があります(下記参照)。

signal(SIGINT, signal_handler);
void signal_hander(int signum)
{
/* 下記がtimerやsubscriber, nodeの停止用関数。実行するタイミングはプログラムに依存するので、必ずしもハンドラで実行すればよい訳ではない */
  timer.stop();        // timerの停止。この関数はtimerの中で呼んだ方がよいかもしれない。
  sub.shutdown(); // subscriberの停止
  ros::shutdown(); // ノードの停止。これを呼ぶとspinから抜ける。
}

上記終了処理に伴い、main関数中でspin関数を呼ぶ部分は下記の様に書く必要があります。spinOnceでなくspinを使ってしまうと、シグナルハンドラは呼ばれるものの、spin関数から抜けられないためにwhile文から抜けられません。終了処理を書きたい場合は、spinOnceを使うようにしましょう。そんなことはありません、ちゃんと抜けます。下記のcase1, 2のどちらでも構いません。

/* case 1 */
ros::spin();
/* case 2 */
ros::Rate rate(1);
while( false == ros::isShuttingDown() )
{
    ros::spinOnce();
    rate.sleep();
}

インピーダンス制御とコンプライアンス制御

インピーダンス制御は、目標値の計算に弾性項と粘性項の両方を加味する。一方コンプライアンス制御は、粘性項を無視して弾性項のみを使う。これにより、コンプライアンス制御は動作速度の抑制は行わないことがわかる。

roslaunchでパラメータの値を設定する方法

roslaunchにおいては、タグまたはタグのどちらかを使えば、パラメータの値を設定できる。

*下記ではの両方で記述しているが、どちらか片方だけ記述すればよいことに注意。
*下記では変数型としてstrを記述しているが、他にもint, double, bool, yamlも使える。

<launch>
    <param name="string_name" type="str" value="string_value" />
    <rosparam>
        string_name    : string_value (ex. hoge.txt) * ここでは""などで囲む必要はありません
    </rosparam>
</launch>

Canonical Scan Matcher

Canonical Scan Matcherは、連続するscanデータの移動量を推定する手法です。Visual OdometryでPnPを使って移動量を推定するのと、等価の出力といえます。まだ読み進めていないのですが、アブストラクトを読む限り、移動量が大きい場合はエラーが大きくなってしまうみたいです。つまりLoop Closureの候補を検出するには使いにくく、連続するscan間の移動量(Scanning Odometry?)を求めるのが最良の用途のようです。

Daynamo - Autodesk tool

Dynamoには「Dynamo」と「Dynamo Studio」の2種類があります。前者はAutodesk Revitの拡張ツールでOSSです。また無償でダウンロードできます(そもそものRevitが有償ですが)。後者のDynamo Studioは、スタンドアローンなツールです。こちらは有償です。ただしスタンドアローンなので、Revitが持っている機能などを使うことができます。そのためOSSではなくクローズなソフトになっています。どちらもVisual programmigを通じてデータ処理やジオメトリの生成を可能にします。

f:id:graziegrazie:20181026194620p:plain
Dynamoを使ったVisual Programmingの例[3]

またDynamoを使って、ロボットの制御用プログラムを生成することも可能です。なのでイメージとしてはGrasshopperのAutodesk版とも言えるかもしれません。KUKAのロボットについては、今年のなってKUKAが提供するKUKA|prc[7][8]のDynamo版が提供されたようです。またABBに関しては、殆ど情報がないのですが、[6]にDynamo Toroについての言及があります。ToroとはABBが提供するシミュレーション・制御用のGrasshopperプラグインのことです[9]。こちらについては情報が少ないことから、現在のサポート状況についてはわかりかねます。もしもDynamoを介してABBのロボットを制御したい場合は、AutodeskかABBにご相談されることをお勧めします。Universal robotのロボットに関しては、私は今回情報を見つけることが出来ませんでしたので、現時点ではサポート外だと思います。

またGrasshopperと同様に、Fireflyを使うことでArduino - Dynamoをつなぐことができるみたいです[6]。

RhinoVAULT - Rhinoceros plugin

ETH Zurichが開発したプラグインで、Compression-onlyな構造を創造・探求するのに使います。美しい形状を創り出すだけでなく、構造体の原理を理解するのにも使えます。興味がある方は、[1]にTutorial動画が沢山ありますので、そちらをご覧ください。