@@ -14,6 +14,7 @@ class Nao (Robot):
1414 DOF = 25
1515 PHALANX_MAX = 8
1616 ACTUATOR_PKT_SIZE = 786
17+ MSGPACK_READ_LENGTH = 896
1718
1819 sensors = {
1920 "Stiffness" : [ 1.0 ] * DOF ,
@@ -26,9 +27,9 @@ class Nao (Robot):
2627 "Angles" : [ 0.0 , 0.0 ],
2728 "Sonar" : [ 0.0 , 0.0 ],
2829 "FSR" : [ 0.0 ] * 8 ,
29- "Status" : [ 0.0 ] * DOF ,
30+ "Status" : [ 0 ] * DOF ,
3031 "Touch" : [ 0.0 ] * 14 ,
31- "RobotConfig" : [ "0000 " , "6.0.0" , "0000 " , "6.0.0" ],
32+ "RobotConfig" : [ "P0000000000000000000 " , "6.0.0" , "P0000000000000000000 " , "6.0.0" ],
3233 }
3334
3435
@@ -43,7 +44,7 @@ def setHand(self, angle, right=True):
4344 array = self .rphalanx ;
4445 if not right :
4546 array = self .lphalanx
46-
47+
4748 for i in range (self .PHALANX_MAX ):
4849 clampedAngle = angle
4950 if clampedAngle > self .maxPhalanxMotorPosition [i ]:
@@ -90,15 +91,15 @@ def findAndEnableDevices(self):
9091 self .lfootrbumper = self .getDevice ('LFoot/Bumper/Right' )
9192 self .rfootlbumper = self .getDevice ('RFoot/Bumper/Left' )
9293 self .rfootrbumper = self .getDevice ('RFoot/Bumper/Right' )
93-
94+
9495 self .leds ["Chest" ] = self .getDevice ('ChestBoard/Led' )
9596 self .leds ["REar" ] = self .getDevice ('Ears/Led/Right' )
9697 self .leds ["LEar" ] = self .getDevice ('Ears/Led/Left' )
9798 self .leds ["LEye" ] = self .getDevice ('Face/Led/Left' )
9899 self .leds ["REye" ] = self .getDevice ('Face/Led/Right' )
99100 self .leds ["LFoot" ] = self .getDevice ('LFoot/Led' )
100101 self .leds ["RFoot" ] = self .getDevice ('RFoot/Led' )
101-
102+
102103 # finger motors
103104 for i in range (self .PHALANX_MAX ):
104105 self .lphalanx .append (self .getDevice ("LPhalanx%d" % (i + 1 )))
@@ -135,7 +136,7 @@ def findAndEnableDevices(self):
135136 self .lfootrbumper = self .getTouchSensor ('LFoot/Bumper/Right' )
136137 self .rfootlbumper = self .getTouchSensor ('RFoot/Bumper/Left' )
137138 self .rfootrbumper = self .getTouchSensor ('RFoot/Bumper/Right' )
138-
139+
139140 # there are 7 controlable LED groups in Webots
140141 self .leds ["Chest" ] = self .getLED ('ChestBoard/Led' )
141142 self .leds ["REar" ] = self .getLED ('Ears/Led/Right' )
@@ -144,7 +145,7 @@ def findAndEnableDevices(self):
144145 self .leds ["REye" ] = self .getLED ('Face/Led/Right' )
145146 self .leds ["LFoot" ] = self .getLED ('LFoot/Led' )
146147 self .leds ["RFoot" ] = self .getLED ('RFoot/Led' )
147-
148+
148149 # finger motors
149150 for i in range (self .PHALANX_MAX ):
150151 self .lphalanx .append (self .getDevice ("LPhalanx%d" % (i + 1 )))
@@ -194,13 +195,13 @@ def findAndEnableDevices(self):
194195
195196
196197 def updateSensors (self ):
197- # increase tick, taking care it will not overflow
198+ # increase tick, taking care it will not overflow
198199 # the 16 bit unsigned image timestamp
199200 self .tick = (self .tick + 1 ) % 2 ** 16
200201
201202 # update ticks (by abusing battery temperature field)
202203 if self .args .send_ticks :
203- self .sensors ["Battery" ][3 ] = self .tick
204+ self .sensors ["Battery" ][3 ] = self .tick * 1.0 # convert to float
204205
205206 # IMU
206207 a = self .accelerometer .getValues ()
@@ -226,7 +227,7 @@ def updateSensors(self):
226227 # FSR
227228 # conversion is stolen from webots nao_demo_python controller
228229 fsv = [self .fsr [0 ].getValues (), self .fsr [1 ].getValues ()]
229-
230+
230231 a = []
231232 a .append (fsv [0 ][2 ] / 3.4 + 1.5 * fsv [0 ][0 ] + 1.15 * fsv [0 ][1 ]) # Left Foot Front Left
232233 a .append (fsv [0 ][2 ] / 3.4 + 1.5 * fsv [0 ][0 ] - 1.15 * fsv [0 ][1 ]) # Left Foot Front Right
@@ -238,23 +239,23 @@ def updateSensors(self):
238239 a .append (fsv [1 ][2 ] / 3.4 - 1.5 * fsv [1 ][0 ] - 1.15 * fsv [1 ][1 ]) # Right Foot Rear Right
239240 a .append (fsv [1 ][2 ] / 3.4 - 1.5 * fsv [1 ][0 ] + 1.15 * fsv [1 ][1 ]) # Right Foot Rear Left
240241 for i in range (len (a )):
241- self .sensors ["FSR" ][i ] = max (0 , a [i ]/ 25.0 ) # fix scaling of values
242+ self .sensors ["FSR" ][i ] = max (0.0 , a [i ]/ 25.0 ) # fix scaling of values
242243
243244 # set chest button if C key is pressed
244245 if self .key == ord ('C' ):
245246 if self .sensors ["Touch" ][0 ] < 1 :
246247 print (AnsiCodes .CYAN_FOREGROUND + "Chest button pressed." + AnsiCodes .RESET )
247- self .sensors ["Touch" ][0 ] = 1
248+ self .sensors ["Touch" ][0 ] = 1.0
248249 elif self .key == ord ('U' ):
249250 if self .sensors ["Touch" ][2 ] < 1 :
250251 print (AnsiCodes .CYAN_FOREGROUND + "Head touched." + AnsiCodes .RESET )
251252 for i in range (1 ,4 ):
252- self .sensors ["Touch" ][i ] = 1
253+ self .sensors ["Touch" ][i ] = 1.0
253254 elif self .key == ord ('A' ):
254255 if self .sensors ["Touch" ][1 ] < 1 :
255256 print (AnsiCodes .CYAN_FOREGROUND + "Front head & chest button pressed." + AnsiCodes .RESET )
256- self .sensors ["Touch" ][0 ] = 1
257- self .sensors ["Touch" ][1 ] = 1
257+ self .sensors ["Touch" ][0 ] = 1.0
258+ self .sensors ["Touch" ][1 ] = 1.0
258259 else :
259260 if self .sensors ["Touch" ][0 ] > 0 :
260261 print (AnsiCodes .CYAN_FOREGROUND + "Chest button released." + AnsiCodes .RESET )
@@ -263,7 +264,7 @@ def updateSensors(self):
263264 elif self .sensors ["Touch" ][1 ] > 0 :
264265 print (AnsiCodes .CYAN_FOREGROUND + "Front head & chest button released." + AnsiCodes .RESET )
265266 for i in range (0 ,4 ):
266- self .sensors ["Touch" ][i ] = 0
267+ self .sensors ["Touch" ][i ] = 0.0
267268
268269
269270
@@ -276,35 +277,35 @@ def led_array2RGB(self, a):
276277
277278 def updateActuators (self , actuators ):
278279 # motors
279- if "Position" in actuators :
280+ if b "Position" in actuators :
280281 for i in range (self .DOF - 2 ):
281- self .motors [i ].setPosition (actuators ["Position" ][i ])
282+ self .motors [i ].setPosition (actuators [b "Position" ][i ])
282283 # set hands, since they have more than 1 actuator each in webots
283- self .setHands (actuators ["Position" ][23 ], actuators ["Position" ][24 ])
284+ self .setHands (actuators [b "Position" ][23 ], actuators [b "Position" ][24 ])
284285 # set RHipYawPitch which does not exists in LoLa packet
285- self .motors [25 ].setPosition (actuators ["Position" ][7 ])
286+ self .motors [25 ].setPosition (actuators [b "Position" ][7 ])
286287
287288 # LEDs
288- if "Chest" in actuators :
289- self .leds ["Chest" ].set (self .led_array2RGB (actuators ["Chest" ]))
290- if "LFoot" in actuators :
291- self .leds ["LFoot" ].set (self .led_array2RGB (actuators ["LFoot" ]))
292- if "RFoot" in actuators :
293- self .leds ["RFoot" ].set (self .led_array2RGB (actuators ["RFoot" ]))
289+ if b "Chest" in actuators :
290+ self .leds ["Chest" ].set (self .led_array2RGB (actuators [b "Chest" ]))
291+ if b "LFoot" in actuators :
292+ self .leds ["LFoot" ].set (self .led_array2RGB (actuators [b "LFoot" ]))
293+ if b "RFoot" in actuators :
294+ self .leds ["RFoot" ].set (self .led_array2RGB (actuators [b "RFoot" ]))
294295
295296 # webots model has only one LED per eye, so just use the first one
296- if "LEye" in actuators :
297- v = actuators ["LEye" ]
297+ if b "LEye" in actuators :
298+ v = actuators [b "LEye" ]
298299 self .leds ["LEye" ].set (self .led_array2RGB ([v [0 ], v [8 ], v [16 ]]))
299- if "REye" in actuators :
300- v = actuators ["REye" ]
300+ if b "REye" in actuators :
301+ v = actuators [b "REye" ]
301302 self .leds ["REye" ].set (self .led_array2RGB ([v [0 ], v [8 ], v [16 ]]))
302303
303304 # webots model has only one LED per ear, so just use the first one
304- if "LEar" in actuators :
305- self .leds ["LEar" ].set (self .led_array2RGB ([0 , 0 , actuators ["LEar" ][0 ]]))
306- if "REar" in actuators :
307- self .leds ["REar" ].set (self .led_array2RGB ([0 , 0 , actuators ["REar" ][0 ]]))
305+ if b "LEar" in actuators :
306+ self .leds ["LEar" ].set (self .led_array2RGB ([0 , 0 , actuators [b "LEar" ][0 ]]))
307+ if b "REar" in actuators :
308+ self .leds ["REar" ].set (self .led_array2RGB ([0 , 0 , actuators [b "REar" ][0 ]]))
308309
309310
310311
@@ -338,10 +339,10 @@ def parse_args(self):
338339 dest = "lola_addr" , default = "" , metavar = "ADDR" ,
339340 help = "Path for LoLa UNIX socket or address on which TCP server will listen on (\" <host>:<port>\" or \" <port>\" )" )
340341 op .add_argument ("--tcam-listen=" , action = "store" ,
341- dest = "tcam_addr" , default = "" , metavar = "ADDR" ,
342+ dest = "tcam_addr" , default = "" , metavar = "ADDR" ,
342343 help = "Listen address for top camera image server (\" <host>:<port>\" or \" <port>\" )" )
343344 op .add_argument ("--bcam-listen=" , action = "store" ,
344- dest = "bcam_addr" , default = "" , metavar = "ADDR" ,
345+ dest = "bcam_addr" , default = "" , metavar = "ADDR" ,
345346 help = "Listen address for bottom camera image server (\" <host>:<port>\" or \" <port>\" )" )
346347 op .add_argument ("--framerate=" , action = "store" ,
347348 dest = "fps" , default = 30 , type = int ,
@@ -374,7 +375,7 @@ def parse_args(self):
374375 args .tcam_addr = ("localhost" , self .TCP_BASE_PORT + 1 )
375376 else :
376377 args .tcam_addr = self .parse_tcp_addr (args .tcam_addr )
377-
378+
378379 # set bottom cam listen address
379380 if not args .bcam_addr :
380381 a = args .tcam_addr
@@ -454,9 +455,12 @@ def run(self):
454455
455456 if conn :
456457 self .updateSensors ()
457- try :
458+ try :
458459 # send sensor data to LoLa client
459- conn .send (umsgpack .packb (self .sensors ))
460+ packed = umsgpack .packb (self .sensors , force_float_precision = "single" )
461+ if len (packed ) != self .MSGPACK_READ_LENGTH :
462+ print (AnsiCodes .RED_FOREGROUND + "Msgpack packet size doesn't match LoLA specifications." + AnsiCodes .RESET )
463+ conn .send (packed )
460464 data = conn .recv (self .ACTUATOR_PKT_SIZE * 3 )
461465 if data :
462466 self .updateActuators (umsgpack .unpackb (data ))
@@ -476,7 +480,10 @@ def run(self):
476480 else :
477481 try :
478482 (conn , addr ) = sock .accept ()
479- conn .send (umsgpack .packb (self .sensors ))
483+ packed = umsgpack .packb (self .sensors , force_float_precision = "single" )
484+ if len (packed ) != self .MSGPACK_READ_LENGTH :
485+ print (AnsiCodes .RED_FOREGROUND + "Msgpack packet size doesn't match LoLA specifications." + AnsiCodes .RESET )
486+ conn .send (packed )
480487 print (AnsiCodes .GREEN_FOREGROUND + "LoLa client connected." + AnsiCodes .RESET )
481488 except :
482489 conn = None
@@ -490,7 +497,8 @@ def run(self):
490497 self .topImageServer .stop ()
491498 self .bottomImageServer .stop ()
492499
493-
500+ # Enable Msgpack Old Specification Compatibility Mode, which is used in LoLA
501+ umsgpack .compatibility = True
494502
495503# create the Robot instance and run main loop
496504robot = Nao ()
0 commit comments