tag:blogger.com,1999:blog-31139268835346509802024-03-06T04:10:16.535+09:00毎日がロボット勉強会岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.comBlogger42125tag:blogger.com,1999:blog-3113926883534650980.post-79425492962308104822015-01-04T20:38:00.000+09:002014-12-19T20:36:55.747+09:0010.ロボットビジョン(応用編その1) 10.5 ROSとOpenCVのブリッジ: cv_bridge パッケージ<br />
cv_bridge パッケージでROSでイメージデータをOpenCVで画像処理してみます。<br />
カメラがKinectの時は、<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision openni_node.launch</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
あるいは、Webカメラの時は、</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision uvc_camera.launch device:=/dev/video0</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
別のターミナルウィンドウで、</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ rosrun rbx1_vision cv_bridge_demo.py</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
次のような画像が表示されます。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhOIz4doOPv_DtRqKatgjLQ5mxmuggn7ib-hcuCskdLVgRCKlH9QxowFb5am2xdn8THeq51XE_Qryle6Y4TdNaJK7O2EzKL-KVd7Qxqjz5QBLwgypjVBaQF4ETZOXgfylsqnKOw7xaeuw/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-16+21.13.10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhOIz4doOPv_DtRqKatgjLQ5mxmuggn7ib-hcuCskdLVgRCKlH9QxowFb5am2xdn8THeq51XE_Qryle6Y4TdNaJK7O2EzKL-KVd7Qxqjz5QBLwgypjVBaQF4ETZOXgfylsqnKOw7xaeuw/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-16+21.13.10.png" /></a></div>
<div>
<br /></div>
10.6 ros2opencv2.py ユーティリティ<br />
カメラがKinectの時は、<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision openni_node.launch</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
あるいは、Webカメラの時は、</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision uvc_camera.launch device:=/dev/video0</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
別のターミナルウィンドウで、</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision ros2opencv2.launch</span></span></pre>
もう一つ別のターミナルウィンドウで、<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;"> </span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">$ rostopic echo /roi</span></span></pre>
<br />
次のような画像が表示されます。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVaK8Kc8HCH7VK5nXJPlffGOlqkWH9hFF6G9L0JxxJ51_T__-2s_gxcAYT7SOye2ngMnUIhq1ntzU-dU471bLvuZf66iRIo3_zsX66MTPJ8i2LWwhnWzk4jWjJ9AXhydN4hRtbrxyFeWg/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-18+21.42.10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVaK8Kc8HCH7VK5nXJPlffGOlqkWH9hFF6G9L0JxxJ51_T__-2s_gxcAYT7SOye2ngMnUIhq1ntzU-dU471bLvuZf66iRIo3_zsX66MTPJ8i2LWwhnWzk4jWjJ9AXhydN4hRtbrxyFeWg/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-18+21.42.10.png" height="235" width="320" /></a></div>
<br />
<br />
<br />
10.7 録画された動画の処理<br />
video2ros.pyプログラムで、予め録画した動画を利用することができます。<br />
以前に使った、画像処理にプログラムを実行し、<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ rosrun rbx1_vision cv_bridge_demo.py</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
別のターミナルウィンドウで、</div>
<span class="anchor" id="line-75" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="line-76" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision video2ros.launch input:=`rospack find \
rbx1_vision`/videos/hide2.mp4</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhse-5qqLf47tZOoLoNuXPlq-2aaxy8UNMsgHsnNpYqlwqv7Sk5vK0H2kQsKDuuM9I5RQPdoksotcStX_3_L9h_NYuP_4VNpARfP4Fy2pwK6L7kKmvbGFrBlBEg7cNJVfBVFc_qq5ZqN_I/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-18+21.50.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhse-5qqLf47tZOoLoNuXPlq-2aaxy8UNMsgHsnNpYqlwqv7Sk5vK0H2kQsKDuuM9I5RQPdoksotcStX_3_L9h_NYuP_4VNpARfP4Fy2pwK6L7kKmvbGFrBlBEg7cNJVfBVFc_qq5ZqN_I/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-18+21.50.16.png" height="316" width="640" /></a></div>
<div>
<br /></div>
<div class="line862" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="line-75" style="box-sizing: border-box;"></span><span class="anchor" id="line-76" style="box-sizing: border-box;"></span></div>
<div class="line862" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<br /></div>
<br />
<br />岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-59823017422198042152015-01-02T21:29:00.000+09:002014-12-19T20:37:15.982+09:0010. ロボットビジョン(準備編)10章はOpenCVと連携することにより、様々な画像処理の例を紹介しています。<br />
<br />
10.1 OpenCV, OpenNI と PCL<br />
<a href="http://opencv.org/">OpenCV</a>は<a href="http://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%82%BD%E3%83%BC%E3%82%B9" style="background: none rgb(255, 255, 255); color: #0b0080; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px; text-decoration: none;" title="オープンソース">オープンソース</a><span style="background-color: white; color: #252525; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px;">の</span><a href="http://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%93%E3%82%B8%E3%83%A7%E3%83%B3" style="background: none rgb(255, 255, 255); color: #0b0080; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px; text-decoration: none;" title="コンピュータビジョン">コンピュータビジョン</a><span style="background-color: white; color: #252525; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px;">向けライブラリで、画像処理の必要な様々な機能が用意されています。</span><br />
<span style="background-color: white; color: #252525; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px;">OpenNIはオープンソースのKinect用のライブラリであり、ROSからKinectの機能を使うために必須です。</span><br />
<span style="background-color: white; color: #252525; font-family: sans-serif; font-size: 15.1999998092651px; line-height: 19.3331203460693px;"><a href="http://pointclouds.org/">PCL</a>(Point Cloud Library)は</span>オープンソースの3Dポイントクラウド(点群)データ処理をまとめたライブラリであり、Kinectの3D距離データを利用する。<br />
本書では、以下のトピックについて触れる<br />
<br />
<ul>
<li>WebカメラあるいはKinect(RDB-D カメラ)をROSから利用する</li>
<li>ROS cv_bridge によりROSのイメージをOpenCVで処理する</li>
<li>顔検出、オプティカルフロー、色追跡等のROSによる実装</li>
<li>Kinectから得られる距離情報処理</li>
</ul>
<br />
10.2 カメラの解像度に関して<br />
処理速度との関係で、本書で扱う画像は320x240 (QVGA)であるが、場合によっては640x480 (VGA)で試してみます。<br />
<div>
<br /></div>
10.3 カメラドライバーのインストール<br />
10.3.1 OpenNI用ドライバーのインストール<br />
ROSではKinect for X360をサポートしており、以下のようにOpenNIのドライバをインストールする。<br />
<span style="color: red;">KinectはVMwareで実行されたUbuntu上では動作しないので注意が必要である。</span><br />
<pre style="border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ sudo apt-get install ros-hydro-openni-camera</span></span>
</pre>
<div>
<br /></div>
10.3.2 Webカメラ用ドライバーのインストール<br />
<div>
ROS by ExampleではWebカメラのドライバ−にuvc_camを使っています(141ページ)</div>
<div>
が、ソースをダウンロードしてコンパイルしなければいけないし、いろいろ面倒なので、</div>
<div>
私はuvc_camera を使いました。</div>
<div>
私の環境ではuvc_camera の方が安定して動いているようです。</div>
<div>
以下のコマンドでインストールが可能です。</div>
<div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 1.428571429; white-space: pre-wrap;">$ </span></span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">sudo apt-get install ros-hydro-uvc-camera</span></span></pre>
</div>
<div>
<br />
10.3.3 Kinect あるいは Xtion カメラのテスト<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision openni_node.launch</span></span></pre>
<span class="anchor" id="line-75" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="line-76" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><br />
<div class="line862" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
別のターミナルウィンドウで、</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ rosrun image_view image_view image:=/camera/rgb/image_color</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWWVSQt9u5L5DL4Obw_9kCYZPjzLIxy7977pIw9ruIrZCL_Z1qZGekpHsiJlbgNzoDsxE9mcuvPmpPkuWBpMHpFSWZEolMKEZ2jpTpSEWqephW8ke3GNhcT7uE_bOUvysaF6zJ7du5f38/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-23+13.13.58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWWVSQt9u5L5DL4Obw_9kCYZPjzLIxy7977pIw9ruIrZCL_Z1qZGekpHsiJlbgNzoDsxE9mcuvPmpPkuWBpMHpFSWZEolMKEZ2jpTpSEWqephW8ke3GNhcT7uE_bOUvysaF6zJ7du5f38/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-23+13.13.58.png" height="255" width="320" /></a></div>
<div>
こんな感じでカラー画像が表示されます。</div>
<div>
同様に、以下のコマンドで距離画像が表示されます。</div>
<div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ rosrun image_view disparity_view image:=/camera/depth/disparity</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
<br /></div>
</div>
10.3.4 USB Webカメラのテスト<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision uvc_camera.launch device:=/dev/video0</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
あるいは</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ roslaunch rbx1_vision uvc_camera.launch device:=/dev/video1</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
/dev/video* の*はお使いの環境に合わせて変えて下さい。 </div>
<div>
また、<span style="color: red;">ROS by Example では uvc_cam.launch ですが、ここでは uvc_camera.launchとします。</span></div>
<div>
別のターミナルウィンドウで、以下のようにコマンドを実行すると、カラー画像が表示されるはずです。</div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ rosrun image_view image_view image:=/camera/rgb/image_color</span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
<br /></div>
10.4 OpenCV の Ubuntu Linuxへのインストール<br />
以降の章で使うOpenCVライブラリを次にようにインストールしておいてください。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$ sudo apt-get install ros-hydro-opencv2 ros-hydro-vision-opencv</span></span></pre>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-79591893691119620152014-12-23T16:17:00.000+09:002014-12-24T16:17:56.222+09:008.2.5 障害物が存在する場合に手動でゴールを設定する岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-5112607301201659362014-12-23T16:16:00.001+09:002014-12-24T16:17:23.277+09:008.2.4 仮想障害物の回避岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-52551351552574989152014-12-23T16:16:00.000+09:002014-12-24T16:16:39.839+09:008.2.3 move_baseを使った四角形に沿った移動 8.2.3 move_baseを使った四角形に沿った移動<br />
<br />岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-10565944321813851382014-12-22T20:39:00.000+09:002014-12-24T16:14:53.631+09:008.2 ArbotiX シミュレータでmove_baseノードをテストする8.2 ArbotiX シミュレータによる move_base のテスト<br />
<br />
まだ地図が出来ていないので~/catkin_ws/src/rbx1/rbx1_nav/maps/blank_map.pgmという何も無い環境(真っ黒な地図)でロボットを動かす。<br />
地図の指定は以下のように~/catkin_ws/src/rbx1/rbx1_nav/maps/blank_map.yamlファイルで行う。<br />
<div class="line874" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
ノードを実行可能にすることを忘れないように:<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-162" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-163" style="box-sizing: border-box;"></span></div>
<div class="line867" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-164" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-165" style="box-sizing: border-box;"></span></div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-1-29" style="box-sizing: border-box;"></span>mage: blank_map.pgm
resolution: 0.01
origin: [-2.5, -2.5, 0]
occupied_thresh: 0.65
free_thresh: 0.196 # Taken from the Willow Garage map in the turtlebot_navigation package
negate: 0</pre>
move_baseノードはfake_move_base_blank_map.launchで起動する<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><launch>
<!-- Run the map server with a blank map -->
<node name="map_server" pkg="map_server" type="map_server" args="$(find rbx1_nav)/maps/blank_map.yaml"/>
<!-- Launch move_base and load all navigation parameters -->
<include file="$(find rbx1_nav)/launch/fake_move_base.launch" />
<!-- Run a static transform between /odom and /map -->
<node pkg="tf" type="static_transform_publisher" name="odom_map_broadcaster" args="0 0 0 0 0 0 /odom /map 100" />
</launch></span></span></pre>
始めに、map_serverノードをblank_map.yamlを引数として起動する<br />
次に、以下で説明する fake_move_base.launch を読み込む。fake_move_base.launch ではmove_baseノード<br />
を起動する。<br />
最後に、ここではブランク地図を使い、シミュレータ内のロボットはセンサを持たないので距離データを使えないので、<br />
代わりにオドメトリが完全なものとして、マップ上の自己位置を更新する。<br />
<br />
fake_move_base.launchは次のような内容です<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="line-1-8" style="box-sizing: border-box;"></span><launch>
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find rbx1_nav)/config/fake/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find rbx1_nav)/config/fake/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find rbx1_nav)/config/fake/local_costmap_params.yaml" command="load" />
<rosparam file="$(find rbx1_nav)/config/fake/global_costmap_params.yaml" command="load" />
<rosparam file="$(find rbx1_nav)/config/fake/base_local_planner_params.yaml" command="load" />
</node>
</launch></pre>
<span class="anchor" id="line-75" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="line-76" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span>パラメータファイルに関しては8.1.2を見てください。<br />
<br />
起動は以下のようにします。<br />
始めに、ArbotiXシミュレータを起動します。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="line-1-8" style="box-sizing: border-box;"></span>$roslaunch rbx1_bringup fake_turtlebot.launch</pre>
ここで、KOBUKIを使いたいときには<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$roslaunch rbx1_bringup fake_turtlebot2.launch</span></span></pre>
とします。<br />
次に、move_baseノードをブランク地図で起動します。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="font-family: 'Hiragino Kaku Gothic Pro'; white-space: normal;">$roslaunch rbx1_nav fake_move_base_blank_map.launch</span></pre>
さらに、可視化のためにRvizを起動します。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="font-family: Hiragino Kaku Gothic Pro;"><span style="white-space: normal;">$rosrun rviz rviz -d `rospack find rbx1_nav`/nav.rviz</span></span></pre>
最後に、コマンドラインからmove_baseアクションを送ることでロボットが指定された位置・姿勢に向けて移動します。<br />
以下の例は、ロボットをX軸方向に1mだけ移動させます。<br />
※以下のコマンドをコピペする時に、継続行を示す”バックスラッシュ”は不要です。<br />
<div class="line867" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-164" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-165" style="box-sizing: border-box;"></span></div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-1-29" style="box-sizing: border-box;"></span>$rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped \'{ header: { frame_id: "map" }, pose: { position: { x: 1.0, y: 0, z: 0 }, orientation: { x: 0, y: 0, z: 0, w: 1 } } }'</pre>
こちらを使って下さい。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped '{ header: { frame_id: "map" }, pose: { position: { x: 1.0, y: 0, z: 0 }, orientation: { x: 0, y: 0, z: 0, w: 1 } } }'</span></span></pre>
次のコマンドでは、グローバル座標系で初期位置・姿勢に戻ります。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: transparent; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">$rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped '{ header: { frame_id: "map" }, pose: { position: { x: 0, y: 0, z: 0 }, orientation: { x: 0, y: 0, z: 0, w: 1 } } }'</span></pre>
<div class="p2">
<br /></div>
ロボットの軌跡が直線経路ではなく遠回りしているように思えます。<br />
これは、経路上に障害物が無いので経路探索プログラムが一番スムーズだと思える経路を計算したからです。<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="line-1-8" style="box-sizing: border-box;"></span>pdist_scale (0.4)
gdist_scale (0.8)
最大速度 (max_vel_x)</pre>
このパラメータを変えると経路が変わります。<br />
このコマンドでパラメータを変えることができます。<br />
<br />
<div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rosrun rqt_reconfigure rqt_reconfigure</span></span></pre>
<span class="anchor" id="line-75" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="line-76" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><br />
8.2.1 RViz上で目的地をクリックして移動させる<br />
「2D Nav Goal」メニューをクリックし、マウスでゴールの位置と姿勢を指定する。<br />
<br />
<br />
クォータニオンについて<br />
一般的にロボットの姿勢を表すにはオイラー角であるRoll, Pitch, Yawを使いました。<br />
<div>
<br /></div>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-59434535943757368352014-12-21T20:39:00.000+09:002014-12-24T15:53:27.882+09:008.1.2 経路探索のパラメータの設定move_base ノードでは以下の4つのパラメータファイルが必要です。<br />
<br />
<h3>
<b>(1) base_local_planner_params.yaml</b></h3>
controller_frequency: 3.0<br />
経路のプランニングを行う周期。普通のノートPCで3〜5回/秒程度に設定する。<br />
max_vel_x: 0.3<br />
ロボットの最高並進速度(メートル毎秒)。室内だと0.3〜0.5程度<br />
min_vel_x: 0.05:<br />
ロボットの最低並進速度(メートル毎秒)<br />
max_rotational_vel: 1.0<br />
ロボットの最高回転速度(ラジアン毎秒)<br />
min_in_place_vel_theta: 0.5<br />
ロボットの最低回転速度(ラジアン毎秒)<br />
escape_vel: -0.1<br />
ロボットが回避するときの速度(メートル毎秒)。負の値は後退<br />
acc_lim_x: 2.5<br />
x座標方向への加速度の最大値<br />
acc_lim_y: 0.0<br />
y座標方向への加速度の最大値。0の場合は非ホロノミック台車の場合で真横には動けない<br />
acc_lim_theta: 3.2<br />
回転の加速度の最大値<br />
holonomic_robot: false<br />
全方位移動台車を使っていない場合は常に false<br />
yaw_goal_tolerance: 0.1<br />
目的の姿勢との許容誤差(ラジアン)。この値が小さいとゴール付近で振動してしまう。 <br />
xy_goal_tolerance: 0.1<br />
目的の位置との許容誤差(メートル)。地図の解像度よりも小さい値にしないこと。<br />
pdist_scale: 0.8<br />
グローバルパスにどれだけ正確に沿って移動するか。gdist_scaleより大きな値にすると、よりグローバルパスに沿って動く。<br />
gdist_scale: 0.4<br />
ゴールを目指すか、グローバルパスに沿うか、を決める。 <br />
occdist_scale: 0.1<br />
障害物を回避する程度を決める。<br />
sim_time: 1.0<br />
どれくらい先を考慮するか<br />
dwa: true<br />
Dynamic Window Approach を使うか否か<br />
<br />
<h3>
<b>(2) costmap_common_params.yaml</b></h3>
robot_radius: 0.165<br />
円形ロボットの場合、ロボットの半径(メートル)。<br />
円形で無いロボットの場合はfootprintパラメータを使う。<br />
0.165はTurtlebotのサイズ<br />
footprint: [[x0, y0], [x1, y1], [x2, y2], [x3, y3], etc]<br />
ロボットの形状<br />
inflation_radius: 0.3<br />
ロボットが障害物にぶつからないようにするための膨張パラメータ<br />
<br />
<h3>
<b>(3) global_costmap_params.yaml</b></h3>
global_frame: /map<br />
global cost map のフレーム名称<br />
robot_base_fame: /base_footprint<br />
TurtleBot用には /base_footprint を使う。<br />
update_frequency: 1.0<br />
global mapを更新する頻度<br />
publish_frequency: 0<br />
static globalマップは通常連続して配信する必要な無い<br />
static_map: true<br />
global map は静的<br />
rolling_window: false<br />
global map はロボットが動いても変更されないのでfalseにする<br />
transform_tolerance: 1.0<br />
ネットワークの遅延に対処するための待ち時間(秒)<br />
<br />
<h3>
<b>(4) local_costmap_params.yaml</b></h3>
global_frame: /odom<br />
local cost mapにおけるオドメトリのフレーム<br />
robot_base_fame: /base_footprint<br />
/base_link あるいは /base_footprintを設定<br />
TurtleBot の場合は /base_footprint.<br />
update_frequency: 3.0<br />
local map の更新頻度<br />
publish_frequency: 1.0<br />
local map の配信頻度 <br />
static_map: false<br />
local map は更新されるので、静的では無い。<br />
rolling_window: true<br />
local map は更新される。<br />
width: 6.0<br />
rolling map x座標方向<br />
height: 6.0<br />
rolling map y座標方向<br />
Resolution: 0.01<br />
rolling mapの解像度<br />
transform_tolerance: 1.0<br />
ネットワークの遅延に対処するための待ち時間(秒)<br />
<div>
<br /></div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-77946462346280424382014-12-20T20:39:00.001+09:002014-12-24T15:51:47.358+09:008.1 move_baseを使った経路探索と障害物回避8.1 move_baseパッケージによる経路生成と障害物回避<br />
これまでロボットを四角形に沿って動かすスクリプトを書いた。<br />
move_baseパッケージは更に洗練された方法で同じことが実現できる。<br />
move_baseパッケージはROS Action<br />
<br />
8.1.1 move_baseパッケージにおけるゴールの指定方法<br />
MoveBaseActionGoalメッセージによる<br />
rosmsg show MoveBaseActionGoalで確認してください。<br />
Point型の位置(x座標、y座標、z座標)と<br />
Quaternion型の姿勢(z, y, z, w)で指定します。岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-54590029183606498412014-12-19T20:39:00.000+09:002014-12-24T15:49:36.806+09:008. ナビゲーション、経路探索とSLAMNavigation Stackを構成する中心的なパッケージ<br />
<br />
<ul>
<li>move_base 目的に位置・姿勢にロボットを移動させる</li>
<li>gmaping 地図作成</li>
<li>amcl 地図を使って自己位置を求める</li>
</ul>
<br />
この3つがあれば、地図上の任意の場所に障害物を避けながら移動することが可能になる。<br />
<br />
<a href="http://wiki.ros.org/navigation/Tutorials">http://wiki.ros.org/navigation/Tutorials</a><br />
<a href="http://wiki.ros.org/navigation/Tutorials/RobotSetup">http://wiki.ros.org/navigation/Tutorials/RobotSetup</a>岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-23936178938293817802014-12-18T19:18:00.000+09:002014-12-24T15:43:54.515+09:007.10.2 ゲームパッドを使った実機ロボットの操縦キーボードと同様にジョイスティックで実機ロボット(Kobuki)を動かしてみます。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$sudo apt-get install ros-hydro-joystick-drivers</pre>
ジョイスティックのドライバーをインストールしてあることを確認して。<br />
<br />
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"></pre>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-57594472834202700752014-12-17T20:17:00.000+09:002014-12-19T20:46:22.936+09:007.10.1 キーボートを使った実機ロボットの操縦いよいよ実機ロボットを動かしてみます。<br />
私のところにあるのはKobukiベースのTurtlebot2なので本のコマンドとは多少違います。<br />
<h4>
必要なパッケージのインストール</h4>
<div>
次回以降、ジョイスティック等を使ってロボットのコントールも行うので、併せて必要なパッケージをインストールしておきます。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 1.428571429; white-space: pre-wrap;">$ </span></span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">sudo apt-get install ros-hydro-kobuki*</span></span></pre>
</div>
<div>
<span style="color: #333333; font-family: courier, monospace; font-size: x-small;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><br /></span></span>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$sudo apt-get install ros-hydro-joystick-drivers</span></span></pre>
</div>
<div>
<br /></div>
<h4>
Kobukiのドライバのインストール</h4>
<div>
始めに、Kobukiのドライバーをインストールします。<a href="http://www.rt-shop.jp/blog/archives/368">RTのページ</a>を参考にしました。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$rosrun kobuki_ftdi create_udev_rules</pre>
スーパユーザ(sudo)のパスワードを求められるので、入力して下さい。 コマンドが成功して、KobukiのUSBケーブルを接続すれば、以降は /dev/kobuki で実機Kobukiにアクセスができます。</div>
<div>
<br /></div>
<h4>
Kobukiを動かす</h4>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$roslaunch kobuki_node minimal.launch</pre>
別のTerminalウィンドウで<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">$roslaunch kobuki_keyop keyop.launch</span></span><span style="background-color: transparent; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;"> </span></pre>
矢印キーを入力すると,kobukiが動きます.キーを長押しすると速度が増します.スペースキーで停止します.「q」キーで終了します.</div>
<div>
<br /></div>
<div>
Turtlebotのパッケージを使っても同じようなことができます。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$roslaunch turtlebot_bringup minimal.launch</pre>
別のTerminalウィンドウで<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">$roslaunch kobuki_keyop keyop.launch</span></span><span style="background-color: transparent; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;"> </span></pre>
あるいは<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">roslaunch turtlebot_teleop keyboard_teleop.launch</span></span></pre>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
他にもドッキングステーションへの帰還など様々な機能があります。</div>
<div>
詳細は<a href="http://www.rt-shop.jp/blog/archives/368">RTのページ</a>あるいは<a href="http://wiki.ros.org/ja/Robots/TurtleBot">ROSのチュートリアルページ</a>を御覧ください。</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-77603205893556062092014-12-16T20:40:00.000+09:002014-12-24T15:42:51.891+09:007.10 ロボットを操縦する7.10 ロボットを操縦する<br />
これまでの章で /cmd_vel ノードにTwistメッセージを配信することでロボットを動かしました。<br />
ここでは、キーボードやゲームパッド等を使いロボットを動かしてみます。<br />
<br />
<br />
7.10.3 ArbotiX コントール GUI<br />
<br />
7.10.4 Interactive MarkersによるTurtleBotの操縦<br />
<br />
7.10.5 オリジナルの操縦ノードを書く岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-11369204173220341612014-12-16T15:32:00.000+09:002014-12-24T15:39:46.396+09:007.9.4 デッドレコニングの問題点<div class="p1">
ロボットが移動する際に、エンコーダの値(モータの回転量)などの内部センサにだけに頼り、外部のランドマークなどを利用しない手法をデッドレコニングと呼ぶ。</div>
<div class="p1">
皆さんも御存知のように、デッドレコニングによる自己位置の推定は時間が経つにつれ徐々に誤差が蓄積され、やがては自己位置が解らなくなってしまいます。</div>
<div class="p1">
<br /></div>
<div class="p1">
例えば、自分の姿勢が1度ずれたまま、3m進むと約5cmの誤差を生じます。しかし、ロボットは自分の思っている位置と実際の正しい位置との誤差の5cmを知ることは出来ないのです。</div>
<div class="p1">
<br /></div>
<div class="p1">
ROSでは主にSLAMという手法を用いることで、このようなデッドレコニングの問題点を解決しようとしています。</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-88426347052413029022014-12-15T20:59:00.000+09:002014-12-24T15:32:15.124+09:007.9.3 四角形に沿って移動する nav_square.py を見てみる<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">import rospy
from geometry_msgs.msg import Twist, Point, Quaternion
import tf
from rbx1_nav.transform_utils import quat_to_angle, normalize_angle
from math import radians, copysign, sqrt, pow, pi</span></span>
</pre>
ここまではお馴染みですね<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">class NavSquare():
def __init__(self):
# Give the node a name
rospy.init_node('nav_square', anonymous=False)
# Set rospy to execute a shutdown function when terminating the script
rospy.on_shutdown(self.shutdown)
# How fast will we check the odometry values?
rate = 20
# Set the equivalent ROS rate variable
r = rospy.Rate(rate)</span></span></pre>
今回のスクリプトの周期は20Hzです<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Set the parameters for the target square
goal_distance = rospy.get_param("~goal_distance", 1.0) # meters
goal_angle = rospy.get_param("~goal_angle", radians(90)) # degrees converted to radians
linear_speed = rospy.get_param("~linear_speed", 0.2) # meters per second
angular_speed = rospy.get_param("~angular_speed", 0.7) # radians per second
angular_tolerance = rospy.get_param("~angular_tolerance", radians(2)) # degrees to radians</span></span></pre>
今回のスクリプトでは、rospy.get_param()でパラメータを設定しています。<br />
<div>
<a href="http://wiki.ros.org/rospy_tutorials/Tutorials/Parameters">パラメータに関するチュートリアルはこちらです</a>。</div>
<div>
値は.launchファイルで与えます。<br />
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Publisher to control the robot's speed
self.cmd_vel = rospy.Publisher('/cmd_vel', Twist)
# The base frame is base_footprint for the TurtleBot but base_link for Pi Robot
self.base_frame = rospy.get_param('~base_frame', '/base_link')</span></span>
</pre>
<div>
base frameはTurtlebotの場合は base_footprint, PiRobotの場合は base_link です</div>
<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # The odom frame is usually just /odom
self.odom_frame = rospy.get_param('~odom_frame', '/odom')
# Initialize the tf listener
self.tf_listener = tf.TransformListener()
# Give tf some time to fill its buffer
rospy.sleep(2)
# Set the odom frame
self.odom_frame = '/odom'</span></span>
</pre>
オドメトリのフレームは /odom です。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Find out if the robot uses /base_link or /base_footprint
try:
self.tf_listener.waitForTransform(self.odom_frame, '/base_footprint', rospy.Time(), rospy.Duration(1.0))
self.base_frame = '/base_footprint'
except (tf.Exception, tf.ConnectivityException, tf.LookupException):
try:
self.tf_listener.waitForTransform(self.odom_frame, '/base_link', rospy.Time(), rospy.Duration(1.0))
self.base_frame = '/base_link'
except (tf.Exception, tf.ConnectivityException, tf.LookupException):
rospy.loginfo("Cannot find transform between /odom and /base_link or /base_footprint")
rospy.signal_shutdown("tf Exception")</span></span></pre>
/base_link あるいは /base_footprint<br />
<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Initialize the position variable as a Point type
position = Point()
# Cycle through the four sides of the square
for i in range(4):</span></span>
</pre>
位置を初期化して、四角形に一辺づつ動くので、繰り返しを4にします。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Initialize the movement command
move_cmd = Twist()
# Set the movement command to forward motion
move_cmd.linear.x = linear_speed
# Get the starting position values
(position, rotation) = self.get_odom()
x_start = position.x
y_start = position.y</span></span>
</pre>
<div>
移動のためのTwistメッセージを初期化して、直進の移動スピードを設定して、現在のオドメトリの値を初期位置・姿勢に代入します。</div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Keep track of the distance traveled
distance = 0
# Enter the loop to move along a side
while distance < goal_distance and not rospy.is_shutdown():
# Publish the Twist message and sleep 1 cycle
self.cmd_vel.publish(move_cmd)
r.sleep()
# Get the current position
(position, rotation) = self.get_odom()
# Compute the Euclidean distance from the start
distance = sqrt(pow((position.x - x_start), 2) +
pow((position.y - y_start), 2))</span></span>
</pre>
<div>
指定した距離だけ動くために。</div>
<div>
速度をパブリッシュして、1サイクルだけスリープします。</div>
<div>
自己位置(オドメトリの値)を取得して、初期位置からの移動距離を求めます。</div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"> # Stop the robot before rotating
move_cmd = Twist()
self.cmd_vel.publish(move_cmd)
rospy.sleep(1.0)
# Set the movement command to a rotation
move_cmd.angular.z = angular_speed
# Track the last angle measured
last_angle = rotation
# Track how far we have turned
turn_angle = 0
# Begin the rotation
while abs(turn_angle + angular_tolerance) < abs(goal_angle) and not rospy.is_shutdown():
# Publish the Twist message and sleep 1 cycle
self.cmd_vel.publish(move_cmd)
r.sleep()
# Get the current rotation
(position, rotation) = self.get_odom()
# Compute the amount of rotation since the last lopp
delta_angle = normalize_angle(rotation - last_angle)
turn_angle += delta_angle
last_angle = rotation</span></span>
</pre>
<div>
同様に、90度回転します。</div>
<div>
で、また直進、90度回転、直進、90度回転、直進、90度回転</div>
<div>
これで四角形に沿って移動しました。</div>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-17321175032766240202014-12-15T20:40:00.000+09:002014-12-24T15:30:00.996+09:007.9 オドメトリを使った四角形に沿った移動7.9 オドメトリを使った四角形に沿った移動<br />
ここでは、四角形の頂点を4つの経由点とし、四角形に沿った移動を行ないます。<br />
<br />
7.9.1 シミュレータによる四角形に沿った移動<br />
<br />
7.9.2 実機ロボットによる四角形に沿った移動岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-42435970960336175882014-12-14T21:03:00.000+09:002014-12-24T15:28:01.835+09:007.8.4 /odom トピックか /odom フレームか?<br />
トピック<br />
トピックはROSのノード間で配信(発信)したり購読(受信)するデータのことです。<br />
<br />
フレーム<br />
ロボットシステムでは、一般的に、たくさんのワールドフレーム、ベースフレーム、グリッパーフレーム、ヘッドフレームなどなどの常に変化する座標系フレームを持ちます。<br />
tfは常にこれらのフレームをトラックし、以下のようなことを聞きだせるようにしています。<br />
・5秒前のworldフレームから見たheadフレームはどこ?<br />
・基準に対してロボットの手にあるオブジェクトの形はどのような姿勢になっている?<br />
・マップフレームの中でベースフレームはどのような姿勢を今とっている?<br />
tfはディストリビューテッドシステムの中で操作できます。<br />
これは、ロボットの座標系フレームに関するすべての情報はシステムの中のすべてのコンピュータのROSのコンポーネントで利用できることを意味します。<br />
このtfの情報(transform information)にとっては中心のサーバーとなるものは存在しません。<br />
(<a href="http://wiki.ros.org/ja/tf">ROS チュートリアルより</a>)<br />
<br />
/odom トピックか/odomフレームか?<br />
ロボットの位置・姿勢を扱う時に、<b>トピック</b>で扱う方法と<b>フレーム</b>で扱う方法が考えられます。岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-88702896949546062132014-12-14T20:23:00.000+09:002014-12-24T15:27:51.253+09:007.8 オドメトリを使ったOut and Backスクリプト7.8.1 シミュレータによるオドメトリを使った Out and Back<br />
7.8.2 実機によるオドメトリを使った Out and Back<br />
7.8.3 オドメトリを使った Out-and-Back のPythonスクリプト<br />
<div class="p1">
<br />
<br />
Out and Back スクリプトは7.6.2 Pythonスクリプトでロボットを動かしてみる(シミュレーション編)で使ったスクリプトです。</div>
<div class="p1">
Out and Backはロボットに一定時間だけ速度を与え続けることで、目的の距離だけ移動します。</div>
<div class="p1">
<br /></div>
<div class="p1">
ここでは、ロボットのオドメトリ(自己位置)を利用してロボットを動かすことを考えます。オドメトリは必ずしも正確ではありませんが、速度を一定時間だけ決め打ち(?)で与えるよりは正確に移動できます。</div>
<div class="p1">
<br /></div>
<div class="p1">
ここでは、オドメトリを使ったodom_out_and_back.pyスクリプトを見ていきます。</div>
<div>
<span style="color: #333333; font-family: courier, monospace; font-size: x-small;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><br /></span></span></div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">1 #!/usr/bin/env python
2
3 import rospy
4 from geometry_msgs.msg import Twist, Point, Quaternion
5 import tf
6 from rbx1_nav.transform_utils import quat_to_angle, normalize_angle
7 from math import radians, copysign, sqrt, pow, pi</span></span></pre>
geometry_msgsパッケージに含まれる、Twist,Point,Quaternionメッセージタイプを使えるようにする。</div>
<div>
/odom と /base_link (あるいは /base_footprint) を変換するための tf メッセージタイプを使えるようにする。</div>
quat_to_angleはquaternion を オイラー角 (yaw) に変換する関数、<br />
<div class="p1">
normalize_angle はremoves the ambiguity between 180 and -180 degrees as well as 0 and 360 degreesする関数で、いずれもROS by Exampleのサンプルコードに含まれる。</div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">9 class OutAndBack():
10 def __init__(self):
11 # Give the node a name
12 rospy.init_node('out_and_back', anonymous=False)
13
14 # Set rospy to execute a shutdown function when exiting
15 rospy.on_shutdown(self.shutdown)
16
17 # Publisher to control the robot's speed
18 self.cmd_vel = rospy.Publisher('/cmd_vel', Twist)
19
20 # How fast will we update the robot's movement?
21 rate = 20
</span></span><span style="background-color: transparent; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">22
23 # Set the equivalent ROS rate variable
</span><span style="background-color: transparent; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">24 r = rospy.Rate(rate)</span></pre>
/cmd_velトピックにTwist型の型のメッセージ(コマンド?)を送る宣言をします。
一秒間に20回のタイミングでコマンドをアップデートします。
<br />
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">26 # Set the forward linear speed to 0.2 meters per second
27 linear_speed = 0.2
28
29 # Set the travel distance in meters
30 goal_distance = 1.0
31
32 # Set the rotation speed in radians per second
33 angular_speed = 1.0</span></span></pre>
直進速度は秒速0.2メートルでゴールまでの距離は1メートル。<br />
<div>
回転角度は1秒間に1ラジアン。</div>
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">35 # Set the angular tolerance in degrees converted to radians
36 angular_tolerance = radians(2.5)</span></span></pre>
angular_tolerance は角度の許容誤差をラジアンで表した変数です。</div>
<div>
実機のロボットは目的角度にピッタリ止めるのは難しく、目的角度周辺で振動してしまいます(行き過ぎて、逆回転して、戻りすぎて、逆回転して…)。</div>
<div>
そこで、angular_toleranceに入ったらOKにしましょう、という値です。</div>
<div>
<br /></div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">38 # Set the rotation angle to Pi radians (180 degrees)
39 goal_angle = pi</span></span></pre>
回転角度の目標値は180度です。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">41 # Initialize the tf listener
42 self.tf_listener = tf.TransformListener()</span></span></pre>
TransformListenerオブジェクトを生成する。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">44 # Give tf some time to fill its buffer
45 rospy.sleep(2)</span></span></pre>
tfはバッファにデータが溜まるのに時間がかかるので、2秒スリープする。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">47 # Set the odom frame
48 self.odom_frame = '/odom'
49</span></span></pre>
<div>
ロボットの位置・姿勢を取得するために、 /base_footprint あるいは <span class="s1">/base_link を /odm フレームの変換する。</span></div>
<div>
<br /></div>
<div>
TurtleBot の場合は/base_footprint フレームを使う。</div>
<div class="p1">
Pi Robot や Maxwell の場合は <span class="s1">/base_link フレームを使う。</span></div>
<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">50 # Find out if the robot uses /base_link or /base_footprint</span><span style="color: #333333; font-family: courier, monospace;"><span style="background-color: #f3f5f7; line-height: 18.5714302062988px; white-space: pre-wrap;">51 try:
52 self.tf_listener.waitForTransform(self.odom_frame, '/base_footprint', rospy.Time(), rospy.Duration(1.0))
53 self.base_frame = '/base_footprint'
54 except (tf.Exception, tf.ConnectivityException, tf.LookupException):
55 try:
56 self.tf_listener.waitForTransform(self.odom_frame, '/base_link', rospy.Time(), rospy.Duration(1.0))
57 self.base_frame = '/base_link'
58 except (tf.Exception, tf.ConnectivityException, tf.LookupException):
59 rospy.loginfo("Cannot find transform between /odom and /base_link or /base_footprint")
60 rospy.signal_shutdown("tf Exception")</span></span>
</pre>
try:</div>
<div>
/base_footprint が見つかるか?</div>
<div>
except:</div>
<div>
try:</div>
<div>
/base_link が見つかるか?</div>
<div>
except:</div>
<div>
どちらも見つからないので、エラーを出力して終了</div>
<div>
<br /></div>
<div>
<div>
self.tf_listener.waitForTransform(self.odom_frame, '/base_footprint', rospy.Time(), rospy.Duration(1.0))</div>
<div>
waitForTransform()には4つの引数がある:</div>
<div>
<div>
取得したい変換のfromにあたるframe(ここでは /odm)</div>
<div>
取得したい変換のtoにあたるframe(ここでは /base_footprint)</div>
<div>
指定する時間</div>
<div>
時間切れ: この最大の期間よりは長く待たない(ここでは1.0秒)</div>
<div>
/odmとbase_footprint'との間のtransformが利用可能になるか、transformが利用可能でない場合、時間切れが来るまでブロックします。</div>
</div>
<div>
<br /></div>
<div>
self.base_frame = '/base_footprint'</div>
</div>
<div>
以降はbase_frame を使います。</div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">62 # Initialize the position variable as a Point type
63 position = Point()</span></span></pre>
ロボットのポジジョンの為の変数を初期化します<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">66 for i in range(2):</span></span></pre>
スクリプトでは同じことを2回繰り返します(1st legと2nd leg) それぞれのlegでは、ロボットは1メートル進んだあとに180度回転します。<br />
<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">67 # Initialize the movement command
</span><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace; line-height: 18.5714302062988px; white-space: pre-wrap;">68 move_cmd = Twist()</span></pre>
</div>
<div>
ロボットに移動速度を指示する変数を初期化します<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">70 # Set the movement command to forward motion
71 move_cmd.linear.x = linear_speed</span></span></pre>
ロボットに移動速を指示する変数に直進速度を代入します<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">73 # Get the starting position values
74 (position, rotation) = self.get_odom()
75
76 x_start = position.x
77 y_start = position.y</span></span></pre>
現在のオドメトリの値を取得して、初期位置として設定します。</div>
<div>
<b>self.get_odom() 関数を先に説明します。(113行目から定義されています)</b><br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">130 def get_odom(self):
131 # Get the current transform between the odom and base frames
132 try:
133 (trans, rot) = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))
134 except (tf.Exception, tf.ConnectivityException, tf.LookupException):
135 rospy.loginfo("TF Exception")
136 return
137
138 return (Point(*trans), quat_to_angle(Quaternion(*rot)))</span></span></pre>
オドメトリとベースフレームの現在の変換を見るためにtf_listenerを使います。<br />
(trans, rot) = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))<br />
tf_listener.lookupTrasform 関数によりtransとrot(位置と姿勢)が求められたら、Point型の位置情報とQuaternion型の姿勢情報を返します。</div>
<div>
transとrotの前に付いている*記号はPythonスクリプトの記法で、transではx座標, y座標, z座標 、rotではx,y,z,wのQuaternion型のリストデータを返します。</div>
<div>
<b>詳しくはPython言語の解説書を御覧ください。</b></div>
<div>
<br /></div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">79 # Keep track of the distance traveled
80 distance = 0
81
82 # Enter the loop to move along a side
83 while distance < goal_distance and not rospy.is_shutdown():
84 # Publish the Twist message and sleep 1 cycle
85 self.cmd_vel.publish(move_cmd)
86
87 r.sleep()
88
89 # Get the current position
90 (position, rotation) = self.get_odom()
91
92 # Compute the Euclidean distance from the start
93 distance = sqrt(pow((position.x - x_start), 2) +
94 pow((position.y - y_start), 2))</span></span></pre>
83行目から94行目までのループでロボットは1メートル進みます。</div>
<div>
Twistメッセージ(速度の指示)をパブリッシュしたら、必ず一定時間(ここでは1サイクル)スリープを入れるのを忘れないで下さい。</div>
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">96 # Stop the robot before the rotation
97 move_cmd = Twist()
98 self.cmd_vel.publish(move_cmd)
99 rospy.sleep(1)</span></span></pre>
直進移動が終わったあと、回転する前にロボットを一時停止します。</div>
<div>
停止した後に、1秒間スリープします。</div>
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">101 # Set the movement command to a rotation
102 move_cmd.angular.z = angular_speed
104 # Track the last angle measured
105 last_angle = rotation</span></span></pre>
回転速度を設定して、現在の姿勢を設定します。</div>
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">107 # Track how far we have turned
108 turn_angle = 0
109
110 while abs(turn_angle + angular_tolerance) < abs(goal_angle) and not rospy.is_shutdown():
111 # Publish the Twist message and sleep 1 cycle
112 self.cmd_vel.publish(move_cmd)
113 r.sleep()
114
115 # Get the current rotation
116 (position, rotation) = self.get_odom()
117
118 # Compute the amount of rotation since the last loop
119 delta_angle = normalize_angle(rotation - last_angle)
120
121 # Add to the running total
122 turn_angle += delta_angle
123 last_angle = rotation</span></span></pre>
オドメトリを監視しながら、ロボットが指定の姿勢(角度)になるまで回転させます。</div>
<div>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">125 # Stop the robot before the next leg
126 move_cmd = Twist()
127 self.cmd_vel.publish(move_cmd)
128 rospy.sleep(1)
129
130 # Stop the robot for good
131 self.cmd_vel.publish(Twist())</span></span></pre>
<span style="color: red;">ROS by Example本では64ページの’プログラムのリストの125行目から131行目までのインデントが間違っているので注意。</span></div>
<div>
<span style="color: red;">付録のサンプルプログラムは正しいのでちゃんと動きます。</span></div>
<div>
ここでは回転が終わったら次のlegの準備の為にロボットを静止させて、1秒間スリープします。</div>
<div>
さらに1st、2nd のleg が終わったらロボットを停止させます。</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-43928087513841862122014-12-13T17:00:00.000+09:002014-12-24T15:25:06.108+09:007.7 オドメトリを使って自己位置を知る移動ロボットが自由自在に動き回るには正確な自己位置を知ることが重要です。ロボットに装備された様々センサ(車輪の回転角度、画像、距離センサ、GPS…)を使い、自己位置を求める手法をオドメトリあるいはデッドレコニングと言います。<br />
<br />
ROSでは nav_msgs/Odometry という型のメッセージでオドメトリを表現しています。<br />
nav_msgs/Odometry 型の詳細は以下のコマンドで確認できます。<br />
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$rosmsg show nav_msgs/Odometry</pre>
<div class="p2">
<span class="s1">Header</span> <span class="s1">header</span><span class="s3"> </span></div>
<div class="p2">
<span class="s1"> uint32</span> <span class="s1">seq</span><span class="s3"> </span></div>
<div class="p2">
<span class="s1"> time</span> <span class="s1">stamp</span></div>
<div class="p3">
<span class="s1"> string</span> <span class="s1">frame_id</span><span class="s3"> </span></div>
<div class="p3">
<span class="s1">string</span> <span class="s1">child_frame_id</span></div>
<div class="p4">
<span class="s1">geometry_msgs/PoseWithCovariance</span> <span class="s1">pose</span><span class="s3"> </span></div>
<div class="p4">
<span class="s1"> geometry_msgs/Pose</span> <span class="s1">pose</span></div>
<div class="p5">
<span class="s1"> geometry_msgs/Point</span> <span class="s1">position</span><span class="s3"> </span></div>
<div class="p5">
<span class="s1"> float64</span> x</div>
<div class="p6">
<span class="s1"> float64</span> y<span class="s4"> </span></div>
<div class="p6">
<span class="s1"> float64</span> z</div>
<div class="p5">
<span class="s1"> geometry_msgs/Quaternion</span> <span class="s1">orientation</span><span class="s3"> </span></div>
<div class="p5">
<span class="s1"> float64</span> x</div>
<div class="p6">
<span class="s1"> float64</span> y<span class="s4"> </span></div>
<div class="p6">
<span class="s1"> float64</span> z<span class="s4"> </span></div>
<div class="p6">
<span class="s1"> float64</span> w</div>
<div class="p7">
<span class="s1"> float64[36]</span> <span class="s1">covariance</span><span class="s3"> </span></div>
<div class="p7">
<span class="s1">geometry_msgs/TwistWithCovariance</span> <span class="s1">twist</span></div>
<div class="p8">
<span class="s1"> geometry_msgs/Twist</span> <span class="s1">twist</span><span class="s3"> </span></div>
<div class="p8">
<span class="s1"> geometry_msgs/Vector3</span> <span class="s1">linear</span></div>
<div class="p9">
<span class="s1"> float64</span> x<span class="s4"> </span></div>
<div class="p9">
<span class="s1"> float64</span> y<span class="s4"> </span></div>
<div class="p9">
<span class="s1"> float64</span> z</div>
<div class="p5">
<span class="s1"> geometry_msgs/Vector3</span> <span class="s1">angular</span><span class="s3"> </span></div>
<div class="p5">
<span class="s1"> float64</span> x</div>
<div class="p6">
<span class="s1"> float64</span> y<span class="s4"> </span></div>
<div class="p6">
<span class="s1"> float64</span> z</div>
<div class="p10">
<span class="s1"> float64[36]</span> <span class="s1">covariance</span></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
ROSのナビゲーションに関数チュートリアルは以下のページを参照してください。日本語訳が進行中(?)です。</div>
<a href="http://wiki.ros.org/ja/navigation/Tutorials">http://wiki.ros.org/ja/navigation/Tutorials</a><br />
<div>
<br /></div>
<div>
<br /></div>
<div>
<div class="p2">
<br /></div>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-62853788742614548842014-12-11T15:11:00.000+09:002014-12-19T20:53:23.531+09:007.6.2 Pythonスクリプトでロボットを動かしてみる(シミュレーション編)<div class="p1">
</div>
<div class="p1">
<a href="https://github.com/pirobot/rbx1/blob/hydro-devel/rbx1_nav/nodes/timed_out_and_back.py">timed_out_and_back.py</a> を参考にPythonスクリプトでロボットを動かすプログラムを見てみましょう。<br />
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">1 #!/usr/bin/env python
2
3 import rospy</pre>
この2行はPythonスクリプトでROSプログラム書くときのお決まりです<br />
<div style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;">
<span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">4 from geometry_msgs.msg import Twist</span></span><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">5 from math import pi</span></span></div>
Twist型のメッセージを使います<br />
<pre style="border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">7 class OutAndBack():
</span></span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">8 def __init__(self):</span></span>
</pre>
OutAndBackクラスを作ります<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">9 # Give the node a name
10 rospy.init_node('out_and_back', anonymous=False)
11
12 # Set rospy to execute a shutdown function when exiting
13 rospy.on_shutdown(self.shutdown)</span></span></pre>
out_and_backノードを初期化します。<br />
スクリプトが終了するときに呼ばれるコールバックon_shutdown()を宣言します。例えば、CtrlCtrl+cキーが押された時に呼ばれます。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">15 # Publisher to control the robot's speed
16 self.cmd_vel = rospy.Publisher('/cmd_vel', Twist)
17
18 # How fast will we update the robot's movement?
19 rate = 50
20
21 # Set the equivalent ROS rate variable
22 r = rospy.Rate(rate)</span></span></pre>
/cmd_velトピックにTwist型の型のメッセージ(コマンド?)を送る宣言をします。</div>
<div class="p1">
一秒間に50回のタイミングでコマンドをアップデートします。</div>
<div class="p1">
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">24 # Set the forward linear speed to 0.2 meters per second
25 linear_speed = 0.2
26
27 # Set the travel distance to 1.0 meters
28 goal_distance = 1.0
29
30 # How long should it take us to get there?
31 linear_duration = linear_distance / linear_speed</span></span></pre>
ロボットの前進速度を秒速0.2メートルに設定します。</div>
<div class="p1">
ゴールまでの距離を1.0メートルに設定します。</div>
<div class="p1">
ゴールまでの到達時間を求めます。1.0/0.2=5秒<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333;">33 # Set the rotation speed to 1.0 radians per second
34 angular_speed = 1.0
35
36 # Set the rotation angle to Pi radians (180 degrees)
37 goal_angle = pi
38
39 # How long should it take to rotate?
40 angular_duration = </span><strike><span style="color: red;">angular_distance</span></strike><span style="color: #333333;"> / angular_speed
</span><b><span style="color: red;">この行は間違えなので、以下のように修正する。付属のスクリプトは正しい</span></b><span style="color: #333333;">
40 angular_duration = goal_angle / angular_speed</span></span></span></pre>
同じように、ロボットの回転角速度を毎秒1.0ラジアンに設定し、</div>
<div class="p1">
目標とする回転角度を180度(πラジアン)に設定すると、</div>
<div class="p1">
目標とする回転角度までの時間は pi (3.14159263) / 1.0 = 3.14秒<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">42 # Loop through the two legs of the trip
43 for i in range(2):
44 # Initialize the movement command
45 move_cmd = Twist()
46
47 # Set the forward speed
48 move_cmd.linear.x = linear_speed
49
50 # Move forward for a time to go the desired distance
51 ticks = int(linear_duration * rate)
52
53 for t in range(ticks):
54 self.cmd_vel.publish(move_cmd)
55 r.sleep()</span></span></pre>
このループで実際にロボット動かします。<b>一連の動きを2回繰り返します</b>。</div>
<div class="p1">
ロボットを1秒の間に、linear_speedの速度で、linear_distanceの距離だけ動かすために、1/rate 秒の間隔でTwist型のmove_cmd メッセージを出力し続けます。</div>
<div class="p1">
r.sleep()では非常に短い時間(1/rate)だけスリープします。1/rateという時間は、r=rospy.Rate(rate)で設定された値になります。</div>
<div class="p1">
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">57 # Stop the robot before the rotation
58 move_cmd = Twist()
59 self.cmd_vel.publish(move_cmd)
60 rospy.sleep(1)</pre>
ここではループの後半に入る前に、ロボットを一旦停止させ、スクリプトを1秒間停止させます。</div>
<div class="p1">
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;">62 # Now rotate left roughly 180 degrees
63
64 # Set the angular speed
65 move_cmd.angular.z = angular_speed
66
67 # Rotate for a time to go 180 degrees
68 ticks = int(goal_angle * rate)
69
70 for t in range(ticks):
71 self.cmd_vel.publish(move_cmd)
72 r.sleep()</pre>
ループの後半はロボットを回転させます。</div>
<div class="p1">
1秒間で180度回転します。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">74 # Stop the robot before the next leg
75 move_cmd = Twist()
76 self.cmd_vel.publish(move_cmd)
77 rospy.sleep(1)</span></span></pre>
2度めのループに入る前に、ロボットを一旦停止させ、スクリプトを1秒間停止させます。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">
</span></span></pre>
<div class="p1">
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">79 # Stop the robot.
80 self.cmd_vel.publish(Twist())</pre>
2度のループが終わったら、ロボットに空(すべてが0)のTwistメッセージ送る。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">82 def shutdown(self):
83 # Always stop the robot when shutting down the node.
84 rospy.loginfo("Stopping the robot...")
85 self.cmd_vel.publish(Twist())
86 rospy.sleep(1)</span></span></pre>
何らかの理由でシャットダウン(Ctrl+cが押された)が実行された時はこのコールバック関数が実行される。</div>
<div class="p1">
Tearminalウィンドウに”Stopping the robot..." が表示され、空のTwistメッセージが送られ、1秒間ループしたのちにスクリプトは終了する。</div>
<div class="p1">
<br /></div>
<div class="p1">
<b>さて、<a href="https://github.com/pirobot/rbx1/blob/hydro-devel/rbx1_nav/nodes/timed_out_and_back.py">timed_out_and_back.py</a>の動作をシミュレータで確認してみましょう。</b></div>
<div class="p1">
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$roslaunch rbx1_bringup fake_turtlebot.launch</pre>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rosrun rviz rviz -d `rospack find rbx1_nav`/sim.rviz</span></span></pre>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rosrun rbx1_nav timed_out_and_back.py</span></span></pre>
この3つのコマンドをそれぞれ別のTerminalウィンドウで実行して下さい。もう一つ別のウィンドウで $roscore を実行するのを忘れないでください。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRAgdN9s4PkwQ4xt54tnDjkUyb98U2DcPVfz-y8nX-eM10jrJYkk-SAB_hyCkUTkr1vJ3TA4upcYubJKym7n4cx1QstooKCZKfeMyTUU400Fo4K6GpGP6uxCW9VeW1h-55iPJebEgLubk/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-03+16.17.28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRAgdN9s4PkwQ4xt54tnDjkUyb98U2DcPVfz-y8nX-eM10jrJYkk-SAB_hyCkUTkr1vJ3TA4upcYubJKym7n4cx1QstooKCZKfeMyTUU400Fo4K6GpGP6uxCW9VeW1h-55iPJebEgLubk/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-11-03+16.17.28.png" height="216" width="320" /></a></div>
<div class="p1">
<br /></div>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-77135246711464300572014-12-10T20:22:00.000+09:002014-12-24T15:04:56.166+09:007.6 ROSノードからTwistメッセージを発信する7.6ではPythonスクリプトからTwistメッセージを/cmd_vel に配信することで、ロボットを動かしてみます。<br />
<br />
7.6.1 時間あるいは速度により移動距離や回転角度を指定する<br />
<b><span style="color: red;">「ロボットを1m動かしたかったら、0.1m毎秒の速度を10秒間配信する」</span></b>のようなプログラムを作成します。<br />
<br />
実際に1m正確に動くかどうかはロボットのオドメトリの精度に影響されます。<br />
このように、オドメトリだけでロボットを動かすのは、タイヤの滑りや障害物への衝突などの影響で正確な移動は望めません。<br />
しかし、プログラムは簡単なので入門編ではまずこの方法で動かしてみましょう。<br />
<br />岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-59553663892593057942014-12-09T20:17:00.000+09:002014-12-19T20:58:09.208+09:007.5 Twistメッセージを実機ロボットに送るTwistメッセージはロボットに移動速度を与えるメッセージであり、頻繁に使用されます。<br />
Terminal画面で以下のように実行すると詳細が表記されます。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$ rosmsg show geometry_msgs/Twist</pre>
<br />
6つのパラメータの前半3つは並進方向、後半3つは回転方向の速度を指示するように使い、<br />
それぞれ、x軸方向の並進速度、y軸方向の並進速度、z軸方向の並進速度、<br />
x軸回りの回転速度、y軸回りの回転速度、z軸回りの回転速度のように使います。<br />
<br />
以前の記事で、シミュレータ上のロボットを動かすために以下のようなコマンドを実行しました。<br />
この時使ったのがTwistメッセージです。<br />
以下のコマンドでは、秒速0.5ラジアンで回転しながら、秒速0.2mの速度で前に進んでいるはずです。<br />
$rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'<br />
<br />
ここでは実機ロボット(Kobuki)に直接、Twistメッセージを送り、Kobukiが移動するのを確認します。<br />
<br />
<b><span style="color: red;">記事に順番が逆になりますが、「7.10.1 キーボートを使った実機ロボットの操縦」を読んで、Kobukiのパッケージやドライバーをインストールしておいてください。</span></b><br />
<b><span style="color: red;"><br /></span></b>
<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$ roslaunch kobuki_node minimal.launch</pre>
Kobukiの制御ノードを立ち上げ、以下のようにTwistメッセージを送ります。<br />
<div>
<span style="background-color: #f3f5f7; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;"><br /></span></div>
<div>
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.5}}'</pre>
Kobukiを止めたい時は、Ctl+cキーを押して、以下のコマンドを入力してください。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rostopic pub -1 /cmd_vel geometry_msgs/Twist '{}'</span></span></pre>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-3017305355705803552014-12-08T19:20:00.000+09:002014-12-24T14:37:51.326+09:007.4 オドメトリのキャリブレーション実機ロボットのオドメトリをより正確なものにするために、キャリブレーションを行ないます。<br />
7.4.1 並進方向のキャリブレーションおよび7.4.2 回転方向のキャリブレーションを参考にキャリブレーション用のパラメータを求めたら、以下のように設定して下さい。<br />
<br />
床の材質によってキャリブレーションの値は大きく変化します。場所ごとにキャリブレーションを行って、以下のlaunchファイルを複数用意しておくのがいいでしょう。<br />
<br />
<h4>
TurtleBotの場合</h4>
turtlebot_carpet_create.launch を編集して、以下のように数値を変更して下さい。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333;"><launch>
<param name="/use_sim_time" value="false" />
<!-- Calibration parameters after calibration of an original Create TurtleBot on low-ply carpet -->
<param name="turtlebot_node/gyro_measurement_range" value="150"/>
<param name="turtlebot_node/gyro_scale_correction" value="1.43"/>
</span><span style="color: red;"><param name="turtlebot_node/odom_angular_scale_correction" value="1.0 "/>
<param name="turtlebot_node/odom_linear_scale_correction" value="0.955"/></span><span style="color: #333333;">
<include file="$(find rbx1_bringup)/launch/turtlebot_minimal_create.launch" />
</launch></span></span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
<br /></div>
以降は、キャリブレーション済みの launchファイルを使って下さい。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;">$ <span style="background-color: transparent; line-height: 18.5714302062988px;">roslaunch rbx1_bringup turtlebot_carpet_create.launch</span></pre>
<br />
<h4>
Kobukiの場合</h4>
turtlebot_carpet_create.launch をコピーして、turtlebot_carpet_kobuki.launch を作成し、以下のように変更して下さい。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333;"><launch>
<param name="/use_sim_time" value="false" />
<!-- Calibration parameters after calibration of an original Create TurtleBot on low-ply carpet -->
<param name="turtlebot_node/gyro_measurement_range" value="150"/>
<param name="turtlebot_node/gyro_scale_correction" value="1.43"/>
</span><span style="color: red;"><param name="turtlebot_node/odom_angular_scale_correction" value="1.0 "/>
<param name="turtlebot_node/odom_linear_scale_correction" value="0.955"/></span><span style="color: #333333;">
<include file="$(find rbx1_bringup)/launch/turtlebot_minimal_</span><span style="color: red;">kobuki</span><span style="color: #333333;">.launch" /></span></span></span><span style="color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; white-space: pre-wrap;">
</span></pre>
<div>
<br />
<br />
以降は、キャリブレーション済みの launchファイルを使って下さい。<br />
<pre style="background-color: #f3f5f7; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 1.428571429; white-space: pre-wrap;">$ </span></span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">roslaunch rbx1_bringup turtlebot_carpet_kobuki.launch</span></span></pre>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-10644344874128078332014-12-08T14:09:00.000+09:002014-12-24T14:34:52.851+09:007.3.2 RVizによるロボットの可視化RVizは強力な可視化ツールです。<br />
ここでは、シミュレータを使い、Twistメッセージによりロボットが動く様子を可視化してみます。<br />
<br />
シミュレータでTurtlebotを動かして<br />
<div class="line867" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-164" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-165" style="box-sizing: border-box;"></span></div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-1-29" style="box-sizing: border-box;"></span>$roslaunch rbx1_bringup fake_turtlebot.launch</pre>
別のターミナルウィンドウで、rvizを動かします。<br />
<div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rosrun rviz rviz -d `rospack find rbx1_nav`/sim.rviz</span></span></pre>
</div>
<div>
さらに別のターミナルウィンドウで以下のTwistメッセージを配信します<br />
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">$rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0, z: 0}, angular: {x: 0, y: 0, z: -0.5}}'</span></span></pre>
以下の図のように反時計方向に0.1ラジアン毎秒で回転しながら、0.1メートル毎秒で直進します。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLpP4uT26IXIXHO_Ik0OdSsg6l1rg8cd1FvCFx8T078HeRpJ2z8bTXctG8tSgTEzm_wTKh9bBXbMWBMUwSJYyrlhikt6qixzLxfNIWzp744cZXeq65R5l7m75jg61ZISMLjwKlUAKvu8s/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-24+14.30.04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLpP4uT26IXIXHO_Ik0OdSsg6l1rg8cd1FvCFx8T078HeRpJ2z8bTXctG8tSgTEzm_wTKh9bBXbMWBMUwSJYyrlhikt6qixzLxfNIWzp744cZXeq65R5l7m75jg61ZISMLjwKlUAKvu8s/s1600/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88+2014-12-24+14.30.04.png" height="237" width="320" /></a></div>
<div>
<br /></div>
<div>
<span style="color: red;">rostopic の -r 10 オプションは10Hz(毎秒10回)の間隔でTwistメッセージを /cmd_velに発行することを意味します。</span></div>
<div>
<span style="color: red;">ROSでは「安全第一の設計」がされていて、Twistメッセージを送り続けないとロボットは動きません。</span></div>
<div>
<br />
ロボットの動きを止めたい時は、以下のように空のTwistメッセージ発行してください。<br />
<h4 id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.A.2BMLMw.2FDDJieOKrA--1" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 10px;">
<div class="line867" style="box-sizing: border-box; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-164" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-165" style="box-sizing: border-box;"></span></div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-1-29" style="box-sizing: border-box;"></span>$rostopic pub -1 /cmd_vel geometry_msgs/Twist '{}'</pre>
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-166" style="box-sizing: border-box; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-167" style="box-sizing: border-box; font-size: 14px; line-height: 20px;"></span><div class="line867" style="box-sizing: border-box; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-168" style="box-sizing: border-box;"></span></div>
<div class="line867" style="box-sizing: border-box; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
</div>
</h4>
<h4 id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.A.2BMLMw.2FDDJieOKrA--1" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 10px;">
</h4>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-78710347411446869812014-12-07T20:19:00.000+09:002014-12-24T14:08:41.319+09:007.3 Twistメッセージによるロボットの移動ROSでは base controller へのモーションコマンドとして Twist型のメッセージを使います。<br />
頻繁に見かけるのは、以下の様な例です。<br />
<b>「”command velocities"と呼ばれる/cmd_vel ノードにTwistが型のメッセージを配信する」</b><br />
<br />
<br />
7.3.1 Twist型メッセージの例<br />
<div class="line874" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
以下のコマンドでTwist型メッセージの詳細が表示されます<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-163" style="box-sizing: border-box;"></span></div>
<div class="line867" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
<span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-164" style="box-sizing: border-box;"></span><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-165" style="box-sizing: border-box;"></span></div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span class="anchor" id="ja.2BAC8-rospy_tutorials.2BAC8-Tutorials.2BAC8-WritingPublisherSubscriber.line-1-29" style="box-sizing: border-box; line-height: 1.428571429; white-space: pre-wrap;"></span><span style="line-height: 1.428571429; white-space: pre-wrap;">$ </span></span><span style="background-color: transparent; line-height: 18.5714302062988px; white-space: pre-wrap;"><span style="color: #333333; font-family: courier, monospace;">rosmsg show geometry_msgs/Twist</span></span></pre>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; margin-bottom: 10px; padding: 5pt; word-break: break-all; word-wrap: break-word;"><span style="color: #333333; font-family: courier, monospace;"><span style="line-height: 18.5714302062988px; white-space: pre-wrap;">geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z</span></span></pre>
<div class="p2">
geometry_msgs/Twist 型は二つのサブメッセージから成り、それぞれ float64型が3つからなるベクター(配列)型です。</div>
<div class="p2">
geometry_msgs/Vector3 linear は並進方向の速度を意味し、それぞれ x, y, z 方向の速度をメートル毎秒で与えます。</div>
<div class="p2">
また、geometry_msgs/Vector3 angular は回転方向の速度を意味し、それぞれ x, y, z 軸回りの回転速度をラジアン毎秒で与えます。</div>
<div>
<br /></div>
<div class="p2">
例えば、ロボットを0.1メートル/秒で前進させたいときには、</div>
<div class="p2">
</div>
<h3>
<b>'{linear: {x: 0.1, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0}}'</b></h3>
<div class="p1">
<span style="color: red;">※ここで、サブメッセージ内の3つの値のデリミタは「コロン+スペース」なのを注意して下さい。</span></div>
<div class="p1">
<span style="color: red;">x: 0.1 (x + : + スペース+数値)です。:の後にスペースを忘れないように。</span></div>
<div class="p1">
<br /></div>
<div class="p2">
同様に、ロボットをその場で反時計方向に回転させるには以下のようにします。</div>
<h3>
<b>'{linear: {x: 0.0, y: 0, z: 0}, angular: {x: 0, y: 0, z: 0.1}}'</b></h3>
実際にROSのコマンドでロボットを移動させるには以下の様に入力します。<div>
<pre style="background-color: #f3f5f7; border-radius: 4px; border: 1pt solid rgb(174, 189, 204); box-sizing: border-box; color: #333333; font-family: courier, monospace; font-size: 13px; line-height: 1.428571429; margin-bottom: 10px; padding: 5pt; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><span class="anchor" id="line-1-8" style="box-sizing: border-box;"></span>$rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0, z: 0}, angular: {x: 0, y: 0, z: -0.5}}'</pre>
<span class="anchor" id="line-75" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><span class="anchor" id="line-76" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"></span><div class="line862" style="background-color: white; box-sizing: border-box; color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 10px;">
時計方向に0.5ラジアン毎秒で回転しながら、0.1メートル毎秒で移動します。</div>
</div>
<div>
<b><br /></b></div>
<div>
<b><br /></b></div>
<div>
<b><br /></b></div>
<br />岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0tag:blogger.com,1999:blog-3113926883534650980.post-68520954939230062422014-12-03T20:18:00.000+09:002014-12-24T13:48:54.208+09:007.2 移動制御の抽象化のレベル<b>7.2 モーションコントロール</b><br />
ROSでは<b><span style="color: red;">「与えらえたゴールに移動する」</span></b>というタスクに関して、モーターへの指示コマンド(抽象度が低い)から移動先のゴール(位置と姿勢)を与える(抽象度が高い)までを幾つかの抽象度に分解して実装しています。<br />
以下の節では、抽象度の低い順に紹介されています。<br />
<div>
<br /></div>
<div>
<b>7.2.1 モータ, 車輪, エンコーダ</b></div>
<div>
移動ロボットの制御においては、オドメトリ(内部センサによる移動量の推定)が重要になり、エンコーダから得られるモータの回転数だけでなく、加速度計などの移動量を測定できるセンサを使うこともあります。</div>
<div>
例えば、Turtlebotで使っているRoombaは2つのモータの回転数に加え、一軸のジャイロにより姿勢の推定精度を向上させています。</div>
<div>
<br /></div>
<b>7.2.2 モータのコントローラとドライバ</b><br />
移動ロボットの一番低レベルの制御は各モータのスピードを制御することです。<br />
車輪のモータで速度を決めだけで無く、ステアリングのモータを制御して進行方向を変えたり、パンチルト台のモータを制御してカメラが見ている方向を変えることなども含まれます。このレベルは個々のロボット毎に大きく異なります。<br />
モータの数や車輪の大きさはモータ毎に違うので、このレベルにおいてはロボット毎に異なるドライバを実装するのが普通です。<br />
<b><br /></b>
<b>7.2.3 ロボット台車の制御</b><br />
このレベルでは上位レベルから指示された通りに台車を制御することが要求されます。<br />
例えば、<b>「xxメータ/秒で動かす」「xxラジアン/秒で回転させる」</b>などをいかに正確に実現するかが求められます。<br />
指示された制御量にスムーズに追随するため、PD制御やPID制御と言われるドライバが実装されています。<br />
例えば、あなたのロボットが静止状態にあり、「0.5m/sec(秒速50㎝)で前に進め」という指示をしたいとします。<br />
その時、静止状態のロボットにいきなり0.5m/secの速度指定コマンドを送るのは現実的ではありません。急発進して、場合によっては倒れてしまうかもしれません。<br />
そこで、ROSのBase Controllerノードでは、PID制御のような手法を使って、「スムーズに」指定された速度になるまでロボットの速度コマンドを細分化します。<br />
例えば、以下のように一定時間間隔で徐々に速度を上げていきます。 <br />
0.0m/sec ->0.05m/sec -> 0.1m/sec -> 0.15m/sec ..... -> 0.5m/sec<br />
<br />
この<b> base controller ノード</b>と呼ばれるノードからは自己位置(オドメトリ)が /odom トピックとして配信され、/cmd_vel ノードでは上位レベルからの移動速度を待っています。<br />
<span style="background-color: white; color: #212121; font-family: inherit; font-size: 16px; line-height: 24px; white-space: pre-wrap;">同時に、コントローラノードは、一般的に(常にではないが</span><span style="background-color: white; color: #212121; font-family: inherit; font-size: 16px; line-height: 24px; white-space: pre-wrap;">)ベースフレーム(/ base_linkまたは/ base_footprintのいずれか)へ/odmを変換しています。</span><br />
<span style="background-color: white; color: #212121; font-family: inherit; font-size: 16px; line-height: 24px; white-space: pre-wrap;"><br /></span>
TurtleBotのようないくつかのロボットでは、ロボットの位置・姿勢のより正確な推定値を取得するために、車輪のオドメトリとジャイロデータを結合するrobot_pose_ekfパッケージを使用します。この場合には、robot_pose_ekfノードが/odom から/ base_footprintに変換しています。( robot_pose_ekfパッケージは拡張カルマンフィルタにより実装されています。)<br />
<br />
このように、<span style="color: red;"><b>自分のロボット専用の base controller ノード</b></span>を作ってしまえば、後は、上位レベルのプログラミングに専念することが出来ます。<br />
<br />
<b>7.2.4 move_base ROS パッケージによるFrame-Base Motion</b><br />
move_baseパッケージは目的地(一般的な移動ロボットでは移動先の位置・姿勢)を与えられたときに現在地から目的地まで、障害物を回避しながら経路を生成し、移動する機能を提供します。<br />
move_baseパッケージは、非常に洗練された経路計画であり、ロボットが移動するためのパスを選択する際に、ローカルおよびグローバルなコストマップの両方とオドメトリデータを組み合わせを利用します。<br />
<b>7.2.5 gmapping と amcl パッケージによるSLAM</b><br />
gmappingパッケージにより地図を作成します。一般に、SLAMで地図を作るにはレーザレンジファインのような正確な距離センサが必要ですが、Turtlebotに搭載のKinectやXtionでも十分な精度の地図を得ることが可能です。<br />
<br />
地図が作れたら、amcl (adaptive Monte Carlo localization) パッケージを使い正確な自己位置・姿勢を得ることができます。<b><br /></b>
<b>7.2.6 セマンティックゴール Semantic Goals</b><br />
抽象化の最上位のこのレベルでは、<br />
<b><span style="color: red;">「キッチンに行って、ビールを取ってきて」</span></b><br />
<div>
とか、もっと曖昧に<br />
<span style="color: red;"><b>「ビールを取ってきて」</b></span><br />
のように、実現してもらいたいGoalをロボットに指示します。<b><br /></b>
<b>7.2.7 まとめ</b><br />
<h2>
[Goal]<br />↓<br />[AMCL]<br />↓<br />[Path Planner]<br />↓<br />[move_base]<br />↓<br />[/cmd_vel + /odom]<br />↓<br />[Base Controller]<br />↓<br />[Motor Speeds]</h2>
<div class="p1">
<br /></div>
</div>
岡田 浩之http://www.blogger.com/profile/01159298843420657963noreply@blogger.com0