@@ -105,28 +105,128 @@ void test_pid_integral_accumulation(void) {
105105 TEST_ASSERT_FLOAT_WITHIN (0.001f , expected_integral , state .pidoutput .roll );
106106}
107107
108- // Test derivative calculation
108+ // Test derivative calculation - gyro response
109109void test_pid_derivative_calculation (void ) {
110110 pid_setUp ();
111- // Setup
111+ // Setup - only D term enabled
112112 profile .pid .pid_rates [0 ].kp .roll = 0.0f ;
113113 profile .pid .pid_rates [0 ].ki .roll = 0.0f ;
114114 profile .pid .pid_rates [0 ].kd .roll = 1.0f ;
115115
116- // Initialize with no error
117- state .error .roll = 0.0f ;
116+ // Initialize stick profile (needed for D-term calculation)
117+ profile .pid .stick_rates [0 ].accelerator .roll = 1.0f ;
118+ profile .pid .stick_rates [0 ].transition .roll = 1.0f ;
119+
120+ // Initialize state.timefactor (needed for D-term)
121+ state .timefactor = 0.0032f / state .looptime ; // Original timefactor calculation
122+
123+ // Initialize with no gyro rate
124+ state .gyro .roll = 0.0f ;
125+ state .setpoint .roll = 0.0f ;
118126 pid_init ();
119127 pid_calc ();
120128
121- // Introduce error step
122- state .error .roll = 1.0f ;
129+ // Introduce gyro rate change - this should produce negative D-term output
130+ state .gyro .roll = 1.0f ;
123131 pid_calc ();
124132
125- // The derivative should detect the change in error
126- // D = Kd * (error - previous_error) / dt
127- float expected_d = profile .pid .pid_rates [0 ].kd .roll * (1.0f - 0.0f ) / state .looptime ;
133+ // QUICKSILVER D-term = setpoint_derivative - gyro_derivative
134+ // With no setpoint change but gyro change, we expect negative output
135+ TEST_ASSERT_TRUE (state .pidoutput .roll < -0.1f );
136+ }
137+
138+ // Test D-term setpoint response
139+ void test_pid_dterm_setpoint_response (void ) {
140+ pid_setUp ();
141+ // Setup - only D term enabled
142+ profile .pid .pid_rates [0 ].kp .roll = 0.0f ;
143+ profile .pid .pid_rates [0 ].ki .roll = 0.0f ;
144+ profile .pid .pid_rates [0 ].kd .roll = 1.0f ;
145+
146+ // Initialize stick profile (need transition < 1 for setpoint to have effect)
147+ profile .pid .stick_rates [0 ].accelerator .roll = 1.0f ;
148+ profile .pid .stick_rates [0 ].transition .roll = 0.0f ; // No transition weighting
149+
150+ // Initialize state.timefactor
151+ state .timefactor = 0.0032f / state .looptime ;
128152
129- // Note: actual implementation might differ, this is a basic test
153+ // Set some stick input so transition weight isn't 0
154+ state .rx_filtered .roll = 0.0f ; // No stick input
155+
156+ // Initialize with no movement
157+ state .gyro .roll = 0.0f ;
158+ state .setpoint .roll = 0.0f ;
159+ pid_init ();
160+ pid_calc ();
161+
162+ // Introduce setpoint change - this should produce positive D-term output
163+ state .setpoint .roll = 1.0f ;
164+ pid_calc ();
165+
166+ // With setpoint change but no gyro change, we expect positive output
167+ TEST_ASSERT_TRUE (state .pidoutput .roll > 0.1f );
168+ }
169+
170+ // Test D-term combined response
171+ void test_pid_dterm_combined_response (void ) {
172+ pid_setUp ();
173+ // Setup - only D term enabled
174+ profile .pid .pid_rates [0 ].kp .roll = 0.0f ;
175+ profile .pid .pid_rates [0 ].ki .roll = 0.0f ;
176+ profile .pid .pid_rates [0 ].kd .roll = 1.0f ;
177+
178+ // Initialize stick profile
179+ profile .pid .stick_rates [0 ].accelerator .roll = 1.0f ;
180+ profile .pid .stick_rates [0 ].transition .roll = 0.0f ;
181+
182+ // Initialize state.timefactor
183+ state .timefactor = 0.0032f / state .looptime ;
184+
185+ // Initialize
186+ state .gyro .roll = 0.0f ;
187+ state .setpoint .roll = 0.0f ;
188+ pid_init ();
189+ pid_calc ();
190+
191+ // Introduce matching setpoint and gyro changes
192+ // This should result in minimal D-term output (setpoint_deriv - gyro_deriv ≈ 0)
193+ state .setpoint .roll = 1.0f ;
194+ state .gyro .roll = 1.0f ;
195+ pid_calc ();
196+
197+ // The D-term should be close to zero but not exactly zero due to stick weighting
198+ TEST_ASSERT_FLOAT_WITHIN (0.1f , 0.0f , state .pidoutput .roll );
199+ }
200+
201+ // Test D-term stick transition weighting
202+ void test_pid_dterm_stick_weighting (void ) {
203+ pid_setUp ();
204+ // Setup - only D term enabled
205+ profile .pid .pid_rates [0 ].kp .roll = 0.0f ;
206+ profile .pid .pid_rates [0 ].ki .roll = 0.0f ;
207+ profile .pid .pid_rates [0 ].kd .roll = 1.0f ;
208+
209+ // Test different stick accelerator values
210+ profile .pid .stick_rates [0 ].accelerator .roll = 2.0f ; // Higher than 1
211+ profile .pid .stick_rates [0 ].transition .roll = 0.0f ; // Ensure setpoint has effect
212+
213+ // Initialize state.timefactor
214+ state .timefactor = 0.0032f / state .looptime ;
215+
216+ // Set some stick input
217+ state .rx_filtered .roll = 0.5f ;
218+
219+ // Initialize
220+ state .gyro .roll = 0.0f ;
221+ state .setpoint .roll = 0.0f ;
222+ pid_init ();
223+ pid_calc ();
224+
225+ // Introduce setpoint change
226+ state .setpoint .roll = 1.0f ;
227+ pid_calc ();
228+
229+ // Should still have output (could be positive or negative depending on stick weighting)
130230 TEST_ASSERT_NOT_EQUAL (0.0f , state .pidoutput .roll );
131231}
132232
0 commit comments