ROSの勉強 第12弾:センシングと移動


#プログラミング ROS< センシングと移動 >

はじめに

1つの参考書に沿って,ROS(Robot Operating System)を難なく扱えるようになることが目的である.その第12弾として,センシングと移動を扱う.

環境

仮想環境
ソフト VMware Workstation 15
実装RAM 2 GB
OS Ubuntu 64 ビット
isoファイル ubuntu-mate-20.04.1-desktop-amd64.iso
コンピュータ
デバイス MSI
プロセッサ Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz
実装RAM 8.00 GB (7.89 GB 使用可能)
OS Windows (Windows 10 Home, バージョン:1909)
ROS
Distribution noetic
プログラミング言語 Python 3.8.5
シミュレーション gazebo

タスク

前回と前々回でセンシングと移動について学んできた.今回はそれらを使って,あるタスクを通して組み合わせについて理解を深める.以下にそのタスクのフローチャートを示す.

距離の部分をセンサで計測し,それによる移動を行う.

実装

以下にソースコードを示す.なお,このプログラムを実行する際には,gazebo上でturtlebotを起動させた状態で行っている.

wanderbot.py
#! /usr/bin/env python3

import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan

def scan_callback(msg):
    """読み取ったセンサデータをグローバル変数に渡すことで,プログラム全体でその情報を扱えるようにする"""
    global g_range_ahead
    g_range_ahead = msg.ranges[len(msg.ranges)//2]  #正面の距離をグローバル変数に格納


g_range_ahead = 1   #初期値
scan_sub = rospy.Subscriber('scan', LaserScan, scan_callback)   #センサデータの購読
cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size = 1) #移動トピックの配信準備

rospy.init_node('wanderbot')    #ノードの初期化

state_change_time = rospy.Time.now()    #現在時刻を記録
driving_forward = True  #直進可能と仮定
rate = rospy.Rate(10)   #10Hz

#ctrlキーが押されるまでループ
while not rospy.is_shutdown():

    #直進可
    if driving_forward:
        #条件1と2を満たすか
        if (g_range_ahead < 0.8 or rospy.Time.now() > state_change_time):
            driving_forward = False #直進不可
            state_change_time = rospy.Time.now() + rospy.Duration(5)    #rosの基準で5duration先の時刻を現在時刻とする → 5durationの間回転を続けるということ

    #直進不可
    else:
        #方向転換が終了したか
        if rospy.Time.now() > state_change_time:
            driving_forward = True  #直進可能
            state_change_time = rospy.Time.now() + rospy.Duration(30)   #rosの基準で30duration先の時刻を現在時刻とする → 30durationの間直進を続けるということ


    twist = Twist() #全体を0で初期化するために毎回Twistインスタンスを生成    これにより,以下では動かしたい要素のみの変更で済む

    #直進可能 → 直線方向の速度1
    if driving_forward:
        twist.linear.x = -1

    #直進不可 → 方向転換 → 回転の速度(z軸周り)1
    else:
        twist.angular.z = 1

    cmd_vel_pub.publish(twist)  #移動トピックを配信

    rate.sleep()    #10Hz(=0.1秒)待つ

結果

結果としては,あちこち移動するようなロボットが完成した.その様子を以下に示す.

感想

前々回と前回で学んできたtwistによる移動とLaserScanを用いたセンシングをどのように組み合わせるかということをwanderbotを使って学んだ.特にセンシングにより読み取ったデータはグローバル変数に格納することで,条件にそのデータを用いたりすることができ,それにより条件付きの移動プログラムの実現が可能であることを確認できた.

参考文献

プログラミングROS Pythonによるロボットアプリケーション開発
        Morgan Quigley, Brian Gerkey, William D.Smart 著
                       河田 卓志 監訳
            松田 晃一,福地 正樹,由谷 哲夫 訳
                  オイラリー・ジャパン 発行