codrone-edu 2.8__tar.gz → 2.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {codrone_edu-2.8 → codrone_edu-2.10}/PKG-INFO +1 -1
  2. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/drone.py +283 -18
  3. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/protocol.py +254 -13
  4. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/storage.py +6 -0
  5. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/system.py +95 -8
  6. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/transformer.py +279 -132
  7. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/PKG-INFO +1 -1
  8. {codrone_edu-2.8 → codrone_edu-2.10}/setup.py +1 -1
  9. {codrone_edu-2.8 → codrone_edu-2.10}/MANIFEST.in +0 -0
  10. {codrone_edu-2.8 → codrone_edu-2.10}/README.md +0 -0
  11. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/__init__.py +0 -0
  12. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/__main__.py +0 -0
  13. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/crc.py +0 -0
  14. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/black.txt +0 -0
  15. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/blue.txt +0 -0
  16. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/green.txt +0 -0
  17. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/lightblue.txt +0 -0
  18. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/purple.txt +0 -0
  19. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/red.txt +0 -0
  20. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/white.txt +0 -0
  21. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/data/yellow.txt +0 -0
  22. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/errors.py +0 -0
  23. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/receiver.py +0 -0
  24. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/swarm.py +0 -0
  25. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/__init__.py +0 -0
  26. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/interrupter.py +0 -0
  27. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/module_loader.py +0 -0
  28. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/parser.py +0 -0
  29. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/scrubber.py +0 -0
  30. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu/tools/update.py +0 -0
  31. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/SOURCES.txt +0 -0
  32. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/dependency_links.txt +0 -0
  33. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/not-zip-safe +0 -0
  34. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/requires.txt +0 -0
  35. {codrone_edu-2.8 → codrone_edu-2.10}/codrone_edu.egg-info/top_level.txt +0 -0
  36. {codrone_edu-2.8 → codrone_edu-2.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codrone_edu
3
- Version: 2.8
3
+ Version: 2.10
4
4
  Summary: Python CoDrone EDU library
5
5
  Home-page:
6
6
  Author:
@@ -137,7 +137,7 @@ class Drone:
137
137
  # BaseFunctions Start
138
138
 
139
139
  def __init__(self, flagCheckBackground=True, flagShowErrorMessage=False, flagShowLogMessage=False,
140
- flagShowTransferData=False, flagShowReceiveData=False, swarm=False, color_data_dir=None):
140
+ flagShowTransferData=False, flagShowReceiveData=False, swarm=False, color_data_dir=None, flagShowDepLibraryVersion=True):
141
141
 
142
142
  self._serialport = None
143
143
  if sys.platform == 'emscripten':
@@ -182,6 +182,8 @@ class Drone:
182
182
  self._cpuId = []
183
183
  self._battery = 0
184
184
  self._system = ModeSystem.Error
185
+ self._state_update_count = 0
186
+ self._last_state_update_time = 0.0
185
187
 
186
188
  self.timeStartProgram = time.time() # Program Start Time Recording
187
189
 
@@ -268,10 +270,12 @@ class Drone:
268
270
  library_name = "codrone-edu"
269
271
  library = importlib.metadata.distribution(library_name)
270
272
  if sys.platform != 'emscripten' and not self._swarm:
271
- colorama.init()
272
- print(Fore.GREEN + f"Running {library_name} library version {library.version}" + Style.RESET_ALL)
273
+ if flagShowDepLibraryVersion:
274
+ colorama.init()
275
+ print(Fore.GREEN + f"Running {library_name} library version {library.version}" + Style.RESET_ALL)
273
276
  elif sys.platform == 'emscripten':
274
- print("Running {0} library version {1}".format(library_name, library.version), color="green")
277
+ if flagShowDepLibraryVersion:
278
+ print("Running {0} library version {1}".format(library_name, library.version), color="green")
275
279
  # this only works when using the release version of the library
276
280
 
277
281
  def __del__(self):
@@ -1142,6 +1146,10 @@ class Drone:
1142
1146
  self.state_data[6] = drone_type.battery
1143
1147
  self.state_data[7] = drone_type.modeMovement
1144
1148
  self.state_data[8] = drone_type.controlSpeed
1149
+ if sys.platform == 'emscripten':
1150
+ self._battery = drone_type.battery
1151
+ self._state_update_count += 1
1152
+ self._last_state_update_time = time.time()
1145
1153
 
1146
1154
  def get_state_data(self, delay=0.01):
1147
1155
  if sys.platform != 'emscripten' and not self._swarm:
@@ -1162,10 +1170,14 @@ class Drone:
1162
1170
  return self.state_data
1163
1171
 
1164
1172
  async def _get_state_data_emscripten(self, delay=0.01):
1173
+ prev_count = self._state_update_count
1165
1174
  await self.sendRequest(DeviceType.Drone, DataType.State)
1166
1175
  await asyncio.sleep(delay)
1167
1176
  self._system = self.state_data[1]
1168
- self._battery = self.state_data[6]
1177
+ if self._state_update_count == prev_count:
1178
+ # No response this call — only zero battery if data is genuinely stale
1179
+ if time.time() - self._last_state_update_time > 2.0:
1180
+ self._battery = 0
1169
1181
  self.state_data[1] = ModeSystem.Error
1170
1182
  self.state_data[6] = 0
1171
1183
  return self.state_data
@@ -1192,9 +1204,7 @@ class Drone:
1192
1204
 
1193
1205
  async def _get_battery_emscripten(self):
1194
1206
  await self.get_state_data(delay=0.02)
1195
- battery = self._battery
1196
- self._battery = 0
1197
- return battery
1207
+ return self._battery
1198
1208
 
1199
1209
  def get_system_state(self):
1200
1210
  if sys.platform != 'emscripten' and not self._swarm:
@@ -1300,6 +1310,70 @@ class Drone:
1300
1310
  await asyncio.sleep(0.01)
1301
1311
  await self._trigger_speed_callback()
1302
1312
 
1313
+ def control_change(self, mode=ModeControlFlight.Position):
1314
+ """
1315
+ Changes the flight control mode of the drone.
1316
+ default is set to ModeControlFlight.Position
1317
+ :param mode: ModeControlFlight enum value (e.g. Attitude, Position)
1318
+ :return: N/A
1319
+ """
1320
+ if not isinstance(mode, ModeControlFlight):
1321
+ return None
1322
+
1323
+ if sys.platform != 'emscripten' and not self._swarm:
1324
+ return self._control_change_desktop(mode)
1325
+ if sys.platform != 'emscripten' and self._swarm:
1326
+ return asyncio.create_task(self._control_change_swarm(mode))
1327
+ else:
1328
+ return asyncio.create_task(self._control_change_emscripten(mode))
1329
+
1330
+ def _control_change_desktop(self, mode=ModeControlFlight.Position):
1331
+ for _ in range(2):
1332
+ self.sendCommand(CommandType.ModeControlFlight, mode.value)
1333
+ time.sleep(0.03)
1334
+
1335
+ async def _control_change_swarm(self, mode=ModeControlFlight.Position):
1336
+ for _ in range(2):
1337
+ await self.sendCommand(CommandType.ModeControlFlight, mode.value)
1338
+ await asyncio.sleep(0.03)
1339
+
1340
+ async def _control_change_emscripten(self, mode=ModeControlFlight.Position):
1341
+ for _ in range(2):
1342
+ await self.sendCommand(CommandType.ModeControlFlight, mode.value)
1343
+ await asyncio.sleep(0.03)
1344
+
1345
+ def headless_change(self, mode=Headless.Normal):
1346
+ """
1347
+ Changes the headless mode of the drone.
1348
+ default is set to Headless.Normal
1349
+ :param mode: Headless enum value (Headless, Normal)
1350
+ :return: N/A
1351
+ """
1352
+ if not isinstance(mode, Headless):
1353
+ return None
1354
+
1355
+ if sys.platform != 'emscripten' and not self._swarm:
1356
+ return self._headless_change_desktop(mode)
1357
+ if sys.platform != 'emscripten' and self._swarm:
1358
+ return asyncio.create_task(self._headless_change_swarm(mode))
1359
+ else:
1360
+ return asyncio.create_task(self._headless_change_emscripten(mode))
1361
+
1362
+ def _headless_change_desktop(self, mode=Headless.Normal):
1363
+ for _ in range(3):
1364
+ self.sendCommand(CommandType.Headless, mode.value)
1365
+ time.sleep(0.03)
1366
+
1367
+ async def _headless_change_swarm(self, mode=Headless.Normal):
1368
+ for _ in range(3):
1369
+ await self.sendCommand(CommandType.Headless, mode.value)
1370
+ await asyncio.sleep(0.03)
1371
+
1372
+ async def _headless_change_emscripten(self, mode=Headless.Normal):
1373
+ for _ in range(3):
1374
+ await self.sendCommand(CommandType.Headless, mode.value)
1375
+ await asyncio.sleep(0.03)
1376
+
1303
1377
  def update_motion_data(self, drone_type):
1304
1378
 
1305
1379
  """
@@ -2213,7 +2287,11 @@ class Drone:
2213
2287
  # set the speed to medium level
2214
2288
  self.speed_change(speed_level=2)
2215
2289
  time.sleep(0.2)
2216
-
2290
+ self.control_change(mode=ModeControlFlight.Position)
2291
+ time.sleep(0.2)
2292
+ self.headless_change(mode=Headless.Normal)
2293
+ time.sleep(0.2)
2294
+
2217
2295
  # disable the previous YPRT commands
2218
2296
  self.sendControl(0, 0, 0, 0)
2219
2297
  time.sleep(0.2)
@@ -2295,6 +2373,10 @@ class Drone:
2295
2373
  # set the speed to medium level
2296
2374
  await self.speed_change(speed_level=2)
2297
2375
  await asyncio.sleep(0.2)
2376
+ await self.control_change(mode=ModeControlFlight.Position)
2377
+ await asyncio.sleep(0.2)
2378
+ await self.headless_change(mode=Headless.Normal)
2379
+ await asyncio.sleep(0.2)
2298
2380
 
2299
2381
  # disable the previous YPRT commands
2300
2382
  await self.sendControl(0, 0, 0, 0)
@@ -2342,6 +2424,12 @@ class Drone:
2342
2424
  await self.speed_change(speed_level=2)
2343
2425
  await asyncio.sleep(0.2)
2344
2426
 
2427
+ # put all users in the same control/headless modes
2428
+ await self.control_change(mode=ModeControlFlight.Position)
2429
+ await asyncio.sleep(0.2)
2430
+ await self.headless_change(mode=Headless.Normal)
2431
+ await asyncio.sleep(0.2)
2432
+
2345
2433
  # disable the previous YPRT commands
2346
2434
  await self.sendControl(0, 0, 0, 0)
2347
2435
  await asyncio.sleep(0.2)
@@ -2535,7 +2623,7 @@ class Drone:
2535
2623
 
2536
2624
  if monitor0.monitorDataType == MonitorDataType.F32:
2537
2625
 
2538
- dataCount = (dataArray.len() - 1 - Monitor0.getSize()) / 4
2626
+ dataCount = (len(dataArray) - 1 - Monitor0.getSize()) // 4
2539
2627
 
2540
2628
  for i in range(0, dataCount):
2541
2629
 
@@ -2551,7 +2639,7 @@ class Drone:
2551
2639
 
2552
2640
  self.systemTimeMonitorData = monitor4.systemTime
2553
2641
 
2554
- dataCount = (dataArray.len() - 1 - Monitor4.getSize()) / 4
2642
+ dataCount = (len(dataArray) - 1 - Monitor4.getSize()) // 4
2555
2643
 
2556
2644
  for i in range(0, dataCount):
2557
2645
 
@@ -2567,7 +2655,7 @@ class Drone:
2567
2655
 
2568
2656
  self.systemTimeMonitorData = monitor8.systemTime
2569
2657
 
2570
- dataCount = (dataArray.len() - 1 - Monitor8.getSize()) / 4
2658
+ dataCount = (len(dataArray) - 1 - Monitor8.getSize()) // 4
2571
2659
 
2572
2660
  for i in range(0, dataCount):
2573
2661
 
@@ -3400,7 +3488,7 @@ class Drone:
3400
3488
  """
3401
3489
  :param distance: the numerical value of the value to move
3402
3490
  :param units: can either be in inches, centimeters, meters, feet.
3403
- :param speed: default 1 meter per second. Max is 2 meters/second.
3491
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3404
3492
  :return: N/A
3405
3493
  """
3406
3494
  if sys.platform != 'emscripten' and not self._swarm:
@@ -3489,7 +3577,7 @@ class Drone:
3489
3577
  """
3490
3578
  :param distance: the numerical value of the value to move
3491
3579
  :param units: can either be in inches, centimeters, meters, feet.
3492
- :param speed: default 1 meter per second. Max is 2 meters/second.
3580
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3493
3581
  :return: N/A
3494
3582
  """
3495
3583
  if sys.platform != 'emscripten' and not self._swarm:
@@ -3578,7 +3666,7 @@ class Drone:
3578
3666
  """
3579
3667
  :param distance: the numerical value of the value to move
3580
3668
  :param units: can either be in inches, centimeters, meters, feet.
3581
- :param speed: default 1 meter per second. Max is 2 meters/second.
3669
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3582
3670
  :return: N/A
3583
3671
  """
3584
3672
  if sys.platform != 'emscripten' and not self._swarm:
@@ -3666,7 +3754,7 @@ class Drone:
3666
3754
  """
3667
3755
  :param distance: the numerical value of the value to move
3668
3756
  :param units: can either be in inches, centimeters, meters, feet.
3669
- :param speed: default 1 meter per second. Max is 2 meters/second.
3757
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3670
3758
  :return: N/A
3671
3759
  """
3672
3760
  if sys.platform != 'emscripten' and not self._swarm:
@@ -3750,6 +3838,183 @@ class Drone:
3750
3838
 
3751
3839
  await asyncio.sleep(delay + 1.0)
3752
3840
 
3841
+
3842
+ def move_upward(self, distance, units="cm", speed=0.5):
3843
+ """
3844
+ :param distance: the numerical value of the value to move
3845
+ :param units: can either be in inches, centimeters, meters, feet.
3846
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3847
+ :return: N/A
3848
+ """
3849
+ if sys.platform != 'emscripten' and not self._swarm:
3850
+ return self._move_upward_desktop(distance, units, speed)
3851
+ else:
3852
+ return asyncio.create_task(self._move_upward_emscripten(distance, units, speed))
3853
+
3854
+ def _move_upward_desktop(self, distance, units="cm", speed=0.5):
3855
+ if units == "cm":
3856
+ distance_meters = distance / 100
3857
+ elif units == "ft":
3858
+ distance_meters = distance / 3.28084
3859
+ elif units == "in":
3860
+ distance_meters = distance / 39.37
3861
+ elif units == "m":
3862
+ distance_meters = distance * 1
3863
+ else:
3864
+ print(Fore.RED + "Error: Not a valid unit." + Style.RESET_ALL)
3865
+ return
3866
+
3867
+ # cap the speed
3868
+ if speed > 2:
3869
+ speed = 2
3870
+ elif speed < 0:
3871
+ speed = 0
3872
+
3873
+ self.sendControlPosition(positionX=0,
3874
+ positionY=0,
3875
+ positionZ=distance_meters,
3876
+ velocity=speed,
3877
+ heading=0,
3878
+ rotationalVelocity=0)
3879
+
3880
+ delay = distance_meters / speed
3881
+
3882
+ time.sleep(0.1)
3883
+
3884
+ while self.get_movement_state() != ModeMovement.Moving:
3885
+ self.sendControlPosition(positionX=0, positionY=0, positionZ=distance_meters, velocity=speed,
3886
+ heading=0,
3887
+ rotationalVelocity=0)
3888
+ time.sleep(0.1)
3889
+
3890
+ time.sleep(delay + 1.0)
3891
+
3892
+ async def _move_upward_emscripten(self, distance, units="cm", speed=0.5):
3893
+ if units == "cm":
3894
+ distance_meters = distance / 100
3895
+ elif units == "ft":
3896
+ distance_meters = distance / 3.28084
3897
+ elif units == "in":
3898
+ distance_meters = distance / 39.37
3899
+ elif units == "m":
3900
+ distance_meters = distance * 1
3901
+ else:
3902
+ print("Error: Not a valid unit.", color="error")
3903
+ return
3904
+
3905
+ # cap the speed
3906
+ if speed > 2:
3907
+ speed = 2
3908
+ elif speed < 0:
3909
+ speed = 0
3910
+
3911
+ await self.sendControlPosition(positionX=0,
3912
+ positionY=0,
3913
+ positionZ=distance_meters,
3914
+ velocity=speed,
3915
+ heading=0,
3916
+ rotationalVelocity=0)
3917
+
3918
+ delay = distance_meters / speed
3919
+
3920
+ await asyncio.sleep(0.1)
3921
+
3922
+ while (await self.get_movement_state()) != ModeMovement.Moving:
3923
+ await self.sendControlPosition(positionX=0, positionY=0, positionZ=distance_meters, velocity=speed,
3924
+ heading=0,
3925
+ rotationalVelocity=0)
3926
+ await asyncio.sleep(0.10)
3927
+
3928
+ await asyncio.sleep(delay + 1.0)
3929
+
3930
+ def move_downward(self, distance, units="cm", speed=0.5):
3931
+ """
3932
+ :param distance: the numerical value of the value to move
3933
+ :param units: can either be in inches, centimeters, meters, feet.
3934
+ :param speed: default 0.5 meter per second. Max is 2 meters/second.
3935
+ :return: N/A
3936
+ """
3937
+ if sys.platform != 'emscripten' and not self._swarm:
3938
+ return self._move_downward_desktop(distance, units, speed)
3939
+ else:
3940
+ return asyncio.create_task(self._move_downward_emscripten(distance, units, speed))
3941
+
3942
+ def _move_downward_desktop(self, distance, units="cm", speed=0.5):
3943
+ if units == "cm":
3944
+ distance_meters = distance / 100
3945
+ elif units == "ft":
3946
+ distance_meters = distance / 3.28084
3947
+ elif units == "in":
3948
+ distance_meters = distance / 39.37
3949
+ elif units == "m":
3950
+ distance_meters = distance * 1
3951
+ else:
3952
+ print(Fore.RED + "Error: Not a valid unit." + Style.RESET_ALL)
3953
+ return
3954
+
3955
+ # cap the speed
3956
+ if speed > 2:
3957
+ speed = 2
3958
+ elif speed < 0:
3959
+ speed = 0
3960
+
3961
+ self.sendControlPosition(positionX=0,
3962
+ positionY=0,
3963
+ positionZ=-distance_meters,
3964
+ velocity=speed,
3965
+ heading=0,
3966
+ rotationalVelocity=0)
3967
+
3968
+ delay = distance_meters / speed
3969
+
3970
+ time.sleep(0.1)
3971
+
3972
+ while self.get_movement_state() != ModeMovement.Moving:
3973
+ self.sendControlPosition(positionX=0, positionY=0, positionZ=-distance_meters, velocity=speed,
3974
+ heading=0,
3975
+ rotationalVelocity=0)
3976
+ time.sleep(0.1)
3977
+
3978
+ time.sleep(delay + 1.0)
3979
+
3980
+ async def _move_downward_emscripten(self, distance, units="cm", speed=0.5):
3981
+ if units == "cm":
3982
+ distance_meters = distance / 100
3983
+ elif units == "ft":
3984
+ distance_meters = distance / 3.28084
3985
+ elif units == "in":
3986
+ distance_meters = distance / 39.37
3987
+ elif units == "m":
3988
+ distance_meters = distance * 1
3989
+ else:
3990
+ print("Error: Not a valid unit.", color="error")
3991
+ return
3992
+
3993
+ # cap the speed
3994
+ if speed > 2:
3995
+ speed = 2
3996
+ elif speed < 0:
3997
+ speed = 0
3998
+
3999
+ await self.sendControlPosition(positionX=0,
4000
+ positionY=0,
4001
+ positionZ=-distance_meters,
4002
+ velocity=speed,
4003
+ heading=0,
4004
+ rotationalVelocity=0)
4005
+
4006
+ delay = distance_meters / speed
4007
+
4008
+ await asyncio.sleep(0.1)
4009
+
4010
+ while (await self.get_movement_state()) != ModeMovement.Moving:
4011
+ await self.sendControlPosition(positionX=0, positionY=0, positionZ=-distance_meters, velocity=speed,
4012
+ heading=0,
4013
+ rotationalVelocity=0)
4014
+ await asyncio.sleep(0.10)
4015
+
4016
+ await asyncio.sleep(delay + 1.0)
4017
+
3753
4018
  def send_absolute_position(self, positionX, positionY, positionZ, velocity, heading, rotationalVelocity):
3754
4019
  """
3755
4020
  drone movement command
@@ -4520,7 +4785,7 @@ class Drone:
4520
4785
  """
4521
4786
  A looped method that makes the drone fly forward until it reaches
4522
4787
  a desired distance. The drone will keep that distance.
4523
- The range of front sensor is from 0cm-100cm
4788
+ The range of front sensor is from 0cm-150cm
4524
4789
 
4525
4790
  :param timeout: duration in seconds that function will run
4526
4791
  :param distance: distance in cm the drone will maintain in front of object
@@ -4572,7 +4837,7 @@ class Drone:
4572
4837
  def detect_wall(self, distance=50):
4573
4838
  """
4574
4839
  Returns True when a distance below the threshold is reached.
4575
- The range of front sensor is from 0cm-100cm
4840
+ The range of front sensor is from 0cm-150cm
4576
4841
 
4577
4842
  :param distance: threshold in millimeters that returns True
4578
4843
  :return: Boolean