18
18
--rtsp-server rtsp://192.168.1.204:8554/fpv_stream
19
19
20
20
3. Run controller on RPi4 companion computer using an RTSP stream from
21
- a SIYI A8 camea .
21
+ a SIYI A8 camera .
22
22
23
23
python ./onboard_controller.py
24
24
--master 192.168.144.171:15001
@@ -133,7 +133,7 @@ def __init__(self, device, sysid, cmpid, rtsp_url):
133
133
# mavlink connection
134
134
self ._connection = None
135
135
136
- # list of controllers to forward mavlink message to
136
+ # list of controllers to forward mavlink messages
137
137
self ._controllers = []
138
138
self ._camera_controller = None
139
139
self ._gimbal_controller = None
@@ -180,7 +180,7 @@ def _mavlink_recv_task(self):
180
180
"""
181
181
Task to receive a mavlink message and forwward to controllers.
182
182
"""
183
- update_rate = 1000.0
183
+ update_rate = 1000.0 # Hz
184
184
update_period = 1.0 / update_rate
185
185
186
186
while True :
@@ -248,10 +248,19 @@ def run(self):
248
248
tracking_rect_changed = True
249
249
250
250
# TODO: how to ensure consistency of frame updates with GCS?
251
- fps = 50
252
- update_rate = fps
251
+ update_rate = 50.0 # Hz
253
252
update_period = 1.0 / update_rate
254
253
254
+ # TODO: consolidate common code - also used in GUI
255
+ # request gimbal device attitude status
256
+ gimbal_device_attitude_status_rate = 50.0 # Hz
257
+ interval_us = int (1e6 / gimbal_device_attitude_status_rate )
258
+ self .send_set_message_interval_message (
259
+ mavutil .mavlink .MAVLINK_MSG_ID_GIMBAL_DEVICE_ATTITUDE_STATUS ,
260
+ interval_us , # requested interval in microseconds
261
+ response_target = 1 , # flight-stack default
262
+ )
263
+
255
264
frame_count = 0
256
265
while True :
257
266
start_time = time .time ()
@@ -323,6 +332,23 @@ def __compare_rect(rect1, rect2):
323
332
sleep_time = max (0.0 , update_period - elapsed_time )
324
333
time .sleep (sleep_time )
325
334
335
+ def send_set_message_interval_message (
336
+ self , message_id , interval_us , response_target = 1
337
+ ):
338
+ self ._connection .mav .command_long_send (
339
+ self ._connection .target_system , # target_system
340
+ self ._connection .target_component , # target_component
341
+ mavutil .mavlink .MAV_CMD_SET_MESSAGE_INTERVAL , # command
342
+ 0 , # confirmation
343
+ message_id , # param1
344
+ interval_us , # param2
345
+ 0 , # param3
346
+ 0 , # param4
347
+ 0 , # param5
348
+ 0 , # param6
349
+ response_target , # param7
350
+ )
351
+
326
352
327
353
class VideoStream :
328
354
"""
@@ -490,8 +516,8 @@ class CameraTrackController:
490
516
491
517
def __init__ (self , connection ):
492
518
self ._connection = connection
493
- self ._sysid = self ._connection .source_system
494
- self ._cmpid = self . _connection . source_component
519
+ self ._sysid = self ._connection .source_system # system id matches vehicle
520
+ self ._cmpid = 1 # component id matches autopilot
495
521
496
522
print (
497
523
f"Camera Track Controller: "
@@ -721,7 +747,7 @@ def _mavlink_task(self):
721
747
sysid = self ._sysid
722
748
cmpid = self ._cmpid
723
749
724
- update_rate = 1000.0
750
+ update_rate = 1000.0 # Hz
725
751
update_period = 1.0 / update_rate
726
752
727
753
while True :
@@ -758,7 +784,7 @@ def _send_status_task(self):
758
784
# TODO: stop sending image status when tracking stopped
759
785
# TODO: set streaming rate using MAV_CMD_SET_MESSAGE_INTERVAL
760
786
761
- update_rate = 2.0
787
+ update_rate = 20.0 # Hz
762
788
update_period = 1.0 / update_rate
763
789
764
790
while True :
@@ -780,8 +806,8 @@ class GimbalController:
780
806
781
807
def __init__ (self , connection ):
782
808
self ._connection = connection
783
- self ._sysid = self ._connection .source_system
784
- self ._cmpid = self . _connection . source_component
809
+ self ._sysid = self ._connection .source_system # system id matches vehicle
810
+ self ._cmpid = 1 # component id matches autopilot
785
811
786
812
print (f"Gimbal Controller: src_sys: { self ._sysid } , src_cmp: { self ._cmpid } )" )
787
813
@@ -805,9 +831,8 @@ def __init__(self, connection):
805
831
self ._gimbal_failure_flags = None
806
832
807
833
# TODO: add options for PI controller gains
808
- # PI controllers: SIYI A8: 0.1, Gazebo: 0.3
809
- self ._pitch_controller = PI_controller (Pgain = 0.5 , Igain = 0.01 , IMAX = 1.0 )
810
- self ._yaw_controller = PI_controller (Pgain = 0.5 , Igain = 0.01 , IMAX = 1.0 )
834
+ self ._pitch_controller = PI_controller (Pgain = 0.1 , Igain = 0.01 , IMAX = 0.1 )
835
+ self ._yaw_controller = PI_controller (Pgain = 0.1 , Igain = 0.1 , IMAX = 1.0 )
811
836
812
837
# Start the control thread
813
838
self ._control_in_queue = queue .Queue ()
@@ -886,6 +911,9 @@ def _control_task(self):
886
911
# the current mount orientation.
887
912
_ , ay , az = euler .quat2euler (gimbal_orientation )
888
913
914
+ self ._pitch_controller .gain_mul = 4.0
915
+ self ._yaw_controller .gain_mul = 40.0
916
+
889
917
err_pitch = self ._neutral_y - ay
890
918
pitch_rate_rads = self ._pitch_controller .run (err_pitch )
891
919
@@ -909,6 +937,9 @@ def _control_task(self):
909
937
err_x = act_x - tgt_x
910
938
err_y = - (act_y - tgt_y )
911
939
940
+ self ._pitch_controller .gain_mul = 1.0
941
+ self ._yaw_controller .gain_mul = 2.0
942
+
912
943
err_pitch = math .radians (err_y )
913
944
pitch_rate_rads = self ._pitch_controller .run (err_pitch )
914
945
@@ -942,8 +973,6 @@ def __process_message():
942
973
return
943
974
msg = self ._control_in_queue .get ()
944
975
mtype = msg .get_type ()
945
- # NOTE: GIMBAL_DEVICE_ATTITUDE_STATUS is broadcast
946
- # (sysid=0, cmpid=0)
947
976
if msg and mtype == "GIMBAL_DEVICE_ATTITUDE_STATUS" :
948
977
with self ._mavlink_lock :
949
978
self ._gimbal_device_flags = msg .flags
0 commit comments