Skip to content

Commit 1f292cc

Browse files
committed
[WIP][ros_bridge] Fix to tork-a/rtmros_nextage#308.
1 parent 0541637 commit 1f292cc

File tree

3 files changed

+78
-30
lines changed

3 files changed

+78
-30
lines changed

hironx_ros_bridge/scripts/hironx.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,15 @@
5656
' this script, but can use RTM. To use ROS, do not forget' \
5757
' to run rosbridge. How to do so? --> http://wiki.ros.org/rtmros_nextage/Tutorials/Operating%20Hiro%2C%20NEXTAGE%20OPEN'
5858

59-
RTC_LIST = [
60-
['seq', "SequencePlayer"],
61-
['sh', "StateHolder"],
62-
['fk', "ForwardKinematics"],
63-
['ic', "ImpedanceController"],
64-
['el', "SoftErrorLimiter"],
65-
# ['co', "CollisionDetector"],
66-
['sc', "ServoController"],
67-
['log', "DataLogger"],]
59+
RTC_LIST = 'seq, sh, fk, ic, el, sc, log'
6860

6961
if __name__ == '__main__':
7062
parser = argparse.ArgumentParser(description='hiro command line interpreters')
7163
parser.add_argument('--host', help='corba name server hostname')
7264
parser.add_argument('--port', help='corba name server port number')
7365
parser.add_argument('--modelfile', help='robot model file nmae')
7466
parser.add_argument('--robot', help='robot modlule name (RobotHardware0 for real robot, Robot()')
75-
parser.add_argument('--rtcs', help='RT components to activate. If nothing passed then default value will be used.')
67+
parser.add_argument('--rtcs', help="RT components to activate. If nothing passed then default value will be used. Example: ['seq', 'sh', 'fk', 'ic', 'el', 'sc', 'log']")
7668
args, unknown = parser.parse_known_args()
7769
unknown = [u for u in unknown if u[:2] != '__'] # filter out ros arguments
7870

hironx_ros_bridge/src/hironx_ros_bridge/hironx_client.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class via the link above; nicely formatted api doc web page
307307

308308
HandGroups = {'rhand': [2, 3, 4, 5], 'lhand': [6, 7, 8, 9]}
309309

310-
_RTClist = [
310+
_RTC_list = [
311311
['seq', "SequencePlayer"],
312312
['sh', "StateHolder"],
313313
['fk', "ForwardKinematics"],
@@ -318,6 +318,9 @@ class via the link above; nicely formatted api doc web page
318318
['log', "DataLogger"],
319319
]
320320

321+
# List of the name of RT Components that hrpsys requires at minimum.
322+
_RTC_NAME_MINREQ = ['seq', 'sh', 'fk']
323+
321324
# servo controller (grasper)
322325
sc = None
323326
sc_svc = None
@@ -328,7 +331,7 @@ class via the link above; nicely formatted api doc web page
328331
"the function call was successful, since not " +
329332
"all methods internally called return status")
330333

331-
def init(self, robotname="HiroNX(Robot)0", url="", rtcs=_RTClist):
334+
def init(self, robotname="HiroNX(Robot)0", url="", rtcs=None):
332335
'''
333336
Calls init from its superclass, which tries to connect RTCManager,
334337
looks for ModelLoader, and starts necessary RTC components. Also runs
@@ -337,11 +340,10 @@ def init(self, robotname="HiroNX(Robot)0", url="", rtcs=_RTClist):
337340
338341
@type robotname: str
339342
@type url: str
340-
@type rtcs: [[str, str]]
341-
@param rtcs: List of list of RTC names. Each inner list consists of
342-
'SHORTENED' name and the 'FULLNAME'.
343+
@type rtcs: [str]
344+
@param rtcs: List of abbreviated RTC names.
343345
344-
example: [['seq', "SequencePlayer"], ['sh', "StateHolder"],,,]
346+
example: ['seq', 'sh',,,]
345347
'''
346348
# reload for hrpsys 315.1.8
347349
print(self.configurator_name + "waiting ModelLoader")
@@ -367,7 +369,10 @@ def init(self, robotname="HiroNX(Robot)0", url="", rtcs=_RTClist):
367369
self.sensors = self.getSensors(url)
368370

369371
if rtcs:
370-
self._RTClist = rtcs
372+
# convert the list of abbreviated RTC names to the one that
373+
# getRTCList wants.
374+
self.getRTCList(rtcs)
375+
371376
# all([rtm.findRTC(rn[0], rtm.rootnc) for rn in self.getRTCList()]) # not working somehow...
372377
if set([rn[0] for rn in self.getRTCList()]).issubset(set([x.name() for x in self.ms.get_components()])) :
373378
print(self.configurator_name + "hrpsys components are already created and running")
@@ -450,24 +455,55 @@ def goInitial(self, tm=7, wait=True, init_pose_type=0):
450455
self.seq_svc.waitInterpolationOfGroup(self.Groups[i][0])
451456
return ret
452457

453-
def getRTCList(self):
458+
def getRTCList(self, rtcs_str=None):
454459
'''
455460
@see: HrpsysConfigurator.getRTCList
456461
462+
@type rtcs_str: str
463+
@param rtcs_str: A single str for a set of abbreviated names of RTCs,
464+
each of which is comma-separated.
465+
example: "seq, sh, fk, ic, el, sc, log"
457466
@rtype [[str]]
458-
@rerutrn List of available components. Each element consists of a list
467+
@return List of available components. Each element consists of a list
459468
of abbreviated and full names of the component.
469+
@raise TypeError: When rtcs_str isn't a string.
470+
@raise ValueError: When rtcs_str does not contain minimum
471+
required RTCs.
460472
'''
461-
if hasattr(self, 'rmfo'):
473+
if rtcs_str:
474+
if not isinstance(rtcs_str, basestring):
475+
raise TypeError('rtcs_str needs to be string.')
476+
# Set a new list of RTCs
477+
new_rtcs = []
478+
# Separate by comma and remove whitespace.
479+
for rtc_requested in [x.strip() for x in rtcs_str.split(",")]:
480+
for elem in self._RTC_list:
481+
if elem[0] == rtc_requested:
482+
new_rtcs.append(elem)
483+
break
484+
# Check if minimum required RTCs are passed.
485+
if not all(x in self._RTC_NAME_MINREQ for x in new_rtcs):
486+
raise ValueError('{} are required at minimum'.format(
487+
self._RTC_NAME_MINREQ))
488+
self._RTC_list = new_rtcs
489+
490+
is_rmfo_initiated = False
491+
# For some reason using built-in "any" method yields
492+
# `TypeError: 'module' object is not callable`, so do the iteration.
493+
for rtc_list in self._RTC_list:
494+
if 'rmfo' in rtc_list:
495+
is_rmfo_initiated = True
496+
if hasattr(self, 'rmfo') and not is_rmfo_initiated:
462497
self.ms.load("RemoveForceSensorLinkOffset")
463498
self.ms.load("AbsoluteForceSensor")
464499
if "RemoveForceSensorLinkOffset" in self.ms.get_factory_names():
465-
self._RTClist.append(['rmfo', "RemoveForceSensorLinkOffset"])
500+
self._RTC_list.append(['rmfo', "RemoveForceSensorLinkOffset"])
466501
elif "AbsoluteForceSensor" in self.ms.get_factory_names():
467-
self._RTClist.append(['rmfo', "AbsoluteForceSensor"])
502+
self._RTC_list.append(['rmfo', "AbsoluteForceSensor"])
468503
else:
469504
print "Component rmfo is not loadable."
470-
return self._RTClist
505+
print('[getRTCList][DEBUG] _RTC_list: {}'.format(self._RTC_list))
506+
return self._RTC_list
471507

472508
# hand interface
473509
# effort: 1~100[%]

hironx_ros_bridge/test/test_hironx_client.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,23 @@ class TestHiroClient(TestHiro):
4747
['fk', "ForwardKinematics"],
4848
['ic', "ImpedanceController"],
4949
['el', "SoftErrorLimiter"],
50-
# ['co', "CollisionDetector"],
5150
['sc', "ServoController"],
5251
['log', "DataLogger"],
52+
# rmfo will be automatically added in getRTCList.
53+
['rmfo', 'RemoveForceSensorLinkOffset']
5354
]
5455

5556
_RTC_LIST_CUSTOM = [
5657
['seq', "SequencePlayer"],
5758
['sh', "StateHolder"],
5859
['fk', "ForwardKinematics"],
59-
['el', "SoftErrorLimiter"],
60-
['co', "CollisionDetector"],
61-
['log', "DataLogger"],
60+
['rmfo', 'RemoveForceSensorLinkOffset']
6261
]
6362

6463
def test_getRTCList(self):
6564
self.assertListEqual(self.robot.getRTCList(), self._RTC_LIST)
6665

67-
def test_getRTCList_customrtcs(self):
66+
def test_getRTCList_customrtcs_args_correct(self):
6867
'''
6968
Test when the RTC list was passed from the client.
7069
@@ -73,10 +72,31 @@ def test_getRTCList_customrtcs(self):
7372
which is not elegant but as of now I can't think of a better way.
7473
'''
7574
self.robot = HIRONX()
76-
self.robot.init(rtcs=self._RTC_LIST_CUSTOM)
77-
75+
# Passing 1st elems from _RTC_LIST_CUSTOM, to init method that calls
76+
# internally getRTCList.
77+
self.robot.init(rtcs='seq, sh, fk')
7878
self.assertListEqual(self.robot.getRTCList(), self._RTC_LIST_CUSTOM)
7979

80+
def test_getRTCList_customrtcs_args_wrong(self):
81+
'''
82+
Test when the RTC list was passed from the client, in wrong format.
83+
'''
84+
# Passing the list of RTCs falling short of requirement.
85+
self.assertRaises(
86+
ValueError, self.robot.getRTCList, rtcs_str='seq, sh')
87+
88+
# Passing 1st elems from _RTC_LIST_CUSTOM,
89+
# but list is not the right type of arg.
90+
#
91+
## http://stackoverflow.com/questions/6103825/how-to-properly-use-unit-testings-assertraises-with-nonetype-objects
92+
## <-- didn't work, TypeError still raised before assertion.
93+
# with self.assertRaises(TypeError):
94+
# self.robot.getRTCList(rtcs_str=['seq', 'sh', 'fk', 'el', 'co', 'log'])
95+
## http://stackoverflow.com/a/6103930/577001
96+
self.assertRaises(
97+
TypeError, lambda: self.robot.getRTCList,
98+
rtcs_str=['seq', 'sh', 'fk', 'el', 'co', 'log'])
99+
80100
if __name__ == '__main__':
81101
import rostest
82102
rostest.rosrun(PKG, 'test_hronx_client', TestHiroClient)

0 commit comments

Comments
 (0)