@@ -29,7 +29,7 @@ def __init__(self):
29
29
self ._packeter = ucPack (200 )
30
30
self .left_wheel = _ArduinoAlvikWheel (self ._packeter , ord ('L' ))
31
31
self .right_wheel = _ArduinoAlvikWheel (self ._packeter , ord ('R' ))
32
- self ._led_state = [ None ]
32
+ self ._led_state = list (( None ,))
33
33
self .left_led = _ArduinoAlvikRgbLed (self ._packeter , 'left' , self ._led_state ,
34
34
rgb_mask = [0b00000100 , 0b00001000 , 0b00010000 ])
35
35
self .right_led = _ArduinoAlvikRgbLed (self ._packeter , 'right' , self ._led_state ,
@@ -84,12 +84,13 @@ def _progress_bar(percentage: float) -> None:
84
84
:param percentage:
85
85
:return:
86
86
"""
87
- sys .stdout .write ('\r ' )
87
+ sys .stdout .write (bytes ( '\r ' . encode ( 'utf-8' )) )
88
88
if percentage > 97 :
89
89
marks_str = ' \U0001F50B '
90
90
else :
91
91
marks_str = ' \U0001FAAB '
92
- sys .stdout .write (marks_str + f" { percentage } % \t " )
92
+ word = marks_str + f" { percentage } % \t "
93
+ sys .stdout .write (bytes ((word .encode ('utf-8' ))))
93
94
94
95
def _idle (self , delay_ = 1 , check_on_thread = False ) -> None :
95
96
"""
@@ -105,20 +106,20 @@ def _idle(self, delay_=1, check_on_thread=False) -> None:
105
106
while not self .is_on ():
106
107
if check_on_thread and not self .__class__ ._update_thread_running :
107
108
break
108
- ESP32_SDA = Pin (A4 , Pin .OUT )
109
- ESP32_SCL = Pin (A5 , Pin .OUT )
110
- ESP32_SCL .value (1 )
111
- ESP32_SDA .value (1 )
109
+ _ESP32_SDA = Pin (A4 , Pin .OUT )
110
+ _ESP32_SCL = Pin (A5 , Pin .OUT )
111
+ _ESP32_SCL .value (1 )
112
+ _ESP32_SDA .value (1 )
112
113
sleep_ms (100 )
113
- ESP32_SCL .value (0 )
114
- ESP32_SDA .value (0 )
114
+ _ESP32_SCL .value (0 )
115
+ _ESP32_SDA .value (0 )
115
116
116
117
cmd = bytearray (1 )
117
118
cmd [0 ] = 0x06
118
119
i2c = I2C (0 , scl = ESP32_SCL , sda = ESP32_SDA )
119
120
i2c .writeto (0x36 , cmd )
120
121
soc_raw = struct .unpack ('h' , i2c .readfrom (0x36 , 2 ))[0 ]
121
- soc_perc = soc_raw * 0.00390625
122
+ soc_perc = soc_raw * 0.00390625
122
123
self ._progress_bar (round (soc_perc ))
123
124
sleep_ms (delay_ )
124
125
if soc_perc > 97 :
@@ -140,30 +141,32 @@ def _idle(self, delay_=1, check_on_thread=False) -> None:
140
141
LEDG .value (1 )
141
142
NANO_CHK .value (0 )
142
143
143
- def _snake_robot (self , duration : int = 1000 ):
144
+ @staticmethod
145
+ def _snake_robot (duration : int = 1000 ):
144
146
"""
145
147
Snake robot animation
146
- :param percentage :
148
+ :param duration :
147
149
:return:
148
150
"""
149
- i = 0
150
151
151
152
robot = '\U0001F916 '
152
153
snake = '\U0001F40D '
153
154
154
155
cycles = int (duration / 200 )
155
156
157
+ frame = ''
156
158
for i in range (0 , cycles ):
157
- sys .stdout .write ('\r ' )
159
+ sys .stdout .write (bytes ( '\r ' . encode ( 'utf-8' )) )
158
160
pre = ' ' * i
159
161
between = ' ' * (i % 2 + 1 )
160
162
post = ' ' * 5
161
163
frame = pre + snake + between + robot + post
162
- sys .stdout .write (frame )
164
+ sys .stdout .write (bytes ( frame . encode ( 'utf-8' )) )
163
165
sleep_ms (200 )
164
166
165
- sys .stdout .write ('\r ' )
166
- sys .stdout .write ('' )
167
+ sys .stdout .write (bytes ('\r ' .encode ('utf-8' )))
168
+ clear_frame = ' ' * len (frame )
169
+ sys .stdout .write (bytes (clear_frame .encode ('utf-8' )))
167
170
168
171
def begin (self ) -> int :
169
172
"""
@@ -309,7 +312,7 @@ def _reset_hw():
309
312
RESET_STM32 .value (1 )
310
313
sleep_ms (100 )
311
314
312
- def get_wheels_speed (self , unit : str = 'rpm' ) -> (float , float ):
315
+ def get_wheels_speed (self , unit : str = 'rpm' ) -> (float | None , float | None ):
313
316
"""
314
317
Returns the speed of the wheels
315
318
:param unit: the speed unit of measurement (default: 'rpm')
@@ -327,8 +330,8 @@ def set_wheels_speed(self, left_speed: float, right_speed: float, unit: str = 'r
327
330
"""
328
331
329
332
if unit == '%' :
330
- left_speed = (left_speed / 100 )* MOTOR_MAX_RPM
331
- right_speed = (right_speed / 100 )* MOTOR_MAX_RPM
333
+ left_speed = (left_speed / 100 ) * MOTOR_MAX_RPM
334
+ right_speed = (right_speed / 100 ) * MOTOR_MAX_RPM
332
335
else :
333
336
left_speed = convert_rotational_speed (left_speed , unit , 'rpm' )
334
337
right_speed = convert_rotational_speed (right_speed , unit , 'rpm' )
@@ -345,10 +348,10 @@ def set_wheels_position(self, left_angle: float, right_angle: float, unit: str =
345
348
:return:
346
349
"""
347
350
self ._packeter .packetC2F (ord ('A' ), convert_angle (left_angle , unit , 'deg' ),
348
- convert_angle (right_angle , unit , 'deg' ))
351
+ convert_angle (right_angle , unit , 'deg' ))
349
352
uart .write (self ._packeter .msg [0 :self ._packeter .msg_size ])
350
353
351
- def get_wheels_position (self , unit : str = 'deg' ) -> (float , float ):
354
+ def get_wheels_position (self , unit : str = 'deg' ) -> (float | None , float | None ):
352
355
"""
353
356
Returns the angle of the wheels
354
357
:param unit: the angle unit of measurement (default: 'deg')
@@ -357,36 +360,36 @@ def get_wheels_position(self, unit: str = 'deg') -> (float, float):
357
360
return (convert_angle (self .left_wheel .get_position (), 'deg' , unit ),
358
361
convert_angle (self .right_wheel .get_position (), 'deg' , unit ))
359
362
360
- def get_orientation (self ) -> (float , float , float ):
363
+ def get_orientation (self ) -> (float | None , float | None , float | None ):
361
364
"""
362
365
Returns the orientation of the IMU
363
366
:return: roll, pitch, yaw
364
367
"""
365
368
366
369
return self ._roll , self ._pitch , self ._yaw
367
370
368
- def get_accelerations (self ) -> (float , float , float ):
371
+ def get_accelerations (self ) -> (float | None , float | None , float | None ):
369
372
"""
370
373
Returns the 3-axial acceleration of the IMU
371
374
:return: ax, ay, az
372
375
"""
373
376
return self ._ax , self ._ay , self ._az
374
377
375
- def get_gyros (self ) -> (float , float , float ):
378
+ def get_gyros (self ) -> (float | None , float | None , float | None ):
376
379
"""
377
380
Returns the 3-axial angular acceleration of the IMU
378
381
:return: gx, gy, gz
379
382
"""
380
383
return self ._gx , self ._gy , self ._gz
381
384
382
- def get_imu (self ) -> (float , float , float , float , float , float ):
385
+ def get_imu (self ) -> (float | None , float | None , float | None , float | None , float | None , float | None ):
383
386
"""
384
387
Returns all the IMUs readouts
385
388
:return: ax, ay, az, gx, gy, gz
386
389
"""
387
390
return self ._ax , self ._ay , self ._az , self ._gx , self ._gy , self ._gz
388
391
389
- def get_line_sensors (self ) -> (int , int , int ):
392
+ def get_line_sensors (self ) -> (int | None , int | None , int | None ):
390
393
"""
391
394
Returns the line sensors readout
392
395
:return: left_line, center_line, right_line
@@ -406,7 +409,7 @@ def drive(self, linear_velocity: float, angular_velocity: float, linear_unit: st
406
409
"""
407
410
linear_velocity = convert_speed (linear_velocity , linear_unit , 'mm/s' )
408
411
if angular_unit == '%' :
409
- angular_velocity = (angular_velocity / 100 )* ROBOT_MAX_DEG_S
412
+ angular_velocity = (angular_velocity / 100 ) * ROBOT_MAX_DEG_S
410
413
else :
411
414
angular_velocity = convert_rotational_speed (angular_velocity , angular_unit , 'deg/s' )
412
415
self ._packeter .packetC2F (ord ('V' ), linear_velocity , angular_velocity )
@@ -419,15 +422,16 @@ def brake(self):
419
422
"""
420
423
self .drive (0 , 0 )
421
424
422
- def get_drive_speed (self , linear_unit : str = 'cm/s' , angular_unit : str = 'deg/s' ) -> (float , float ):
425
+ def get_drive_speed (self , linear_unit : str = 'cm/s' , angular_unit : str = 'deg/s' ) -> (float | None , float | None ):
423
426
"""
424
427
Returns linear and angular velocity of the robot
425
428
:param linear_unit: output linear velocity unit of meas
426
429
:param angular_unit: output angular velocity unit of meas
427
430
:return: linear_velocity, angular_velocity
428
431
"""
429
432
if angular_unit == '%' :
430
- angular_velocity = (self ._angular_velocity / ROBOT_MAX_DEG_S )* 100
433
+ angular_velocity = (self ._angular_velocity / ROBOT_MAX_DEG_S ) * 100 \
434
+ if self ._angular_velocity is not None else None
431
435
else :
432
436
angular_velocity = convert_rotational_speed (self ._angular_velocity , 'deg/s' , angular_unit )
433
437
@@ -450,7 +454,8 @@ def reset_pose(self, x: float, y: float, theta: float, distance_unit: str = 'cm'
450
454
uart .write (self ._packeter .msg [0 :self ._packeter .msg_size ])
451
455
sleep_ms (1000 )
452
456
453
- def get_pose (self , distance_unit : str = 'cm' , angle_unit : str = 'deg' ) -> (float , float , float ):
457
+ def get_pose (self , distance_unit : str = 'cm' , angle_unit : str = 'deg' ) \
458
+ -> (float | None , float | None , float | None ):
454
459
"""
455
460
Returns the current pose of the robot
456
461
:param distance_unit: unit of x and y outputs
@@ -471,7 +476,7 @@ def set_servo_positions(self, a_position: int, b_position: int):
471
476
self ._packeter .packetC2B (ord ('S' ), a_position & 0xFF , b_position & 0xFF )
472
477
uart .write (self ._packeter .msg [0 :self ._packeter .msg_size ])
473
478
474
- def get_ack (self ):
479
+ def get_ack (self ) -> str :
475
480
"""
476
481
Returns last acknowledgement
477
482
:return:
@@ -609,11 +614,13 @@ def _parse_message(self) -> int:
609
614
610
615
return 0
611
616
612
- def get_battery_charge (self ) -> int :
617
+ def get_battery_charge (self ) -> int | None :
613
618
"""
614
619
Returns the battery SOC
615
620
:return:
616
621
"""
622
+ if self ._battery_perc is None :
623
+ return None
617
624
if self ._battery_perc > 100 :
618
625
return 100
619
626
return round (self ._battery_perc )
@@ -729,9 +736,9 @@ def color_calibration(self, background: str = 'white') -> None:
729
736
blue_avg += blue
730
737
sleep_ms (10 )
731
738
732
- red_avg = int (red_avg / 100 )
733
- green_avg = int (green_avg / 100 )
734
- blue_avg = int (blue_avg / 100 )
739
+ red_avg = int (red_avg / 100 )
740
+ green_avg = int (green_avg / 100 )
741
+ blue_avg = int (blue_avg / 100 )
735
742
736
743
if background == 'white' :
737
744
self ._white_cal = [red_avg , green_avg , blue_avg ]
@@ -763,7 +770,7 @@ def color_calibration(self, background: str = 'white') -> None:
763
770
for line in lines :
764
771
file .write (line )
765
772
766
- def get_color_raw (self ) -> (int , int , int ):
773
+ def get_color_raw (self ) -> (int | None , int | None , int | None ):
767
774
"""
768
775
Returns the color sensor's raw readout
769
776
:return: red, green, blue
@@ -783,9 +790,9 @@ def _normalize_color(self, r: float, g: float, b: float) -> (float, float, float
783
790
g = self ._limit (g , self ._black_cal [1 ], self ._white_cal [1 ])
784
791
b = self ._limit (b , self ._black_cal [2 ], self ._white_cal [2 ])
785
792
786
- r = (r - self ._black_cal [0 ])/ (self ._white_cal [0 ] - self ._black_cal [0 ])
787
- g = (g - self ._black_cal [1 ])/ (self ._white_cal [1 ] - self ._black_cal [1 ])
788
- b = (b - self ._black_cal [2 ])/ (self ._white_cal [2 ] - self ._black_cal [2 ])
793
+ r = (r - self ._black_cal [0 ]) / (self ._white_cal [0 ] - self ._black_cal [0 ])
794
+ g = (g - self ._black_cal [1 ]) / (self ._white_cal [1 ] - self ._black_cal [1 ])
795
+ b = (b - self ._black_cal [2 ]) / (self ._white_cal [2 ] - self ._black_cal [2 ])
789
796
790
797
return r , g , b
791
798
@@ -829,7 +836,7 @@ def rgb2hsv(r: float, g: float, b: float) -> (float, float, float):
829
836
830
837
return h , s , v
831
838
832
- def get_color (self , color_format : str = 'rgb' ) -> (float , float , float ):
839
+ def get_color (self , color_format : str = 'rgb' ) -> (float | None , float | None , float | None ):
833
840
"""
834
841
Returns the normalized color readout of the color sensor
835
842
:param color_format: rgb or hsv only
@@ -888,7 +895,7 @@ def hsv2label(h, s, v) -> str:
888
895
label = 'BLUE'
889
896
elif 260 <= h < 280 :
890
897
label = 'VIOLET'
891
- else : # h<20 or h>=280 is more problematic
898
+ else : # h<20 or h>=280 is more problematic
892
899
if v < 0.5 and s < 0.45 :
893
900
label = 'BROWN'
894
901
else :
@@ -900,31 +907,28 @@ def hsv2label(h, s, v) -> str:
900
907
label = 'BLACK'
901
908
return label
902
909
903
- def get_distance (self , unit : str = 'cm' ) -> (float , float , float , float , float ):
910
+ def get_distance (self , unit : str = 'cm' ) -> (float | None , float | None , float | None , float | None , float | None ):
904
911
"""
905
912
Returns the distance readout of the TOF sensor
906
913
:param unit: distance output unit
907
914
:return: left_tof, center_left_tof, center_tof, center_right_tof, right_tof
908
915
"""
909
916
910
- if None in [self ._left_tof , self ._center_left_tof , self ._center_tof , self ._center_right_tof , self ._right_tof ]:
911
- return None , None , None , None , None
912
-
913
917
return (convert_distance (self ._left_tof , 'mm' , unit ),
914
918
convert_distance (self ._center_left_tof , 'mm' , unit ),
915
919
convert_distance (self ._center_tof , 'mm' , unit ),
916
920
convert_distance (self ._center_right_tof , 'mm' , unit ),
917
921
convert_distance (self ._right_tof , 'mm' , unit ))
918
922
919
- def get_distance_top (self , unit : str = 'cm' ) -> float :
923
+ def get_distance_top (self , unit : str = 'cm' ) -> float | None :
920
924
"""
921
925
Returns the obstacle top distance readout
922
926
:param unit:
923
927
:return:
924
928
"""
925
929
return convert_distance (self ._top_tof , 'mm' , unit )
926
930
927
- def get_distance_bottom (self , unit : str = 'cm' ) -> float :
931
+ def get_distance_bottom (self , unit : str = 'cm' ) -> float | None :
928
932
"""
929
933
Returns the obstacle bottom distance readout
930
934
:param unit:
@@ -998,26 +1002,26 @@ def set_speed(self, velocity: float, unit: str = 'rpm'):
998
1002
"""
999
1003
1000
1004
if unit == '%' :
1001
- velocity = (velocity / 100 )* MOTOR_MAX_RPM
1005
+ velocity = (velocity / 100 ) * MOTOR_MAX_RPM
1002
1006
else :
1003
1007
velocity = convert_rotational_speed (velocity , unit , 'rpm' )
1004
1008
1005
1009
self ._packeter .packetC2B1F (ord ('W' ), self ._label & 0xFF , ord ('V' ), velocity )
1006
1010
uart .write (self ._packeter .msg [0 :self ._packeter .msg_size ])
1007
1011
1008
- def get_speed (self , unit : str = 'rpm' ) -> float :
1012
+ def get_speed (self , unit : str = 'rpm' ) -> float | None :
1009
1013
"""
1010
1014
Returns the current RPM speed of the wheel
1011
1015
:param unit: the unit of the output speed
1012
1016
:return:
1013
1017
"""
1014
1018
if unit == '%' :
1015
- speed = (self ._speed / MOTOR_MAX_RPM )* 100
1019
+ speed = (self ._speed / MOTOR_MAX_RPM ) * 100 if self . _speed is not None else None
1016
1020
else :
1017
1021
speed = convert_rotational_speed (self ._speed , 'rpm' , unit )
1018
1022
return speed
1019
1023
1020
- def get_position (self , unit : str = 'deg' ) -> float :
1024
+ def get_position (self , unit : str = 'deg' ) -> float | None :
1021
1025
"""
1022
1026
Returns the wheel position (angle with respect to the reference)
1023
1027
:param unit: the unit of the output position
0 commit comments