Skip to content

Commit 5c94e15

Browse files
committed
pid: add better tests
1 parent 22d31f0 commit 5c94e15

File tree

2 files changed

+116
-10
lines changed

2 files changed

+116
-10
lines changed

test/test_native/test_main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ extern void test_filter_cascade(void);
1414
extern void test_pid_proportional_control(void);
1515
extern void test_pid_integral_accumulation(void);
1616
extern void test_pid_derivative_calculation(void);
17+
extern void test_pid_dterm_setpoint_response(void);
18+
extern void test_pid_dterm_combined_response(void);
19+
extern void test_pid_dterm_stick_weighting(void);
1720
extern void test_pid_voltage_compensation(void);
1821
extern void test_pid_complete_loop(void);
1922

@@ -104,6 +107,9 @@ int main(int argc, char **argv) {
104107
RUN_TEST(test_pid_proportional_control);
105108
RUN_TEST(test_pid_integral_accumulation);
106109
RUN_TEST(test_pid_derivative_calculation);
110+
RUN_TEST(test_pid_dterm_setpoint_response);
111+
RUN_TEST(test_pid_dterm_combined_response);
112+
RUN_TEST(test_pid_dterm_stick_weighting);
107113
RUN_TEST(test_pid_voltage_compensation);
108114
RUN_TEST(test_pid_complete_loop);
109115

test/test_native/test_pid.c

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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
109109
void 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

Comments
 (0)