ROSのRvizにwaypointを表示させる方法(Python)

概要

rvizのGUIで指定したウェイポイント通りにロボットを自律走行させる(Python,ROS) - 技術メモ集にて、ウェイポイントを保存し、その順番通りにロボットを自律走行させる方法を記載した。
しかし、実際に自律走行させてみると、ウェイポイントを追加したり、ウェイポイントの位置をずらしたり・・・と、ウェイポイントの中身を弄りたくなる。
その際に、座標の羅列だけではどう変更してよいかわからないため、
・ ウェイポイントの座標と番号をrviz上に表示
・ 2D Nav Goalで指定した座標をターミナル上に表示
する機能を持つスクリプトを作成した。
座標番号と位置がひと目でわかるだけでも、かなりデバッグが楽になる。

#本当はGUIでウェイポイントを修正できるようにしたかったが、実装に時間がかかりそうだったので、修正はCSVファイル上からて入力で数値を入れることとした。

地図情報の保存

前提として、ウェイポイントファイルを以下の通り記述し、スクリプトと同じフォルダに置くこととする。(ファイル名waypoint.csv)
フォーマットやファイル名を変更したければ、スクリプトを適宜修正のこと。

ウェイポイントファイル詳細

・ numは0から始まるウェイポイント番号
・ xyzはウェイポイントの座標
・ q1,q2,q3,q4はクォータニオンで示されるロボットの方位

num,x,y,z,q1,q2,q3,q4
0,229.966918945,115.991737366,0,0,0,0.9987130731,-0.0507168376
1,178.294799805,118.079750061,0,0,0,0.9998951068,0.0144836224
2,133.862442017,119.17339325,0,0,0,0.9999969209,0.0024815768

ウェイポイント描画スクリプトの実行方法と、Rvizへの表示画面

スクリプトは最後に記載することとして、ここでは使い方と結果を示す。

まず、Map Server、Rvizと、本スクリプトを起動する。
次に、Rvizの画面から
Add→By topic→Waypoint→Markerをクリックする。
すると、以下の通りRviz上に地図と、矢印、ウェイポイント番号が表示される。

# ウェイポイントが重なると見難いが、心の目で見るしかない・・・。

f:id:t_nkb:20180428094047p:plain

また、この状態で2D Nav Goalを指定すると、以下のようにターミナル上に座標が表示されるので、この数値を元にcsvファイルを編集することで、ウェイポイントファイルと適宜修正できる。

f:id:t_nkb:20180428092648p:plain


スクリプト

スクリプトとしてはシンプルで、Marker型で矢印と数字をPublishしているだけ。
矢印等の描画方法は以下を参考のこと。

www.robotech-note.com

import rospy
import csv
from visualization_msgs.msg import Marker
from move_base_msgs.msg import MoveBaseActionGoal

def callback(data):
    pos = data.goal.target_pose.pose
    print "{0},{1},0.0,0.0,0.0,{2},{3},".format(pos.position.x,pos.position.y,pos.orientation.z,pos.orientation.w)


rospy.init_node("waypoint_manager")

pub = rospy.Publisher("waypoint", Marker, queue_size = 10)
rospy.Subscriber("/move_base/goal", MoveBaseActionGoal, callback)

rate = rospy.Rate(25)


while not rospy.is_shutdown():
    with open('waypoint.csv', 'r') as f:
        counter = 0
        reader = csv.reader(f)
        header = next(reader)

        for row in reader:
            # Mark arrow
            marker_data = Marker()
            marker_data.header.frame_id = "map"
            marker_data.header.stamp = rospy.Time.now()

            marker_data.ns = "basic_shapes"
            marker_data.id = counter

            marker_data.action = Marker.ADD

            marker_data.pose.position.x = map(float,row)[1]
            marker_data.pose.position.y = map(float,row)[2]
            marker_data.pose.position.z = map(float,row)[3]

            marker_data.pose.orientation.x=map(float,row)[4]
            marker_data.pose.orientation.y=map(float,row)[5]
            marker_data.pose.orientation.z=map(float,row)[6]
            marker_data.pose.orientation.w=map(float,row)[7]

            marker_data.color.r = 1.0
            marker_data.color.g = 0.0
            marker_data.color.b = 0.0
            marker_data.color.a = 1.0
            marker_data.scale.x = 5
            marker_data.scale.y = 1
            marker_data.scale.z = 1

            marker_data.lifetime = rospy.Duration()

            marker_data.type = 0

            pub.publish(marker_data)
            counter +=1


            # Mark num
            marker_data = Marker()
            marker_data.header.frame_id = "map"
            marker_data.header.stamp = rospy.Time.now()

            marker_data.ns = "basic_shapes"
            marker_data.id = counter

            marker_data.action = Marker.ADD

            marker_data.pose.position.x = map(float,row)[1]
            marker_data.pose.position.y = map(float,row)[2]
            marker_data.pose.position.z = map(float,row)[3]

            marker_data.pose.orientation.x=map(float,row)[4]
            marker_data.pose.orientation.y=map(float,row)[5]
            marker_data.pose.orientation.z=map(float,row)[6]
            marker_data.pose.orientation.w=map(float,row)[7]

            marker_data.color.r = 0.0
            marker_data.color.g = 0.0
            marker_data.color.b = 0.0
            marker_data.color.a = 1.0
            marker_data.scale.x = 5
            marker_data.scale.y = 5
            marker_data.scale.z = 5

            marker_data.lifetime = rospy.Duration()

            marker_data.type = Marker.TEXT_VIEW_FACING
            marker_data.text = str(int(map(float,row)[0]))

            pub.publish(marker_data)
            counter +=1

    rate.sleep()

rospy.spin()