11#!/usr/bin/env python
22# -*- coding: utf-8 -*-
33"""
4- Copyright (c) 2021 PX4 Development Team
4+ Copyright (c) 2021-2024 PX4 Development Team
55 Redistribution and use in source and binary forms, with or without
66 modification, are permitted provided that the following conditions
77 are met:
@@ -72,6 +72,7 @@ def __init__(self, parent=None):
7272 self .kc = 0.0
7373 self .ki = 0.0
7474 self .kd = 0.0
75+ self .kff = 0.0
7576 self .figure = plt .figure (1 )
7677 self .figure .subplots_adjust (hspace = 0.5 , wspace = 1.0 )
7778 self .num = []
@@ -110,7 +111,7 @@ def __init__(self, parent=None):
110111 pz_group .addRow (QLabel ("Poles" ), self .line_edit_poles )
111112 self .line_edit_delays = QSpinBox ()
112113 self .line_edit_delays .setValue (self .sys_id_delays )
113- self .line_edit_delays .setRange (1 , 1000 )
114+ self .line_edit_delays .setRange (0 , 1000 )
114115 self .line_edit_delays .valueChanged .connect (self .onDelaysChanged )
115116 pz_group .addRow (QLabel ("Delays" ), self .line_edit_delays )
116117 self .btn_run_sys_id = QPushButton ("Run identification" )
@@ -270,14 +271,25 @@ def createPidLayout(self):
270271 layout_d = QHBoxLayout ()
271272 self .slider_d = DoubleSlider (Qt .Horizontal )
272273 self .slider_d .setMinimum (0.0 )
273- self .slider_d .setMaximum (0.05 )
274+ self .slider_d .setMaximum (0.2 )
274275 self .slider_d .setInterval (0.001 )
275276 self .lbl_d = QLabel ("{:.3f}" .format (self .kd ))
276277 layout_d .addWidget (self .slider_d )
277278 layout_d .addWidget (self .lbl_d )
278279 self .slider_d .valueChanged .connect (self .updateLabelD )
279280 layout_pid .addRow (QLabel ("D" ), layout_d )
280281
282+ layout_ff = QHBoxLayout ()
283+ self .slider_ff = DoubleSlider (Qt .Horizontal )
284+ self .slider_ff .setMinimum (0.0 )
285+ self .slider_ff .setMaximum (1.0 )
286+ self .slider_ff .setInterval (0.01 )
287+ self .lbl_ff = QLabel ("{:.3f}" .format (self .kff ))
288+ layout_ff .addWidget (self .slider_ff )
289+ layout_ff .addWidget (self .lbl_ff )
290+ self .slider_ff .valueChanged .connect (self .updateLabelFF )
291+ layout_pid .addRow (QLabel ("FF" ), layout_ff )
292+
281293 return layout_pid
282294
283295 def updateLabelK (self ):
@@ -298,6 +310,12 @@ def updateLabelD(self):
298310 if self .slider_d .isSliderDown ():
299311 self .updateClosedLoop ()
300312
313+ def updateLabelFF (self ):
314+ self .kff = self .slider_ff .value ()
315+ self .lbl_ff .setText ("{:.3f}" .format (self .kff ))
316+ if self .slider_ff .isSliderDown ():
317+ self .updateClosedLoop ()
318+
301319 def createGmvcLayout (self ):
302320 layout_gmvc = QFormLayout ()
303321
@@ -412,7 +430,7 @@ def replayInputData(self):
412430 return
413431 d = self .sysid .d
414432 u_detrended = detrend (self .u )
415- u_delayed = np .concatenate (([0 for k in range (d )], u_detrended [0 :- d ]))
433+ u_delayed = np .concatenate (([0 for k in range (d )], u_detrended [0 :( len ( u_detrended ) - d ) ]))
416434 self .t_est , self .y_est = ctrl .forced_response (self .Gz , T = self .t , U = u_delayed )
417435 if len (self .t_est ) > len (self .y_est ):
418436 self .t_est = self .t_est [0 :len (self .y_est - 1 )]
@@ -494,6 +512,8 @@ def computeController(self):
494512 (self .kc , self .ki , self .kd ) = computePidGmvc (self .num , self .den , self .dt , sigma , delta , lbda )
495513 #TODO:find a better solution
496514 self .ki /= 5.0
515+ static_gain = sum (self .num ) / sum (self .den )
516+ self .kff = 1 / static_gain
497517 # (self.kc, self.ki, self.kd) = computePidDahlin(self.num, self.den, self.dt, sigma)
498518
499519 self .updateKIDSliders ()
@@ -503,6 +523,7 @@ def updateKIDSliders(self):
503523 self .slider_k .setValue (self .kc )
504524 self .slider_i .setValue (self .ki )
505525 self .slider_d .setValue (self .kd )
526+ self .slider_ff .setValue (self .kff )
506527
507528 def updateClosedLoop (self ):
508529 if not self .is_system_identified :
@@ -514,11 +535,12 @@ def updateClosedLoop(self):
514535 kc = self .kc
515536 ki = self .ki
516537 kd = self .kd
538+ kff = self .kff
517539 Gd = ctrl .TransferFunction ([1 ], np .append ([1 ], np .zeros (self .sys_id_delays )), dt )
518540 Gz2 = ctrl .TransferFunction (num , den , dt )
519541 (pid_num , pid_den ) = gainsToNumDen (kc , ki , kd , dt )
520542 PID = ctrl .TransferFunction (pid_num , pid_den , dt )
521- Gcl = ctrl . feedback ( PID * Gd * Gz2 , 1 )
543+ Gcl = ( kff * Gd * Gz2 + PID * Gd * Gz2 ) / ( 1 + PID * Gd * Gz2 )
522544 t_out ,y_out = ctrl .step_response (Gcl , T = np .arange (0 ,1 ,dt ))
523545 self .plotClosedLoop (t_out , y_out )
524546 w = np .logspace (- 1 , 3 , 40 ).tolist ()
0 commit comments