teaching_example.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3 
4 import rospy
5 import moveit_commander
6 from std_msgs.msg import UInt8
7 import sys, tty, termios, select
8 
9 
10 class TeachingDataBase(object):
11  def __init__(self):
12 
14  self._teaching_index = 0
15 
16  def save_joint_values(self, arm, gripper):
17  # アームの各関節角度と、グリッパー開閉角度を配列に保存する
18  self._teaching_joint_values.append([arm, gripper])
19 
20  def load_joint_values(self):
21  # 保存した角度情報を返す
22  # 配列のインデックスが末尾まで来たら、インデックスを0に戻す
23  # 何も保存していない場合はFalseを返す
24  if self._teaching_joint_values:
25  joint_values = self._teaching_joint_values[self._teaching_index]
26  self._teaching_index += 1
27 
28  if self._teaching_index >= len(self._teaching_joint_values):
29  self._teaching_index = 0
30  return joint_values
31  else:
32  rospy.logwarn("Joint Values is nothing")
33  return False
34 
36  # 保存した角度情報をすべて返す
37  # 何も保存していない場合はFalseを返す
38  if self._teaching_joint_values:
39  return self._teaching_joint_values
40  else:
41  rospy.logwarn("Joint Values is nothing")
42  return False
43 
45  # 角度情報が格納された配列を初期化する
46  self._teaching_joint_values = []
47  self._teaching_index = 0
48 
49  def get_current_index(self):
50  return self._teaching_index
51 
52  def get_num_of_poses(self):
53  return len(self._teaching_joint_values)
54 
55 
56 def getch(timeout):
57  # 1文字のキーボード入力を返す
58  fd = sys.stdin.fileno()
59  old = termios.tcgetattr(fd)
60  try:
61  tty.setraw(fd)
62  (result_stdin, w, x) = select.select([sys.stdin], [], [], timeout)
63  if len(result_stdin):
64  return result_stdin[0].read(1)
65  else:
66  return False
67 
68  # return sys.stdin.read(1)
69  finally:
70  termios.tcsetattr(fd, termios.TCSADRAIN, old)
71 
72 
73 def preset_pid_gain(pid_gain_no):
74  # サーボモータのPIDゲインをプリセットする
75  # プリセットの内容はcrane_x7_control/scripts/preset_reconfigure.pyに書かれている
76  rospy.loginfo("PID Gain Preset. No." + str(pid_gain_no))
77  preset_no = UInt8()
78  preset_no.data = pid_gain_no
79  pub_preset.publish(preset_no)
80  rospy.sleep(1) # PIDゲインがセットされるまで待つ
81 
82 
83 def main():
84  arm = moveit_commander.MoveGroupCommander("arm")
85  arm.set_max_velocity_scaling_factor(0.5)
86  arm.set_max_acceleration_scaling_factor(1.0)
87  gripper = moveit_commander.MoveGroupCommander("gripper")
88 
89  TORQUE_ON_PID = 0
90  TORQUE_OFF_PID = 3
91 
92  CTRL_C = 3 # Unicode Code
93 
94  input_code = 0
95  do_shutdown = False
96  do_restart = True
97  is_teaching_mode = True
98  do_loop_playing = False
99 
100  # 何かを掴んでいた時のためにハンドを開く
101  gripper.set_joint_value_target([0.9, 0.9])
102  gripper.go()
103 
104  # SRDFに定義されている"home"の姿勢にする
105  arm.set_named_target("home")
106  arm.go()
107 
108  # preset_reconfigureノードが起動するまで待機
109  rospy.sleep(1)
110 
111  # トルクをオフにする
112  preset_pid_gain(TORQUE_OFF_PID)
113  print("Torque OFF")
114 
115  while do_shutdown is False:
116  poses_num = data_base.get_num_of_poses()
117  pose_index = data_base.get_current_index() + 1 if poses_num else 0
118 
119  # リスタート時はキーボード入力の説明を表示
120  if do_restart:
121  print("")
122  if is_teaching_mode:
123  print("[Teaching Mode]"
124  + "[Next Pose:" + str(pose_index) + " of " + str(poses_num) + "]")
125  print("[q]: Quit, [m]: switch to action Mode, [s]: Save, [d]: Delete")
126  else:
127  print("[Action Mode]"
128  + "[Next Pose:" + str(pose_index) + " of " + str(poses_num) + "]")
129  print("[q]: Quit, [m]: switch to teaching Mode, [p]: Play 1 pose, [a]: play All pose, [l]: Loop play on/off")
130 
131  print("Keyboard input >>>")
132  do_restart = False
133 
134  # 文字入力
135  input_key = getch(0.1) # 一定時間入力がなければFalseを返す
136  input_code = ""
137  if input_key is not False:
138  print(input_key)
139  input_code = ord(input_key)
140 
141  # シャットダウン
142  if input_code == CTRL_C or input_code == ord('q') or input_code == ord('Q'):
143  print("Shutdown...")
144 
145  # トルクをONにしてから終了する
146  if is_teaching_mode:
147  print("Torque ON")
148  # PIDゲインをdefaultに戻すと、目標姿勢に向かって急に動き出す
149  # 安全のため、現在のアームの姿勢を目標姿勢に変更する
150  rospy.sleep(1)
151  arm.set_pose_target(arm.get_current_pose())
152  arm.go()
153  gripper.set_joint_value_target(gripper.get_current_joint_values())
154  gripper.go()
155  preset_pid_gain(TORQUE_ON_PID)
156 
157  do_shutdown = True
158  continue
159 
160  # モード切替
161  if input_code == ord('m') or input_code == ord('M'):
162  print("Mode switch")
163  is_teaching_mode = not is_teaching_mode
164 
165  if is_teaching_mode:
166  print("Torque OFF")
167  preset_pid_gain(TORQUE_OFF_PID)
168  else:
169  print("Torque ON")
170  # PIDゲインをdefaultに戻すと、目標姿勢に向かって急に動き出す
171  # 安全のため、現在のアームの姿勢を目標姿勢に変更する
172  rospy.sleep(1)
173  arm.set_pose_target(arm.get_current_pose())
174  arm.go()
175  gripper.set_joint_value_target(gripper.get_current_joint_values())
176  gripper.go()
177  preset_pid_gain(TORQUE_ON_PID)
178 
179  do_restart = True
180  continue
181 
182 
183  if is_teaching_mode:
184  # 現在のアーム姿勢、グリッパー角度を保存する
185  if input_code == ord('s') or input_code == ord('S'):
186  print("Save joint values")
187  # アームの角度が制御範囲内にない場合、例外が発生する
188  try:
189  arm_joint_values = arm.get_current_joint_values()
190  gripper_joint_values = gripper.get_current_joint_values()
191 
192  arm.set_joint_value_target(arm_joint_values)
193  gripper.set_joint_value_target(gripper_joint_values)
194  data_base.save_joint_values(arm_joint_values, gripper_joint_values)
196  print("Error setting joint target. Is the target within bounds?")
197 
198  do_restart = True
199  continue
200 
201  # 保存したアーム姿勢、グリッパー角度を削除する
202  if input_code == ord('d') or input_code == ord('D'):
203  print("\nDelete joint values")
204  data_base.delete_joint_values()
205  do_restart = True
206  continue
207 
208  else:
209  # 保存したアーム、グリッパー角度を取り出す
210  if input_code == ord('p') or input_code == ord('P'):
211  print("Play 1 pose")
212  joint_values = data_base.load_joint_values()
213  if joint_values:
214  arm.set_joint_value_target(joint_values[0])
215  arm.go()
216  gripper.set_joint_value_target(joint_values[1])
217  gripper.go()
218  do_restart = True
219  continue
220 
221  # 保存したアーム、グリッパー角度を連続再生する
222  if input_code == ord('a') or input_code == ord('A'):
223  print("play All poses")
224  all_joint_values = data_base.load_all_joint_values()
225  if all_joint_values:
226  for i, joint_values in enumerate(all_joint_values):
227  print("Play: " + str(i+1) + " of " + str(poses_num))
228  arm.set_joint_value_target(joint_values[0])
229  arm.go()
230  gripper.set_joint_value_target(joint_values[1])
231  gripper.go()
232  do_restart = True
233  continue
234 
235  # 保存したアーム、グリッパー角度をループ再生する
236  if input_code == ord('l') or input_code == ord('L'):
237  print("Loop play")
238 
239  do_loop_playing = not do_loop_playing
240 
241  if do_loop_playing:
242  print("ON")
243  else:
244  print("OFF")
245  # 再び再生しないようにsleepを設ける
246  rospy.sleep(1)
247  do_restart = True
248  continue
249 
250  # ループ再生
251  if do_loop_playing:
252  joint_values = data_base.load_joint_values()
253  if joint_values:
254  print("Play " + str(pose_index) + " of " + str(poses_num))
255 
256  arm.set_joint_value_target(joint_values[0])
257  arm.go()
258  gripper.set_joint_value_target(joint_values[1])
259  gripper.go()
260  else:
261  # 姿勢が保存されていなかったらループ再生を終了する
262  print("Loop play OFF")
263  do_loop_playing = False
264  do_restart = True
265  continue
266 
267 
268  # SRDFに定義されている"vertical"の姿勢にする
269  arm.set_named_target("vertical")
270  arm.go()
271 
272 
273 if __name__ == '__main__':
274  rospy.init_node("teaching_example")
275 
276  data_base = TeachingDataBase()
277 
278  # PIDゲインプリセット用のPublisher
279  pub_preset = rospy.Publisher("preset_gain_no", UInt8, queue_size=1)
280 
281  try:
282  if not rospy.is_shutdown():
283  main()
284  except rospy.ROSInterruptException:
285  pass
def preset_pid_gain(pid_gain_no)
def save_joint_values(self, arm, gripper)
def getch(timeout)


crane_x7_examples
Author(s): Daisuke Sato , Hiroyuki Nomura
autogenerated on Mon Mar 1 2021 03:18:34