ROS入門 (37) - MoveItのPythonインターフェイスの利用
「MoveIt」のPythonインターフェイスの利用方法をまとめました。
前回
1. 開発環境の準備
「ROS入門 (35) - MoveItのセットアップ」と同様です。
2. rvizとMoveItの起動
ロボットアームの動作確認のため、rvizとMoveItを起動します。
$ roslaunch panda_moveit_config demo.launch
3. ロボット情報の出力
ロボット情報を出力を行う手順は、次のとおりです。
(1) 「~/catkin_ws/src/moveit_tutorials/src/robot_info.py」を作成し、以下のように編集し、実行権限を付加(chmod u+x <ファイル名>)。
・robot_info.py
#!/usr/bin/env python
# coding: UTF-8
import sys
import moveit_commander
import rospy
# メイン
def main():
# MoveitCommanderの初期化
moveit_commander.roscpp_initialize(sys.argv)
# ノードの初期化
rospy.init_node('robot_info')
# RobotCommanderのインスタンス化
robot = moveit_commander.RobotCommander()
# ロボット情報
print "==Robot Info=="
print "[ group_names ]", robot.get_group_names()
print "[ current_state ] ", robot.get_current_state()
print ""
# MoveGroupCommanderのインスタンス化
move_group = moveit_commander.MoveGroupCommander("panda_arm")
# グループ情報
print "==Group Info=="
print "[ name ] ", move_group.get_name()
print "[ planning_frame ] ", move_group.get_planning_frame()
print "[ interface_description ] ", move_group.get_interface_description()
print ""
# ジョイント情報
print "==Joint Info=="
print "[ active_joints ] ", move_group.get_active_joints()
print "[ joints ] ", move_group.get_joints()
print "[ current_joint_values ] ", move_group.get_current_joint_values()
print ""
# エンドエフェクタ情報
print "==EndEffector Info=="
print "[ has_end_effector_link ] ", move_group.has_end_effector_link()
print "[ end_effector_link ] ", move_group.get_end_effector_link()
print "[ current_pose ] ", move_group.get_current_pose()
print "[ current_rpy ] ", move_group.get_current_rpy()
print ""
if __name__ == "__main__":
main()
「MoveitCommander」には、以下の2つのインタフェースがあります。
「RobotCommander」の主な情報取得メソッドは、次のとおりです。
「MoveGroupCommander」の主な情報取得メソッドは、次のとおりです。
(2) 実行。
$ rosrun moveit_tutorials robot_info.py
[ INFO] [1640325462.543879400]: Loading robot model 'panda'...
==Robot Info==
[ group_names ] ['hand', 'panda_arm', 'panda_arm_hand']
[ WARN] [1640325462.860356000]: Unable to update multi-DOF joint 'virtual_joint': Failure to lookup transform between 'world' and 'panda_link0' with TF exception: "world" passed to lookupTransform argument target_frame does not exist.
[ current_state ] joint_state:
header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: "world"
name: [panda_joint1, panda_joint2, panda_joint3, panda_joint4, panda_joint5, panda_joint6,
panda_joint7, panda_finger_joint1, panda_finger_joint2]
position: [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785, 0.035, 0.035]
velocity: []
effort: []
multi_dof_joint_state:
header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: "world"
joint_names: [virtual_joint]
transforms:
-
translation:
x: 0.0
y: 0.0
z: 0.0
rotation:
x: 0.0
y: 0.0
z: 0.0
w: 1.0
twist: []
wrench: []
attached_collision_objects: []
is_diff: False
[ INFO] [1640325463.960647000]: Ready to take commands for planning group panda_arm.
==Group Info==
[ name ] panda_arm
[ planning_frame ] world
[ interface_description ] name: "OMPL"
planner_ids: [hand, 'hand[BFMTkConfigDefault]', 'hand[BKPIECEkConfigDefault]', 'hand[BiESTkConfigDefault]',
'hand[BiTRRTkConfigDefault]', 'hand[ESTkConfigDefault]', 'hand[FMTkConfigDefault]',
'hand[KPIECEkConfigDefault]', 'hand[LBKPIECEkConfigDefault]', 'hand[LBTRRTkConfigDefault]',
'hand[LazyPRMkConfigDefault]', 'hand[LazyPRMstarkConfigDefault]', 'hand[PDSTkConfigDefault]',
'hand[PRMkConfigDefault]', 'hand[PRMstarkConfigDefault]', 'hand[ProjESTkConfigDefault]',
'hand[RRTConnectkConfigDefault]', 'hand[RRTkConfigDefault]', 'hand[RRTstarkConfigDefault]',
'hand[SBLkConfigDefault]', 'hand[SPARSkConfigDefault]', 'hand[SPARStwokConfigDefault]',
'hand[STRIDEkConfigDefault]', 'hand[TRRTkConfigDefault]', 'hand[TrajOptDefault]',
panda_arm, 'panda_arm[BFMTkConfigDefault]', 'panda_arm[BKPIECEkConfigDefault]',
'panda_arm[BiESTkConfigDefault]', 'panda_arm[BiTRRTkConfigDefault]', 'panda_arm[ESTkConfigDefault]',
'panda_arm[FMTkConfigDefault]', 'panda_arm[KPIECEkConfigDefault]', 'panda_arm[LBKPIECEkConfigDefault]',
'panda_arm[LBTRRTkConfigDefault]', 'panda_arm[LazyPRMkConfigDefault]', 'panda_arm[LazyPRMstarkConfigDefault]',
'panda_arm[PDSTkConfigDefault]', 'panda_arm[PRMkConfigDefault]', 'panda_arm[PRMstarkConfigDefault]',
'panda_arm[ProjESTkConfigDefault]', 'panda_arm[RRTConnectkConfigDefault]', 'panda_arm[RRTkConfigDefault]',
'panda_arm[RRTstarkConfigDefault]', 'panda_arm[SBLkConfigDefault]', 'panda_arm[SPARSkConfigDefault]',
'panda_arm[SPARStwokConfigDefault]', 'panda_arm[STRIDEkConfigDefault]', 'panda_arm[TRRTkConfigDefault]',
'panda_arm[TrajOptDefault]', panda_arm_hand, 'panda_arm_hand[BFMTkConfigDefault]',
'panda_arm_hand[BKPIECEkConfigDefault]', 'panda_arm_hand[BiESTkConfigDefault]',
'panda_arm_hand[BiTRRTkConfigDefault]', 'panda_arm_hand[ESTkConfigDefault]', 'panda_arm_hand[FMTkConfigDefault]',
'panda_arm_hand[KPIECEkConfigDefault]', 'panda_arm_hand[LBKPIECEkConfigDefault]',
'panda_arm_hand[LBTRRTkConfigDefault]', 'panda_arm_hand[LazyPRMkConfigDefault]',
'panda_arm_hand[LazyPRMstarkConfigDefault]', 'panda_arm_hand[PDSTkConfigDefault]',
'panda_arm_hand[PRMkConfigDefault]', 'panda_arm_hand[PRMstarkConfigDefault]', 'panda_arm_hand[ProjESTkConfigDefault]',
'panda_arm_hand[RRTConnectkConfigDefault]', 'panda_arm_hand[RRTkConfigDefault]',
'panda_arm_hand[RRTstarkConfigDefault]', 'panda_arm_hand[SBLkConfigDefault]', 'panda_arm_hand[SPARSkConfigDefault]',
'panda_arm_hand[SPARStwokConfigDefault]', 'panda_arm_hand[STRIDEkConfigDefault]',
'panda_arm_hand[TRRTkConfigDefault]', 'panda_arm_hand[TrajOptDefault]']
==Joint Info==
[ active_joints ] ['panda_joint1', 'panda_joint2', 'panda_joint3', 'panda_joint4', 'panda_joint5', 'panda_joint6', 'panda_joint7']
[ joints ] ['panda_joint1', 'panda_joint2', 'panda_joint3', 'panda_joint4', 'panda_joint5', 'panda_joint6', 'panda_joint7', 'panda_joint8']
[ current_joint_values ] [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
==EndEffector Info==
[ has_end_effector_link ] True
[ end_effector_link ] panda_link8
[ current_pose ] header:
seq: 0
stamp:
secs: 1640325464
nsecs: 125233888
frame_id: "world"
pose:
position:
x: 0.307019570052
y: -5.22132961561e-12
z: 0.590269558277
orientation:
x: 0.923955699469
y: -0.382499497279
z: 1.3249325839e-12
w: 3.20041176635e-12
[ current_rpy ] [3.1415926535848926, -4.896669808048392e-12, -0.785000000006922]
4. 関節の角度によるモーションプランニング
関節の角度によるモーションプランニングの手順は、次のとおりです。
(1) 「~/catkin_ws/src/moveit_tutorials/src/joint_planner.py」を作成し、以下のように編集し、実行権限を付加(chmod u+x <ファイル名>)。
・joint_planner.py
#!/usr/bin/env python
# coding: UTF-8
import sys
from math import pi
import moveit_commander
import rospy
def main():
# MoveitCommanderの初期化
moveit_commander.roscpp_initialize(sys.argv)
# ノードの生成
rospy.init_node("joint_planner")
# MoveGroupCommanderの準備
move_group = moveit_commander.MoveGroupCommander("panda_arm")
# 関節の角度でゴール状態を指定
joint_goal = [0, -20 * pi / 180, 0, -30 * pi / 180, 0, 160 * pi / 180, 0]
move_group.set_joint_value_target(joint_goal)
# モーションプランの計画と実行
move_group.go(wait=True)
# 後処理
move_group.stop()
if __name__ == "__main__":
main()
関節の角度によるモーションプランニングで使う主なメソッドは、次のとおりです。
(2) 実行。
$ rosrun moveit_tutorials joint_planner.py
5. エンドエフェクタの姿勢によるモーションプランニング
エンドエフェクタの姿勢によるモーションプランニングの手順は、次のとおりです。
(1) 「~/catkin_ws/src/moveit_tutorials/src/pose_planner.py」を作成し、以下のように編集し、実行権限を付加(chmod u+x <ファイル名>)。
・pose_planner.py
#!/usr/bin/env python
# coding: UTF-8
import sys
import geometry_msgs.msg
import moveit_commander
import rospy
import tf
from geometry_msgs.msg import Quaternion, Vector3
def main():
# MoveitCommanderの初期化
moveit_commander.roscpp_initialize(sys.argv)
# ノードの生成
rospy.init_node("pose_planner")
# MoveGroupCommanderの準備
move_group = moveit_commander.MoveGroupCommander("panda_arm")
# エンドポイントの姿勢でゴール状態を指定
pose_goal = geometry_msgs.msg.Pose()
pose_goal.position = Vector3(0.7, 0.0, 0.7)
q = tf.transformations.quaternion_from_euler(0, 0, 0)
pose_goal.orientation = Quaternion(x=q[0], y=q[1], z=q[2], w=q[3])
move_group.set_pose_target(pose_goal)
# モーションプランの計画と実行
move_group.go(wait=True)
# 後処理
move_group.stop()
move_group.clear_pose_targets()
if __name__ == "__main__":
main()
エンドエフェクタの姿勢によるモーションプランニングで使う主なメソッドは、次のとおりです。
(2) 実行。
$ rosrun moveit_tutorials pose_planner.py
6. モーションプランが見つからない場合の対処
モーションプランが見つからないと、以下のメッセージが表示されます。
ABORTED: No motion plan found. No execution attempted.
主な原因と対処方法は、次のとおりです。
◎ ゴールに到達可能だが、ゴール近くの関節設定を見つけることができなかった。
(1) 到達可能なゴールであるかを確認。
(2) ゴールの許容誤差をあまくする。
(3) 異なるIKまたはパラメータを使用。
◎ ゴールまでのパスを見つけることができなかった。
(1) 移動可能なパスが存在するかを確認。
(2) 別のプランナーを試す。
(3) プランニング時間を増やす。
この対応で使う主なメソッドは、次のとおりです。
◎ 近似解の指定
・move_group.set_joint_value_target(arg1, arg2, arg3) : arg2以降にTrueで近似解を許可。
◎ ゴール状態の許容誤差の指定
・move_gorup.set_goal_tolerance(value) : 関節の角度と、エンドエフェクタの位置と向きの許容誤差の指定。
・move_group.set_goal_joint_tolerance(value) : 関節の角度の許容誤差の指定。
・move_group.set_goal_position_tolerance(value) : エンドエフェクタの位置の許容誤差の指定。
・move_group.set_goal_orientation_tolerance(value) : エンドエフェクタの向きの許容誤差の指定。
◎ プランナーIDの指定
・move_group.set_planner_id(planner_id) : プランナーIDの指定。(RRTConnectkConfigDefaultなど)
・move_gruop.get_planner_id() : プランナーIDの取得。
◎ プランニング時間の指定
・move_group.set_planning_time(sec) : プランニング時間の指定。
・move_group.get_planning_time() : プランニング時間の取得。
◎ ROSパラメータの指定
Unity Robotics Hubのサンプルで使われている設定になります。
<param name="/move_group/trajectory_execution/execution_duration_monitoring" value="false" />
<param name="/move_group/trajectory_execution/allowed_start_tolerance" value="0.0" />
<param name="/move_group/planning_pipelines/ompl/start_state_max_bounds_error" value="0.3" />
7. 参考
次回
この記事が気に入ったらサポートをしてみませんか?