-
Notifications
You must be signed in to change notification settings - Fork 1
robot_state_publisher_principle
Masaru Morita edited this page Oct 31, 2015
·
13 revisions
-
gazebo
起動時にrviz
観察した場合、ホイールのフレームが回転しました。 - 一方、実機のbagファイル再生時 は、
rviz
で観察してもホイールフレームは見えているのに、(joint_state_publisher
,robot_state_publisher
の起動状態でも) 回転はしていませんでした。 - なぜだ!? と思い、調べてみました。推測含みますが、分かったことを記載しておきます。
- まぁ、実動作には支障はないのですが、なんとなく笑。
robot_state_publisher
ノードは、稼働ジョイントの現在角度を表す/joint_states
トピックをsubscribeし、その状態を反映させたTF
フレームをpublishする役割を持ちます。
-
rqt_graph
を見てみます。ほうほう、確かにrobot_state_publisher
はjoint_states
トピックをsubscribeしています。 -
その先も見てみます。
robot_state_publisher
が/tf
をpublishし、rviz
がsubscribeしている様子が分かります。 -
joint_state_publisher
は、/robot_description
パラメータを機械的に解読し、稼働可能なjoint
一覧を表示します。ユーザはこれをグリグリいじって稼働可能なジョイント角度を自由に設定できます。 -
ユーザが入力した値に従って
/joint_states
トピックをpublishします。内部的には、下記のように/joint_states
がpublishされます。 -
コードのイメージ。あくまでイメージ。
#include <ros/ros.h>
#include <sensor_msgs/JointState.h>
int main() {
~省略~
ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
sensor_msgs::JointState joint_state;
~省略~
ユーザ入力時のコールバック {
//update joint_state
joint_state.header.stamp = ros::Time::now();
//稼働ジョイント数分領域確保
joint_state.name.resize(ジョイント数);
joint_state.position.resize(ジョイント数);
//稼働ジョイント現在角度設定。ユーザ入力に合わせてフレームIDと回転角度[rad]入力。
joint_state.name[0] ="left_front_wheel";
joint_state.position[0] = hoge0; // left_front_wheelフレームの回転角度
//
joint_state.name[1] ="right_front_wheel";
joint_state.position[1] = hoge1; // right_front_wheelフレームの回転角度
//
joint_state.name[2] ="left_rear_wheel";
joint_state.position[2] = hoge2; // left_rear_wheelフレームの回転角度
//
joint_state.name[3] ="right_rear_wheel";
joint_state.position[3] = hoge3; // right_rear_wheelフレームの回転角度
// 以下、ジョイント数分続く。固定フレームの場合、positonは0となる。
joint_pub.publish(joint_state);
}
}
- あとは、
robot_state_publisher
が良きに計らってTF
フレームを発行してくれます。
-
rqt_graph
を見てみます。 - その先も見てみます。先ほどと同様、
robot_state_publisher
が/tf
をpublishし、rviz
がsubscribeしている様子が分かります。- 大事なことは、
gazebo
が直接/tf
をpublishしていないという点です。 - これは、ロボットのジョイントに関する情報が
/joint_states
トピックに集約されていることを示しています。
- 大事なことは、
-
gazebo
は/robot_description
パラメータを機械的に解読しジョイントを割り出します。 - その中で、ユーザが明示的に指定した稼働ジョイントについて、
gazebo
内で回転角度等全部計算した上で、/joint_states
トピックをpublishしてくれます。 - なお、
joint_state_publisher
の起動は不要です。 - 内部的には、下記のように
/joint_states
がpublishされているはずです。 - コードのイメージ。あくまでイメージ。
#include <ros/ros.h>
#include <sensor_msgs/JointState.h>
int main() {
~省略~
ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
sensor_msgs::JointState joint_state;
~省略~
while (ros::ok()) {
//update joint_state
joint_state.header.stamp = ros::Time::now();
//稼働ジョイント数分領域確保
joint_state.name.resize(ジョイント数);
joint_state.position.resize(ジョイント数);
//稼働ジョイント現在角度設定。フレームIDと回転角度[rad]入力。
joint_state.name[0] ="left_front_wheel";
joint_state.position[0] = hoge0; // left_front_wheelフレームの回転角度
//
joint_state.name[1] ="right_front_wheel";
joint_state.position[1] = hoge1; // right_front_wheelフレームの回転角度
//
joint_state.name[2] ="left_rear_wheel";
joint_state.position[2] = hoge2; // left_rear_wheelフレームの回転角度
//
joint_state.name[3] ="right_rear_wheel";
joint_state.position[3] = hoge3; // right_rear_wheelフレームの回転角度
// 以下、ジョイント数分続く。固定フレームの場合、positonは0となる。
// gazebo内部の回転角度やオドメトリ計算。ジョイントの角度(hoge0 ~ hoge3)も更新。
~省略~
joint_pub.publish(joint_state);
}
}
- 補足
-
gazebo
の場合にジョイント周りの制御を最上位で司るのは、gazebo_ros_control
というgazebo
用プラグインです。 - 更に、
gazebo_ros_control
の配下にcontroller_spawner
というノードが必要です。目的に合わせて適切なコントローラをspawnします。 - 例えば、
joint_states
周りの面倒を見てくれるコントローラは、joint_state_controller
というものらしいです。こいつをspawnしないと、下記のように回転するジョイントのTFフレームだけが発行されないという現象が起こりました。 -
joint_state_controller
をspawnすると解決します。
-
- ここまで来ればもう分かります。
gazebo
内部でやっているオドメトリと/joint_states
のpublishをドライバにやらせればよいと考えます。 - パラメータから機械的に解読するのではなくて、自分で明示的に回転ジョイントを指定する必要があります。
-
third_robot_driver
パッケージのthird_robot_driver_node
で/odom
トピックをpublishしている部分で、/joint_states
トピックもpublishすれば、おそらく実機で動かした時でもrviz
上のホイールのTFフレームが回転するはずです。 - コードのイメージ。あくまでイメージ。
#include <ros/ros.h>
#include <sensor_msgs/JointState.h>
int main() {
~省略~
ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
sensor_msgs::JointState joint_state;
~省略~
while (ros::ok()) {
//update joint_state
joint_state.header.stamp = ros::Time::now();
//稼働ジョイント数分領域確保
joint_state.name.resize(ジョイント数);
joint_state.position.resize(ジョイント数);
//稼働ジョイント現在角度設定。フレームIDと回転角度[rad]入力。ここを開発者が明示的に指定する。
joint_state.name[0] ="left_front_wheel";
joint_state.position[0] = hoge0; // left_front_wheelフレームの回転角度
//
joint_state.name[1] ="right_front_wheel";
joint_state.position[1] = hoge1; // right_front_wheelフレームの回転角度
//
joint_state.name[2] ="left_rear_wheel";
joint_state.position[2] = hoge2; // left_rear_wheelフレームの回転角度
//
joint_state.name[3] ="right_rear_wheel";
joint_state.position[3] = hoge3; // right_rear_wheelフレームの回転角度
// 以下、ジョイント数分続く。固定フレームの場合、positonは0となる
// エンコーダの値を取るなりなんなり。
~ third_robot_interface でやっている辺り。 ~
// 回転角度やオドメトリ計算。ジョイントの角度(hoge0 ~ hoge3)も更新。
~ third_robot_interface でできそうな辺り。 ~
joint_pub.publish(joint_state);
}
}