@@ -186,7 +186,7 @@ def update(
186186 if self .debug_hook is not None :
187187 self .debug_hook ({
188188 "err_position" : err_position ,
189- "output_pi" : 57.3 * measurement_rate ,
189+ "output_pi" : output_pi ,
190190 "feedback_speed" : feedback_speed ,
191191 "measurement_rate" : 57.3 * measurement_rate ,
192192 "out" : out ,
@@ -195,33 +195,132 @@ def update(
195195 return out
196196
197197class PitchController (BaseController ):
198- def update (self , setpoint : float , measurement : float , measurement_rate : float , dt : float ) -> float :
199- # same structure as yaw but error normalized for angles
200- err = normalize_angle_deg (setpoint - measurement )
201- stage = err * self .K_1
202- res_p = stage * self .K_p
203- res_i = self .trapezoidal_integrate (stage * self .K_i , dt )
204- output_pi = res_p + res_i
198+ def update (
199+ self ,
200+ setpoint : float ,
201+ measurement : float ,
202+ measurement_rate : float ,
203+ dt : float ,
204+ flag_setup_feedback_speed : bool ,
205+ param_update : dict | None = None
206+ ) -> float :
207+
208+ if param_update :
209+ self .apply_params (** param_update )
210+
211+ dt = max (min (dt , 0.05 ), 1e-3 )
212+
213+ # --- позиционный контур ---
214+ if flag_setup_feedback_speed :
215+ err_position = 0.0
216+ output_pi = 0.0
217+ setspeed = setpoint
218+ else :
219+ err_position = normalize_angle_deg (setpoint - measurement )
220+ stage = err_position * self .K_1
221+ res_p = stage * self .K_p
222+ res_i = self .trapezoidal_integrate (stage * self .K_i , dt )
223+ output_pi = res_p + res_i
224+ setspeed = 0.0
225+
226+ # --- ОС по скорости ---
205227 ap = self .aperiodic_step (measurement_rate , dt )
206228 feedback_speed = ap * self .K_2
207- out = output_pi - feedback_speed
229+
230+ error_speed = output_pi + setspeed - feedback_speed
231+
208232 if self .out_sat is not None :
209- out = saturation (out , self .out_sat , - self .out_sat )
233+ out = saturation (error_speed , self .out_sat , - self .out_sat )
234+ else :
235+ out = error_speed
236+
237+ # --- DEBUG ---
238+ if self .debug_hook is not None :
239+ self .debug_hook ({
240+ "err_position" : err_position ,
241+ "output_pi" : output_pi ,
242+ "measurement_rate" : measurement_rate ,
243+ "feedback_speed" : feedback_speed ,
244+ "error_speed" : error_speed ,
245+ "out" : out ,
246+ })
247+
210248 return out
211249
212250class RollController (BaseController ):
213- def update (self , setpoint : float , measurement : float , measurement_rate : float , dt : float ) -> float :
214- # same as pitch
215- err = normalize_angle_deg (setpoint - measurement )
216- stage = err * self .K_1
217- res_p = stage * self .K_p
218- res_i = self .trapezoidal_integrate (stage * self .K_i , dt )
219- output_pi = res_p + res_i
251+ def __init__ (
252+ self ,
253+ * args ,
254+ grav_bias : float = 0.0 ,
255+ grav_gain : float = 0.0 ,
256+ grav_offset_deg : float = 0.0 ,
257+ ** kwargs
258+ ):
259+ super ().__init__ (* args , ** kwargs )
260+ self .grav_bias = grav_bias
261+ self .grav_gain = grav_gain
262+ self .grav_offset_deg = grav_offset_deg
263+
264+ def update (
265+ self ,
266+ setpoint : float ,
267+ measurement : float ,
268+ measurement_rate : float ,
269+ dt : float ,
270+ flag_setup_feedback_speed : bool ,
271+ param_update : dict | None = None
272+ ) -> float :
273+
274+ if param_update :
275+ self .apply_params (** param_update )
276+
277+ dt = max (min (dt , 0.05 ), 1e-3 )
278+
279+ # -------- режим настройки скорости --------
280+ if flag_setup_feedback_speed :
281+ output_pi = 0.0
282+ err_position = 0.0
283+ setspeed = setpoint
284+ else :
285+ # -------- позиционный контур --------
286+ err_position = normalize_angle_deg (setpoint - measurement )
287+ stage = err_position * self .K_1
288+ res_p = stage * self .K_p
289+ res_i = self .trapezoidal_integrate (stage * self .K_i , dt )
290+ output_pi = res_p + res_i
291+ setspeed = 0.0
292+
293+ # -------- гравитационная компенсация --------
294+ grav = (
295+ self .grav_bias
296+ + math .sin (math .radians (measurement - self .grav_offset_deg ))
297+ * self .grav_gain
298+ )
299+
300+ # -------- ОС по скорости --------
220301 ap = self .aperiodic_step (measurement_rate , dt )
221302 feedback_speed = ap * self .K_2
222- out = output_pi - feedback_speed
303+
304+ # -------- итог --------
305+ error_speed = output_pi + grav + setspeed - feedback_speed
306+
223307 if self .out_sat is not None :
224- out = saturation (out , self .out_sat , - self .out_sat )
308+ out = saturation (error_speed , self .out_sat , - self .out_sat )
309+ else :
310+ out = error_speed
311+
312+ if self .debug_hook is not None :
313+ self .debug_hook ({
314+ "err_position" : err_position ,
315+ "output_pi" : output_pi ,
316+ "measurement_rate" : measurement_rate ,
317+ "feedback_speed" : feedback_speed ,
318+ "grav" : grav ,
319+ "error_speed" : error_speed ,
320+ "out" : out ,
321+ })
322+
323+
225324 return out
226325
227326# -----------------------
0 commit comments