acceptancetest_hironx.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 
3 # Software License Agreement (BSD License)
4 #
5 # Copyright (c) 2014, TORK (Tokyo Opensource Robotics Kyokai Association)
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 #
12 # * Redistributions of source code must retain the above copyright
13 # notice, this list of conditions and the following disclaimer.
14 # * Redistributions in binary form must reproduce the above
15 # copyright notice, this list of conditions and the following
16 # disclaimer in the documentation and/or other materials provided
17 # with the distribution.
18 # * Neither the name of TORK. nor the
19 # names of its contributors may be used to endorse or promote products
20 # derived from this software without specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 # POSSIBILITY OF SUCH DAMAGE.
34 
35 import time, rospy
36 
37 from hironx_ros_bridge.constant import Constant
38 from hironx_ros_bridge.hironx_client import HIRONX
39 from hironx_ros_bridge.ros_client import ROS_Client
40 from hironx_ros_bridge.testutil.abst_acceptancetest import AbstAcceptanceTest
41 from hironx_ros_bridge.testutil.acceptancetest_ros import AcceptanceTestROS
42 from hironx_ros_bridge.testutil.acceptancetest_rtm import AcceptanceTestRTM
43 
44 
46  '''
47  This class holds methods that can be used for verification of the robot
48  Kawada Industries' dual-arm robot Hiro (and the same model of other robots
49  e.g. NEXTAGE OPEN).
50 
51  This test class is:
52  - Intended to be run as nosetests, ie. roscore isn't available by itself.
53  - Almost all the testcases don't run without an access to a robot running.
54 
55  Above said, combined with a rostest that launches roscore and robot (either
56  simulation or real) hopefully these testcases can be run, both in batch
57  manner by rostest and in nosetest manner.
58 
59  Prefix for methods 'at' means 'acceptance test'.
60 
61  All time arguments are second.
62  '''
63 
64  _POSITIONS_LARM_DEG_UP = [-4.697, -2.012, -117.108, -17.180, 29.146, -3.739]
65  _POSITIONS_LARM_DEG_DOWN = [6.196, -5.311, -73.086, -15.287, -12.906, -2.957]
66  _POSITIONS_RARM_DEG_DOWN = [-4.949, -3.372, -80.050, 15.067, -7.734, 3.086]
67  _POSITIONS_LARM_DEG_UP_SYNC = [-4.695, -2.009, -117.103, -17.178, 29.138, -3.738]
68  _POSITIONS_RARM_DEG_UP_SYNC = [4.695, -2.009, -117.103, 17.178, 29.138, 3.738]
69  _ROTATION_ANGLES_HEAD_1 = [[0.1, 0.0], [50.0, 10.0]]
70  _ROTATION_ANGLES_HEAD_2 = [[50, 10], [-50, -10], [0, 0]]
71  _POSITIONS_TORSO_DEG = [[130.0], [-130.0]]
72  _R_Z_SMALLINCREMENT = 0.0001
73  # Workspace; X near, Y far
74  _POS_L_X_NEAR_Y_FAR = [0.326, 0.474, 1.038]
75  _RPY_L_X_NEAR_Y_FAR = (-3.075, -1.569, 3.074)
76  _POS_R_X_NEAR_Y_FAR = [0.326, -0.472, 1.048]
77  _RPY_R_X_NEAR_Y_FAR = (3.073, -1.569, -3.072)
78  # Workspace; X far, Y far
79  _POS_L_X_FAR_Y_FAR = [0.47548142379781055, 0.17430276793604782, 1.0376878025614884]
80  _RPY_L_X_FAR_Y_FAR = (-3.075954857224205, -1.5690261926181046, 3.0757659493049574)
81  _POS_R_X_FAR_Y_FAR = [0.4755337947019357, -0.17242322190721648, 1.0476395479774052]
82  _RPY_R_X_FAR_Y_FAR = (3.0715850722714944, -1.5690204449882248, -3.071395243174742)
83 
84  _TASK_DURATION_DEFAULT = 5.0
85  _DURATION_EACH_SMALLINCREMENT = 0.1
86  _TASK_DURATION_TORSO = 4.0
87  _TASK_DURATION_HEAD = 2.5
88 
89  _DURATON_TOTAL_SMALLINCREMENT = 30 # Second.
90 
91  def __init__(self, rtm_robotname='HiroNX(Robot)0', url=''):
92  '''
93  Initiate both ROS and RTM robot clients, keep them public so that they
94  are callable from script. e.g. On ipython,
95 
96  In [1]: acceptance.ros.go_init()
97  In [2]: acceptance.rtm.goOffPose()
98  '''
99  self._rtm_robotname = rtm_robotname
100  self._rtm_url = url
101 
102  # Init RTM and ROS client.
103  self.ros = ROS_Client()
105  if rospy.has_param('/gazebo'):
106  print("\033[32m[INFO] Assming Gazebo Siulator, so do not connect to CORBA systmes\033[0m")
107  print("\033[32m[INFO] run 'acceptance.run_tests_ros()' for ROS interface test\033[0m")
108  else:
109  self.rtm = HIRONX()
110  self.rtm.init(robotname=self._rtm_robotname, url=self._rtm_url)
112  print("\033[32m[INFO] run 'acceptance.run_tests_rtm()' for RTM interface test\033[0m")
113 
114  def _wait_input(self, msg, do_wait_input=False):
115  '''
116  @type msg: str
117  @param msg: To be printed on prompt.
118  @param do_wait_input: If True python commandline waits for any input
119  to proceed.
120  '''
121  if msg:
122  msg = '\n' + msg + '= '
123  if do_wait_input:
124  try:
125  input('Waiting for any key. **Do NOT** hit enter multiple ' +
126  'times. ' + msg)
127  except NameError:
128  # On python < 3, `input` can cause errors like following with
129  # any input string. So here just catch-release it.
130  # e.g.
131  # NameError: name 'next' is not defined
132  pass
133 
134  def run_tests_rtm(self, do_wait_input=False):
135  '''
136  @param do_wait_input: If True, the user will be asked to hit any key
137  before each task to proceed.
138  '''
139  self._run_tests(self._acceptance_rtm_client, do_wait_input)
140 
141  def run_tests_ros(self, do_wait_input=False):
142  '''
143  Run by ROS exactly the same actions that run_tests_rtm performs.
144 
145  @param do_wait_input: If True, the user will be asked to hit any key
146  before each task to proceed.
147  '''
148  self._run_tests(self._acceptance_ros_client, do_wait_input)
149 
150  def _run_tests(self, test_client, do_wait_input=False):
151  '''
152  @type test_client: hironx_ros_robotics.abst_acceptancetest.AbstAcceptanceTest
153  '''
154 
155  _task_msgs = ['TASK-1-1. Move each arm separately to the given pose by passing joint space.',
156  'TASK-1-2. Move each arm separately to the given pose by specifying a pose.',
157  'TASK-2. Move both arms at the same time using relative distance and angle from the current pose.',
158  'TASK-3. Move arm with very small increment (0.1mm/sec).\n\tRight hand 3 cm upward over 30 seconds.',
159  'In the beginning you\'ll see the displacement of the previous task.' +
160  '\nTASK-4. Move head using Joint angles in degree.',
161  'TASK-5. Rotate torso to the left and right 130 degree.',
162  'TASK-6. Overwrite ongoing action.' +
163  '\n\t6-1. While rotating torso toward left, it gets canceled and rotate toward right.' +
164  '\n\t6-2. While lifting left hand, right hand also tries to reach the same height that gets cancelled so that it stays lower than the left hand.',
165  'TASK-7. Show the capable workspace on front side of the robot.']
166 
167  _msg_type_client = None
168  if isinstance(test_client, AcceptanceTestROS):
169  _msg_type_client = '(ROS) '
170  elif isinstance(test_client, AcceptanceTestRTM):
171  _msg_type_client = '(RTM) '
172 
173  test_client.go_initpos()
174 
175  msg_task = _task_msgs[0]
176  msg = _msg_type_client + msg_task
177  self._wait_input(msg, do_wait_input)
178  self._move_armbyarm_jointangles(test_client)
179 
180  msg_task = _task_msgs[1]
181  msg = _msg_type_client + msg_task
182  self._wait_input(msg, do_wait_input)
183  self._move_armbyarm_pose(test_client)
184 
185  msg_task = _task_msgs[2]
186  msg = _msg_type_client + msg_task
187  self._wait_input(msg, do_wait_input)
188  self._movearms_together(test_client)
189 
190  msg_task = _task_msgs[3]
191  msg = _msg_type_client + msg_task
192  self._wait_input(msg, do_wait_input)
193  self._set_pose_relative(test_client)
194 
195  msg_task = _task_msgs[4]
196  msg = _msg_type_client + msg_task
197  self._wait_input(msg, do_wait_input)
198  self._move_head(test_client)
199 
200  msg_task = _task_msgs[5]
201  msg = _msg_type_client + msg_task
202  self._wait_input(msg, do_wait_input)
203  self._move_torso(test_client)
204 
205  msg_task = _task_msgs[6]
206  msg = _msg_type_client + msg_task
207  self._wait_input(msg, do_wait_input)
208  self._overwrite_torso(test_client)
209  self._overwrite_arm(test_client)
210 
211  msg_task = _task_msgs[7]
212  msg = _msg_type_client + msg_task
213  self._wait_input(msg, do_wait_input)
214  self._show_workspace(test_client)
215 
216  def _move_armbyarm_jointangles(self, test_client):
217  '''
218  @type test_client: hironx_ros_robotics.abst_acceptancetest.AbstAcceptanceTest
219  '''
220  test_client.go_initpos()
221  arm = Constant.GRNAME_LEFT_ARM
222  test_client.set_joint_angles(arm, self._POSITIONS_LARM_DEG_UP,
223  'Task1 {}'.format(arm))
224 
225  arm = Constant.GRNAME_RIGHT_ARM
226  test_client.set_joint_angles(arm, self._POSITIONS_RARM_DEG_DOWN,
227  'Task1 {}'.format(arm))
228  time.sleep(2.0)
229 
230  def _move_armbyarm_pose(self, test_client):
231  print('** _move_armbyarm_pose isn\'t yet implemented')
232  pass
233 
234  def _movearms_together(self, test_client):
235  '''
236  @type test_client: hironx_ros_robotics.abst_acceptancetest.AbstAcceptanceTest
237  '''
238  test_client.go_initpos()
239  arm = Constant.GRNAME_LEFT_ARM
240  test_client.set_joint_angles(
241  arm, self._POSITIONS_LARM_DEG_UP_SYNC, '{}'.format(arm),
242  self._TASK_DURATION_DEFAULT, False)
243  #'task2; Under current implementation, left arm ' +
244  #'always moves first, followed immediately by right arm')
245  arm = Constant.GRNAME_RIGHT_ARM
246  test_client.set_joint_angles(
247  arm, self._POSITIONS_RARM_DEG_DOWN, '{}'.format(arm),
248  self._TASK_DURATION_DEFAULT, False)
249  time.sleep(2.0)
250 
251  def _set_pose_relative(self, test_client):
252  test_client.go_initpos()
253 
254  delta = self._R_Z_SMALLINCREMENT
256  t_total_sec = self._DURATON_TOTAL_SMALLINCREMENT
257  total_increment = int(t_total_sec / t)
258  msg_1 = ('Right arm is moving upward with' +
259  '{}mm increment per {}s'.format(delta, t))
260  msg_2 = ' (Total {}cm over {}s).'.format(delta * total_increment, t_total_sec)
261  print(msg_1 + msg_2)
262  for i in range(total_increment):
263  msg_eachloop = '{}th loop;'.format(i)
264  test_client.set_pose_relative(
265  Constant.GRNAME_RIGHT_ARM, dz=delta,
266  msg_tasktitle=msg_eachloop, task_duration=t, do_wait=True)
267 
268  def _move_head(self, test_client):
269  test_client.go_initpos()
270 
271  for positions in self._ROTATION_ANGLES_HEAD_1:
272  test_client.set_joint_angles(
273  Constant.GRNAME_HEAD,
274  positions, '(1);', self._TASK_DURATION_HEAD)
275 
276  for positions in self._ROTATION_ANGLES_HEAD_2:
277  test_client.set_joint_angles(
278  Constant.GRNAME_HEAD, positions,
279  '(2);', self._TASK_DURATION_HEAD)
280 
281  def _move_torso(self, test_client):
282  test_client.go_initpos()
283  for positions in self._POSITIONS_TORSO_DEG:
284  test_client.set_joint_angles(Constant.GRNAME_TORSO,
285  positions, '')
286 
287  def _overwrite_torso(self, test_client):
288  test_client.go_initpos()
289  test_client.set_joint_angles(
290  Constant.GRNAME_TORSO, self._POSITIONS_TORSO_DEG[0],
291  '(1)', self._TASK_DURATION_TORSO, False)
292  time.sleep(2.0)
293  test_client.set_joint_angles(
294  Constant.GRNAME_TORSO, self._POSITIONS_TORSO_DEG[1],
295  '(2)', self._TASK_DURATION_TORSO, True)
296  time.sleep(2.0)
297 
298  def _overwrite_arm(self, test_client):
299  test_client.go_initpos()
300  test_client.set_joint_angles(
301  Constant.GRNAME_LEFT_ARM, self._POSITIONS_LARM_DEG_UP_SYNC,
302  '(1)', self._TASK_DURATION_DEFAULT, False)
303  test_client.set_joint_angles(
304  Constant.GRNAME_RIGHT_ARM, self._POSITIONS_RARM_DEG_UP_SYNC,
305  '(2) begins. Overwrite previous arm command.' +
306  '\n\tIn the beginning both arm starts to move to the' +
307  '\n\tsame height, but to the left arm interrupting' +
308  '\ncommand is sent and it goes downward.',
309  self._TASK_DURATION_DEFAULT, False)
310  time.sleep(2.0)
311  test_client.set_joint_angles(
312  Constant.GRNAME_LEFT_ARM, self._POSITIONS_LARM_DEG_DOWN,
313  '(3)', self._TASK_DURATION_DEFAULT, False)
314 
315  def _show_workspace(self, test_client):
316  test_client.go_initpos()
317  msg = '; '
318 
319  larm = Constant.GRNAME_LEFT_ARM
320  rarm = Constant.GRNAME_RIGHT_ARM
321  # X near, Y far.
322  test_client.set_pose(
323  larm, self._POS_L_X_NEAR_Y_FAR, self._RPY_L_X_NEAR_Y_FAR,
324  msg + '{}'.format(larm), self._TASK_DURATION_DEFAULT, False)
325  test_client.set_pose(
326  rarm, self._POS_R_X_NEAR_Y_FAR, self._RPY_R_X_NEAR_Y_FAR,
327  msg + '{}'.format(rarm), self._TASK_DURATION_DEFAULT, True)
328 
329  # X far, Y far.
330  test_client.set_pose(
331  larm, self._POS_L_X_FAR_Y_FAR, self._RPY_L_X_FAR_Y_FAR,
332  msg + '{}'.format(larm), self._TASK_DURATION_DEFAULT, False)
333  test_client.set_pose(
334  rarm, self._POS_R_X_FAR_Y_FAR, self._RPY_R_X_FAR_Y_FAR,
335  msg + '{}'.format(rarm), self._TASK_DURATION_DEFAULT, True)
336 
337 import argparse
338 
339 from hrpsys import rtm
340 
341 if __name__ == '__main__':
342  parser = argparse.ArgumentParser(description='hiro command line interpreters')
343  parser.add_argument('--host', help='corba name server hostname')
344  parser.add_argument('--port', help='corba name server port number')
345  parser.add_argument('--modelfile', help='robot model file nmae')
346  parser.add_argument('--robot', help='robot modlule name (RobotHardware0 for real robot, Robot()')
347  args, unknown = parser.parse_known_args()
348 
349  if args.host:
350  rtm.nshost = args.host
351  if args.port:
352  rtm.nsport = args.port
353  if not args.robot:
354  args.robot = 'RobotHardware0' if args.host else 'HiroNX(Robot)0'
355  if not args.modelfile:
356  args.modelfile = ''
357 
358  # support old style format
359  if len(unknown) >= 2:
360  args.robot = unknown[0]
361  args.modelfile = unknown[1]
362  acceptance = AcceptanceTest_Hiro()
def _run_tests(self, test_client, do_wait_input=False)
def __init__(self, rtm_robotname='HiroNX(Robot) 0', url='')
def run_tests_rtm(self, do_wait_input=False)
def _wait_input(self, msg, do_wait_input=False)
def run_tests_ros(self, do_wait_input=False)


hironx_ros_bridge
Author(s): Kei Okada , Isaac I.Y. Saito
autogenerated on Thu May 14 2020 03:52:05