16
16
17
17
from __future__ import annotations
18
18
19
- from collections import deque
20
19
from datetime import datetime
21
- from statistics import fmean
22
20
from typing import Any
23
21
24
22
import monotonic
23
+ from pymavlink import mavutil
25
24
26
25
import pymavswarm .state as swarm_state
27
26
from pymavswarm .mission import SwarmMission
@@ -81,23 +80,16 @@ def __init__(
81
80
self .__gps_info = swarm_state .GPSInfo (
82
81
0.0 , 0.0 , 0 , 0 , optional_context_props = context_props
83
82
)
84
- self .__position = swarm_state .Position (
85
- 0.0 , 0.0 , 0.0 , optional_context_props = context_props
86
- )
83
+ self .__position = swarm_state .Position (optional_context_props = context_props )
87
84
self .__ekf = swarm_state .EKFStatus (
88
85
0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , optional_context_props = context_props
89
86
)
90
87
self .__telemetry = swarm_state .Telemetry (
91
88
0.0 , optional_context_props = context_props
92
89
)
93
- self .__velocity = swarm_state .Velocity (
94
- 0.0 , 0.0 , 0.0 , optional_context_props = context_props
95
- )
96
- self .__prev_velocity = swarm_state .Velocity (
97
- 0.0 , 0.0 , 0.0 , optional_context_props = context_props
98
- )
90
+ self .__velocity = swarm_state .Velocity (optional_context_props = context_props )
99
91
self .__acceleration = swarm_state .Acceleration (
100
- 0.0 , 0.0 , 0.0 , optional_context_props = context_props
92
+ optional_context_props = context_props
101
93
)
102
94
self .__armed = swarm_state .Generic (
103
95
"armed" , False , optional_context_props = context_props
@@ -129,23 +121,23 @@ def __init__(
129
121
self .__last_params_read = swarm_state .ParameterList (
130
122
max_length = max_params_stored , optional_context_props = context_props
131
123
)
132
- self .__home_position = swarm_state .Position (
133
- 0.0 , 0.0 , 0.0 , optional_context_props = context_props
124
+ self .__home_position = swarm_state .Vector (
125
+ 0.0 ,
126
+ 0.0 ,
127
+ 0.0 ,
128
+ mavutil .mavlink .MAV_FRAME_GLOBAL ,
129
+ 0.0 ,
130
+ optional_context_props = context_props ,
134
131
)
135
132
self .__hrl_state = swarm_state .Generic (
136
133
"hrl_state" , None , optional_context_props = context_props
137
134
)
138
135
self .__ping = swarm_state .Generic (
139
136
"ping" , 0 , optional_context_props = context_props
140
137
)
141
- self .__last_position_message_timestamp = swarm_state .Generic (
142
- "time_boot_ms " , 0 , optional_context_props = context_props
138
+ self .__clock_offset = swarm_state .Generic (
139
+ "clock_offset " , 0 , optional_context_props = context_props
143
140
)
144
- self .__clock_offset : deque [int ] = deque (maxlen = 5 )
145
-
146
- # Initialize the clock offset with a value so that we have something to access
147
- # at boot
148
- self .__clock_offset .append (0 )
149
141
150
142
return
151
143
@@ -249,16 +241,6 @@ def velocity(self) -> swarm_state.Velocity:
249
241
"""
250
242
return self .__velocity
251
243
252
- @property
253
- def previous_velocity (self ) -> swarm_state .Velocity :
254
- """
255
- Velocity of the agent at the previous measurement.
256
-
257
- return: agent's previous velocity
258
- :rtype: Velocity
259
- """
260
- return self .__prev_velocity
261
-
262
244
@property
263
245
def acceleration (self ) -> swarm_state .Acceleration :
264
246
"""
@@ -370,7 +352,7 @@ def last_params_read(self) -> swarm_state.ParameterList:
370
352
return self .__last_params_read
371
353
372
354
@property
373
- def home_position (self ) -> swarm_state .Position :
355
+ def home_position (self ) -> swarm_state .Vector :
374
356
"""
375
357
Home position of the agent.
376
358
@@ -400,36 +382,14 @@ def ping(self) -> Generic:
400
382
return self .__ping
401
383
402
384
@property
403
- def last_position_message_timestamp (self ) -> Generic :
404
- """
405
- Most recent time that the agent sent the position message in the global clock.
406
-
407
- :return: time since boot [ms]
408
- :rtype: Generic
385
+ def clock_offset (self ) -> Generic :
409
386
"""
410
- return self .__last_position_message_timestamp
411
-
412
- def update_clock_offset (self , offset : int ) -> None :
413
- """
414
- Update the agent clock offset relative to the source clock.
415
-
416
- :param offset: clock offset
417
- :type offset: int
418
- """
419
- self .__clock_offset .append (offset )
420
- return
421
-
422
- @property
423
- def clock_offset (self ) -> int :
424
- """
425
- Average offset between the source clock and agent clock.
426
-
427
- This property does not implement a watcher interface.
387
+ Clock offset from the global clock.
428
388
429
389
:return: clock offset
430
- :rtype: int
390
+ :rtype: Generic
431
391
"""
432
- return int ( fmean ( self .__clock_offset ))
392
+ return self .__clock_offset
433
393
434
394
def compute_reachable_set (
435
395
self ,
@@ -438,11 +398,14 @@ def compute_reachable_set(
438
398
reach_time : float ,
439
399
initial_step_size : float = 0.5 ,
440
400
reach_timeout : float = 0.001 ,
441
- uses_lat_lon : bool = True ,
442
401
) -> tuple [HyperRectangle , float ]:
443
402
"""
444
403
Compute the current reachable set of the agent.
445
404
405
+ In the current state of the system, the reachable set is only computed using
406
+ the global frame. In the future, if transformations between frames is
407
+ implemented, reachable set computation for multiple frames may be supported.
408
+
446
409
:param position_error: 3D position error to account for in the measurement
447
410
:type position_error: float
448
411
:param velocity_error: 3D velocity error to account for in the measurement
@@ -460,103 +423,71 @@ def compute_reachable_set(
460
423
from the start time
461
424
:rtype: tuple[HyperRectangle, float]
462
425
"""
463
- if uses_lat_lon :
464
- rect = HyperRectangle (
465
- [
466
- # When computing the reachable state for the GPS position, we pass
467
- # the origin as the position. After computing what the reachable
468
- # change, we correct the original lat/lon position. This
469
- # helps us eliminate *some* error that occurs during
470
- # conversions.
471
- Interval (- position_error , position_error ),
472
- Interval (- position_error , position_error ),
473
- Interval (
474
- self .position .z - position_error ,
475
- self .position .z + position_error ,
476
- ),
477
- Interval (
478
- self .velocity .x - velocity_error ,
479
- self .velocity .x + velocity_error ,
480
- ),
481
- Interval (
482
- self .velocity .y - velocity_error ,
483
- self .velocity .y + velocity_error ,
484
- ),
485
- Interval (
486
- self .velocity .z - velocity_error ,
487
- self .velocity .z + velocity_error ,
488
- ),
489
- ]
490
- )
491
- else :
492
- rect = HyperRectangle (
493
- [
494
- Interval (
495
- self .position .x - position_error ,
496
- self .position .x + position_error ,
497
- ),
498
- Interval (
499
- self .position .y - position_error ,
500
- self .position .y + position_error ,
501
- ),
502
- Interval (
503
- self .position .z - position_error ,
504
- self .position .z + position_error ,
505
- ),
506
- Interval (
507
- self .velocity .x - velocity_error ,
508
- self .velocity .x + velocity_error ,
509
- ),
510
- Interval (
511
- self .velocity .y - velocity_error ,
512
- self .velocity .y + velocity_error ,
513
- ),
514
- Interval (
515
- self .velocity .z - velocity_error ,
516
- self .velocity .z + velocity_error ,
517
- ),
518
- ]
519
- )
426
+ # When computing the reachable state for the GPS position, we pass
427
+ # the origin as the position. After computing what the reachable
428
+ # change, we correct the original lat/lon position. This
429
+ # helps us eliminate *some* error that occurs during
430
+ # conversions.
431
+ rect = HyperRectangle (
432
+ [
433
+ Interval (- position_error , position_error ),
434
+ Interval (- position_error , position_error ),
435
+ Interval (
436
+ self .position .global_frame .z - position_error ,
437
+ self .position .global_frame .z + position_error ,
438
+ ),
439
+ Interval (
440
+ self .velocity .global_frame .x - velocity_error ,
441
+ self .velocity .global_frame .x + velocity_error ,
442
+ ),
443
+ Interval (
444
+ self .velocity .global_frame .y - velocity_error ,
445
+ self .velocity .global_frame .y + velocity_error ,
446
+ ),
447
+ Interval (
448
+ self .velocity .global_frame .z - velocity_error ,
449
+ self .velocity .global_frame .z + velocity_error ,
450
+ ),
451
+ ]
452
+ )
520
453
521
454
# Compute the sender's reachable state
522
455
(
523
456
reachable_state ,
524
457
reach_time_elapsed ,
525
458
) = SafetyChecker .face_lifting_iterative_improvement (
526
459
rect ,
527
- self .last_position_message_timestamp . value ,
460
+ self .position . global_frame . timestamp ,
528
461
(
529
- self .acceleration .x ,
530
- self .acceleration .y ,
531
- self .acceleration .z ,
462
+ self .acceleration .global_frame . x ,
463
+ self .acceleration .global_frame . y ,
464
+ self .acceleration .global_frame . z ,
532
465
),
533
466
reach_time ,
534
467
initial_step_size = initial_step_size ,
535
468
timeout = reach_timeout ,
536
469
)
537
470
538
- if uses_lat_lon :
539
- # Correct the latitude using the reachable positions
540
- reachable_state .intervals [0 ].interval_min = latitude_conversion (
541
- self .position .x ,
542
- reachable_state .intervals [0 ].interval_min ,
543
- )
544
- reachable_state .intervals [0 ].interval_max = latitude_conversion (
545
- self .position .x ,
546
- reachable_state .intervals [0 ].interval_max ,
547
- )
548
-
549
- # Correct the longitude using the reachable positions
550
- reachable_state .intervals [1 ].interval_min = longitude_conversion (
551
- self .position .x ,
552
- self .position .y ,
553
- reachable_state .intervals [1 ].interval_min ,
554
- )
555
- reachable_state .intervals [1 ].interval_max = longitude_conversion (
556
- self .position .x ,
557
- self .position .y ,
558
- reachable_state .intervals [1 ].interval_max ,
559
- )
471
+ # Correct the positions to use latitude and longitude
472
+ reachable_state .intervals [0 ].interval_min = latitude_conversion (
473
+ self .position .global_frame .x ,
474
+ reachable_state .intervals [0 ].interval_min ,
475
+ )
476
+ reachable_state .intervals [0 ].interval_max = latitude_conversion (
477
+ self .position .global_frame .x ,
478
+ reachable_state .intervals [0 ].interval_max ,
479
+ )
480
+
481
+ reachable_state .intervals [1 ].interval_min = longitude_conversion (
482
+ self .position .global_frame .x ,
483
+ self .position .global_frame .y ,
484
+ reachable_state .intervals [1 ].interval_min ,
485
+ )
486
+ reachable_state .intervals [1 ].interval_max = longitude_conversion (
487
+ self .position .global_frame .x ,
488
+ self .position .global_frame .y ,
489
+ reachable_state .intervals [1 ].interval_max ,
490
+ )
560
491
561
492
return reachable_state , reach_time_elapsed
562
493
0 commit comments