1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

メンバ変数でconst宣言されたROSメッセージを初期化する方法(C++)

Last updated at Posted at 2020-01-10

概要

クラスのメンバ変数はコンストラクタで初期化することができますが,ROSのメッセージ(例えばgeometry_msgs::Twist)などは下記のようにすべての変数にアクセスして初期化しなければなりません.

geometry_msgs::Twist twist;
twist.linear.x = 0.0;
twist.linear.y = 0.0;
twist.linear.z = 0.0;
twist.angular.x = 0.0;
twist.angular.y = 0.0;
twist.angular.z = 0.0;

通常使用時にはそこまで気にならなかったのですが,この前geometry_msgs::Twistをconstでクラスメンバ変数として作成しようとしたときに初期化方法がわからなかったので,調べたついでにここにメモします.

環境

  • Ubuntu 16.04
  • ROS: Kinetic
  • C++: C++11以降
    • コンパイル時にはCMakeLists.txtにてC++11がコンパイルできるようにしておく

const宣言されたROSメッセージの初期化方法

残念ながらきれいな初期化方法が見つからなかったので,無理矢理コンストラクタで初期化する方法2つを紹介します.

0. メッセージ内変数をすべて0で初期化したい場合

公式曰く,C++では宣言されたROSメッセージにはデフォルトで0が入るらしいので,小賢しい方法は必要ありません.

1. メンバ変数初期化用の関数を作成

パッと思いついた方法.初期化したいメンバ変数型を返り値とする関数を予め用意しておきます.(@yuki12さんより指摘いただいたので初期化用関数をクラス外に作成)
パッと思いついただけあって,初期化したいメンバ変数の分,初期化用関数が増えていってしまうのが難点.

// geometry_msgs::Twist初期化用関数
geometry_msgs::Twist geoTwistInit (const std::vector<double>& c_twist)
{
    geometry_msgs::Twist twist;
    twist.linear.x = c_twist[0]; twist.linear.y = c_twist[1]; twist.linear.z = c_twist[2];
    twist.angular.x = c_twist[3]; twist.angular.y = c_twist[4]; twist.angular.z = c_twist[5];
    return twist;
}

class Hoge
{
private:
    const geometry_msgs::Twist cmd_vel_;
public:
    Hoge(void):
    cmd_vel_(geoTwistInit(std::vector(1.0, 1.0, 1.0, 2.0, 2.0, 2.0)))
    {
         std::printf("cmd_vel: %f, %f, %f, %f, %f, %f", cmd_vel_.linear.x, cmd_vel_.linear.y, cmd_vel_.linear.z, cmd_vel_.angular.x, cmd_vel_.angular.y, cmd_vel_.angular.x);
    }
};

int main (void)
{
    Hoge hoge;
    return 0;
}

出力

cmd_vel: 1.0, 1.0, 1.0, 2.0, 2.0, 2.0

2.ラムダ式を使う方法

他に方法がないか調べたところ,ROSに限らずコンストラクタが設定されていない型の初期化方法としてラムダ式を使う方法を発見(参考).

class Hoge
{
private:
    const geometry_msgs::Twist cmd_vel_;
public:
    Hoge(void):
    cmd_vel_( []()->geometry_msgs::Twist{geometry_msgs::Twist twist;
                                         twist.linear.x=1.0; twist.linear.y=1.0; twist.linear.z=1.0;
                                         twist.angular.x=2.0; twist.angular.y=2.0; twist.angular.z=2.0;
                                         return twist;}() )
    {
         std::printf("cmd_vel: %f, %f, %f, %f, %f, %f", cmd_vel_.linear.x, cmd_vel_.linear.y, cmd_vel_.linear.z, cmd_vel_.angular.x, cmd_vel_.angular.y, cmd_vel_.angular.x);
    }
};

int main (void)
{
    Hoge hoge;
    return 0;
}

出力

cmd_vel: 1.0, 1.0, 1.0, 2.0, 2.0, 2.0

キモはラムダ式の最後に()をつけることらしい.

まとめ

紹介した2つの方法はどちらもあまりきれいではありませんが,力業で解決できることがわかってよかったです.

参考

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?