今月のやること.ROS Mapping & Localization

 早くも3月第三週目に突入してしまったのですが,今月のやることをリストアップしておきます.先月の大きな目標として,Odometryフレーム内でロボットの制御を動かすという目標を作ったのですが,teb_local_plannerを使うことである程度目処はたったかなと思っています.今日これから外で実験してきます.

 で,今月というか直近2ヶ月・3ヶ月の目標として,とりあえず既存のものを組み合わせて動くレベルのものを作ろうと思います.自分のテーマは画像処理だけでつくばチャレンジ完走で,今もそこは変わらないのですが,一から暗中模索でやるとどうしても全体のフローが見えづらく一連のタスクを洗い出せないので...ということで,まずはショッピングです(笑)公開されているライブラリにハマるように,センサーを買いあさります.

1.買い物

1.レーザスキャナ
 画像処理だけで動かすことを最終目的としつつ,レファレンス取得用・一発目の構成作成用に購入します.ちょうど安価なものが発売されようとしてるみたいなので,見積もりをとってみます.
Scanse | Affordable Scanning LiDAR for Everyone

RPLIDAR - Slamtec - Leading Service Robot Localization and Navigation Solution Provider


2.ステレオカメラ
 2つカメラを購入して,自作でステレオカメラを作ったのですが,ハード同期できないカメラだったので撮影する際にロボットを停止しなければならず,,,これではちょっと成り立たないので,買います.前回と同じように,2つカメラを購入して同期の仕組みも含めて作るべきか悩みましたが,結局値段が高くなってしまうのと自分でやると限界があるので出来合いのものを購入します.

ZED Stereo Camera

3.処理ボード
 これは,ちょっと興味半分なところもあるのですが(笑),予算と時間が許せば買いたいなと.

NVIDIA Online Store - Checkout

2.今月のやること

1. Week of 2017/3/5
 Odometryフレーム内でのロボット制御の実現.

2. Week of 2017/3/12
 teb_local_plannerのパラメータ調整
 ショッピングの見積もり取り,発注.
 gmappingをつかってmapを作れるようにする.


3. Week of 2017/3/19
 ??

4. Week of 2017/3/26
 ??

ROS Navigation Stack ~ Teb Local Planner ~

座標指示でロボットを制御することを目標に,ROSのNavigation Stackを用いて軌道生成・制御を使用としていたのが前回のエントリだったのですが,実際にロボットを動かしてみて驚愕の事実が発覚...

車タイプのロボットの制御には対応していない!

車タイプのロボットだと,当然のことながら前に進みながらじゃないと横方向に移動できませんが,DWA Local Plannerで対象としているロボットはその場で回転ができるロボット対象でした...
何とかハックできないかと思ったのですが,アッカーマンとかいろいろ考えだすと簡単にできそうでなく..午前中は途方に暮れていたのですが,見つけました.「teb_local_planner」です!いやあ,オープンソース様様ですね.DWA Local Plannerのパラメータ設定からそれほど大きな変更をすることなくすんなりと動かすことができました.実際に長い距離を動かし始めると問題も出てくるかと思うのですが,とりあえず明日もう少しパラメータ調整を実施して問題なさそうなら,次のアイテムに進みたいと思います.下記ビデオはteb_local_plannerを用いたレーンチェンジ動作のイメージです.

youtu.be

ROS Navigation Stack ~ DWA Local Planner パラメータ調整1 ~

先日の投稿で,cmd_velをつかってロボットが動かせるようになった様子をアップしましたが,今日はついにmove_baseを使ってロボットを動かせるようにします.すでにちょっと試してみて,前進はできるようになったのですが曲がる動作がどうもうまくいかず...パラメータを一通り勉強して調整する必要があるかと思ったので,このエントリを作りました.

1. DWA Local Plannerとは

 ROSではローカルプランニングようにいくつかアルゴリズムが選択できるようになってますが,今回はDWA Local Plannerを使うことにしました.DWA Local Plannerでは,下記のようなフローで実際に軌道が生成されます.

  1. ロボットの実現可能な制御空間を速度 (vx, vy, vtheta) をサンプリング.
  2. サンプリングしたそれぞれの速度に対して,速度積分していって実現軌道を取得.
  3. サンプリングしたそれぞれの実現軌道に対して,スコアリングを実施する.ROSで実際に実装されているスコアの基準としては,「1.ゴールからの距離」「2.障害物からの距離」「3.グローバルパスからの乖離度」.
  4. スコアの一番高かった軌道を選択して,その軌道を生成した速度をcmd_velとして送信する.

2. 各種パラメータ

変更必須のパラメータ
座標軸毎の最大・最小速度

自分のロボットは車両型でy方向には動けないので,速度設定は下記のようになるみたい.
あと,つくばチャレンジの速度制限から,x方向の最大速度は1m/s(=3.6kph)

DWAPlannerROS:
max_vel_x: 1.0
min_vel_x: 0.0
max_vel_y: 0.0
min_vel_y: 0.0

縦横方向の最大・最小速度

DWAPlannerROS:
max_trans_vel: 1.0
min_trans_vel: 0.0
trans_stopped_vel: 0.1

最大・最小角速度

DWAPlannerROS:
max_rot_vel: 0.5
min_rot_vel: 0.0
rot_stopped_vel: 0.0

最大加速度

DWAPlannerROS:
acc_lim_x: 0.5
acc_lim_theta: 0.2
acc_lim_y: 0.0

必要に応じて変更するパラメータ
目標位置との許容誤差パラメータ

yaw_goal_tolerance: 0.1
xy_goal_tolerance: 0.15

制御空間でサンプリングした値に対するシミュレーションパラメータ

sim_time: 4.0
vx_samples: 10
vy_samples: 1
vtheta_samples: 20
sim_granularity: 0.025

ひとまず上記設定でロボットを動かしてみて,うまくいけばアップします!

ROS Navigation Stack ~ Arduino Controller ~

Arduino, ROSの制御周りの実装・リファクタが終わりました.
制御にはPIDを用いましたが,等速直線運動,定常円旋回に関してはそこそこうまく動くようになりました.
ちょっとギクシャクしてしまってますが,これは制御器の設定が悪いせいではなく,ハードの作りこみが甘いことが原因のようで,制御パラメータをいくら変えても改善しませんでした...

youtu.be

youtu.be

youtu.be

youtu.be

ということで,想定より時間がかかってしまいましたが,ようやく cmd_vel を受けるインターフェースが整ったので,今週から Navigation Stack を使ってロボットを動かしていきます!

今月のやること.ROS Navigation Stack

おはようございます.なんと,はや3月...最近時間がたつのが早いです.
さて,今月のロボット目標です.2月中にROS Navigation Stackを動かしてみる予定でしたが,案の情遅れてしまいました.OdometryやArduino周りのコードをリファクタしてたら思いのほか時間がかかってしまったというのが理由ですが,まあ,理解は深まってコードも整理されたので良しとしましょう!

ということで,3月も引き続き ROS Navigation Stackを動かすことを目標にやっていきます.

1. Week of 2017/3/6
Navigation Stackを用いたロボットの前進・右折・左折
2. Week of 2017/3/13
 Odometryフレーム内でのロボットの制御
3. Week of 2017/3/20
 ?? 
4. Week of 2017/3/27
 ??

ROS Navigation Stack ~ Arduino Controller ~

おはようございます.前回の投稿から一週間以上経過して,早くも当初の目標をデコミットしてしまいましたが,,,
なにもしていなかったわけではなく,久々にArduinoのコードを整理していたらわけがわからなくなってしまい,,,,整理ついでにリファクタリングしてました.
あと,つくるものの規模が比較的大きくなってくると,どうしても前に作業したことを覚えておくのが難しくなってしまい,忘れてしまうので,備忘もかねて簡単な設計書を残すことにしました.
(なんか仕事でもないのに,仕事みたいなことしてるな...)

www.slideshare.net

制御のパラメータ調整をしないといけないですが,それはまた後日のエントリで...

ROS Navigation Stack について3 ~ Goalを送信するノードの作成 ~

move_baseとodometryに関しては整ったので,ここではmove_baseに対してゴールを送信するノードを作成します.
引用:http://wiki.ros.org/ja/navigation/Tutorials/SendingSimpleGoals

ただ,今回作成したシステムでは,オドメトリ情報がでたらめなので,実際にロボットでmove_baseを動かすには,ここを調整してあげる必要があります.
実際のodometryノードに関しては,あとのポストで詳しく書ければと思います.

1. Goal送信ノード用のパッケージ作成

Goal送信ノード用のパッケージを生成します.ここでは,simple_goal_generatorパッケージとします.

cd ~/reps/catkin_ws/src
catkin_create_pkg simple_goal_generator move_base_msgs actionlib roscpp

2. Goal送信ノードの作成

ここでは,チュートリアル通りのコードsrc/simple_goal_generator.cppを作成します.

#include <ros/ros.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>

typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;

int main(int argc, char** argv){
  ros::init(argc, argv, "simple_goal_generator");

  //tell the action client that we want to spin a thread by default
  MoveBaseClient ac("move_base", true);

  //wait for the action server to come up
  while(!ac.waitForServer(ros::Duration(5.0))){
    ROS_INFO("Waiting for the move_base action server to come up");
  }

  move_base_msgs::MoveBaseGoal goal;

  //we'll send a goal to the robot to move 1 meter forward
  goal.target_pose.header.frame_id = "base_footprint";
  goal.target_pose.header.stamp = ros::Time::now();

  goal.target_pose.pose.position.x = 1.0;
  goal.target_pose.pose.orientation.w = 1.0;

  ROS_INFO("Sending goal");
  ac.sendGoal(goal);

  ac.waitForResult();

  if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
    ROS_INFO("Hooray, the base moved 1 meter forward");
  else
    ROS_INFO("The base failed to move forward 1 meter for some reason");

  return 0;
}

3. CMakeLists.txtの生成・編集

いつものように,catkinビルドのためにCMakeLists.txtを変更します.

cmake_minimum_required(VERSION 2.8.3)
project(simple_goal_generator)

find_package(catkin REQUIRED COMPONENTS
  actionlib
  move_base_msgs
  roscpp
)

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES simple_goal_generator
  CATKIN_DEPENDS actionlib move_base_msgs roscpp
  DEPENDS system_lib
)

include_directories(
  ${catkin_INCLUDE_DIRS}
)

add_executable(simple_goal_generator_node src/simple_goal_generator.cpp)

target_link_libraries(simple_goal_generator_node
  ${catkin_LIBRARIES}
)

4. ノードの起動

roscore
rosrun simple_goal_generator simple_goal_generator_node

move_baseノードが起動している状態で上記ノードを起動すると,goal座標をmove_baseに送ってくれます.
送信後は,下記のようなログが出力されます.

[ INFO] [1486816759.533561032]: Sending goal