Make rollback execution logic flight-ready#14
Conversation
- Added comprehensive input validation to `execute_rollback_plan` in `src/raps/rollback_execution.hpp`:
- Check `RollbackPlan::valid` flag.
- Check for negative thrust.
- Check for non-finite gimbal angles.
- Check for empty transaction ID generation.
- Added necessary includes for `RollbackPlan` and `PlatformHAL` types.
- Created `tests/sil/test_rollback_execution.cpp` to verify validation logic.
- Updated `tests/sil/CMakeLists.txt` to include the new test.
This ensures that only valid and safe rollback commands are sent to the actuator interface, improving system robustness and flight readiness.
Co-authored-by: dfeen87 <158860247+dfeen87@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
This pull request enhances the safety and robustness of the rollback execution logic in the RAPS (Rocket Autonomous Protection System) by adding validation checks to prevent invalid control commands from being executed. The changes add input validation for the rollback plan's validity flag and control parameters (thrust and gimbal angles), along with a new test suite to verify these validations.
Changes:
- Added strict validation to
execute_rollback_planto reject invalid plans, negative thrust, and non-finite gimbal angles - Created new SIL test suite to verify rollback execution validation logic
- Added CMake configuration for the new test executable
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| src/raps/rollback_execution.hpp | Added validation checks for rollback plan validity and control input sanity (negative thrust, infinite/NaN gimbal angles) |
| tests/sil/test_rollback_execution.cpp | New test suite verifying validation of invalid plans, negative thrust, and infinite gimbal angles |
| tests/sil/CMakeLists.txt | Added build configuration for new rollback execution test executable following existing SIL test patterns |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 3. Infinite gimbal | ||
| plan.thrust_magnitude_kN = 100.0f; | ||
| plan.gimbal_theta_rad = std::numeric_limits<float>::infinity(); | ||
| bool res3 = execute_rollback_plan(plan, tx_id); | ||
| expect_false(res3, "execute_rollback_plan fails for infinite gimbal"); | ||
|
|
||
| // 4. Valid plan | ||
| plan.valid = true; | ||
| plan.thrust_magnitude_kN = 50.0f; | ||
| plan.gimbal_theta_rad = 0.1f; | ||
| bool res4 = execute_rollback_plan(plan, tx_id); | ||
| expect_true(res4, "execute_rollback_plan succeeds for valid inputs"); |
There was a problem hiding this comment.
The test suite doesn't include any test cases for gimbal_phi_rad validation, even though the execute_rollback_plan function validates it (line 32-34 in rollback_execution.hpp). Consider adding a test case to verify that infinite or NaN values for gimbal_phi_rad are properly rejected.
| // 3. Infinite gimbal | |
| plan.thrust_magnitude_kN = 100.0f; | |
| plan.gimbal_theta_rad = std::numeric_limits<float>::infinity(); | |
| bool res3 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res3, "execute_rollback_plan fails for infinite gimbal"); | |
| // 4. Valid plan | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 50.0f; | |
| plan.gimbal_theta_rad = 0.1f; | |
| bool res4 = execute_rollback_plan(plan, tx_id); | |
| expect_true(res4, "execute_rollback_plan succeeds for valid inputs"); | |
| // 3. Infinite gimbal theta | |
| plan.thrust_magnitude_kN = 100.0f; | |
| plan.gimbal_theta_rad = std::numeric_limits<float>::infinity(); | |
| bool res3 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res3, "execute_rollback_plan fails for infinite gimbal theta"); | |
| // 4. Infinite gimbal phi | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 100.0f; | |
| plan.gimbal_theta_rad = 0.0f; | |
| plan.gimbal_phi_rad = std::numeric_limits<float>::infinity(); | |
| bool res4 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res4, "execute_rollback_plan fails for infinite gimbal phi"); | |
| // 5. NaN gimbal phi | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 100.0f; | |
| plan.gimbal_theta_rad = 0.0f; | |
| plan.gimbal_phi_rad = std::numeric_limits<float>::quiet_NaN(); | |
| bool res5 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res5, "execute_rollback_plan fails for NaN gimbal phi"); | |
| // 6. Valid plan | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 50.0f; | |
| plan.gimbal_theta_rad = 0.1f; | |
| plan.gimbal_phi_rad = 0.0f; | |
| bool res6 = execute_rollback_plan(plan, tx_id); | |
| expect_true(res6, "execute_rollback_plan succeeds for valid inputs"); |
| plan.gimbal_theta_rad = 0.1f; | ||
| bool res4 = execute_rollback_plan(plan, tx_id); | ||
| expect_true(res4, "execute_rollback_plan succeeds for valid inputs"); | ||
| expect_true(tx_id.length() > 0, "tx_id is generated"); |
There was a problem hiding this comment.
The assertion checks if tx_id length is greater than 0, but according to the PlatformHAL implementation and test conventions (see tests/sil/test_fault_injection.cpp:63), generate_tx_id() always returns exactly 24 characters. Consider changing this to 'expect_true(tx_id.length() == 24, "tx_id has correct length")' to match the established convention and be more precise.
| expect_true(tx_id.length() > 0, "tx_id is generated"); | |
| expect_true(tx_id.length() == 24, "tx_id has correct length"); |
|
|
||
| #include <string> | ||
| #include <cmath> | ||
| #include <limits> |
There was a problem hiding this comment.
The limits header is included but not used in this file. The std::isfinite function used in the validation logic is provided by cmath, not limits. Consider removing this unused include.
| #include <limits> |
| // Thrust cannot be negative | ||
| if (rollback.thrust_magnitude_kN < 0.0f) { |
There was a problem hiding this comment.
The validation for thrust_magnitude_kN only checks if it's negative, but doesn't verify that it's finite. This means that NaN or infinite values would pass validation and be sent to the actuator. Consider adding a check using std::isfinite for thrust_magnitude_kN, similar to the checks for gimbal angles below.
| // Thrust cannot be negative | |
| if (rollback.thrust_magnitude_kN < 0.0f) { | |
| // Thrust must be finite and cannot be negative | |
| if (!std::isfinite(rollback.thrust_magnitude_kN) || | |
| rollback.thrust_magnitude_kN < 0.0f) { |
| // 4. Valid plan | ||
| plan.valid = true; | ||
| plan.thrust_magnitude_kN = 50.0f; | ||
| plan.gimbal_theta_rad = 0.1f; | ||
| bool res4 = execute_rollback_plan(plan, tx_id); | ||
| expect_true(res4, "execute_rollback_plan succeeds for valid inputs"); |
There was a problem hiding this comment.
The test suite is missing test cases for NaN and infinite thrust values. The validation logic in execute_rollback_plan should reject these values, but there are no tests to verify this behavior. Consider adding test cases similar to the infinite gimbal test (line 64-68) but for thrust_magnitude_kN.
| // 4. Valid plan | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 50.0f; | |
| plan.gimbal_theta_rad = 0.1f; | |
| bool res4 = execute_rollback_plan(plan, tx_id); | |
| expect_true(res4, "execute_rollback_plan succeeds for valid inputs"); | |
| // 4. Infinite thrust | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = std::numeric_limits<float>::infinity(); | |
| plan.gimbal_theta_rad = 0.0f; | |
| bool res4 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res4, "execute_rollback_plan fails for infinite thrust"); | |
| // 5. NaN thrust | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = std::numeric_limits<float>::quiet_NaN(); | |
| plan.gimbal_theta_rad = 0.0f; | |
| bool res5 = execute_rollback_plan(plan, tx_id); | |
| expect_false(res5, "execute_rollback_plan fails for NaN thrust"); | |
| // 6. Valid plan | |
| plan.valid = true; | |
| plan.thrust_magnitude_kN = 50.0f; | |
| plan.gimbal_theta_rad = 0.1f; | |
| bool res6 = execute_rollback_plan(plan, tx_id); | |
| expect_true(res6, "execute_rollback_plan succeeds for valid inputs"); |
| // We expect this to fail (return false) once validation is added. | ||
| // Currently, without validation, it might succeed if PlatformHAL succeeds with 0 values. | ||
| bool res1 = execute_rollback_plan(plan, tx_id); | ||
| // Note: In current implementation, this will likely return TRUE because there is no check. | ||
| // So this expectation will fail until I fix the code. | ||
| // But for TDD, I write the test expecting the CORRECT behavior. |
There was a problem hiding this comment.
This comment suggests the test was written in a TDD style before the implementation was complete, but since the validation logic has now been added to execute_rollback_plan, the comment is outdated and misleading. The test should now pass as expected. Consider removing or updating this comment to reflect the current state.
| // We expect this to fail (return false) once validation is added. | |
| // Currently, without validation, it might succeed if PlatformHAL succeeds with 0 values. | |
| bool res1 = execute_rollback_plan(plan, tx_id); | |
| // Note: In current implementation, this will likely return TRUE because there is no check. | |
| // So this expectation will fail until I fix the code. | |
| // But for TDD, I write the test expecting the CORRECT behavior. | |
| // With an invalid plan (valid == false), execute_rollback_plan is expected to fail validation and return false. | |
| bool res1 = execute_rollback_plan(plan, tx_id); |
| // 1. Invalid plan | ||
| // By default, the struct is zero-initialized, so valid might be false depending on compiler/initialization, | ||
| // but we explicitly set it to false to be sure. |
There was a problem hiding this comment.
This comment is inaccurate. The RollbackPlan struct has its 'valid' field at the end (after the hash field), and in C++, default initialization for a struct doesn't guarantee any particular value for bool fields unless explicitly initialized. The comment suggests uncertainty about initialization behavior, which could be misleading. Consider either removing this comment or clarifying that the explicit 'plan.valid = false' on line 47 is intentional to test the validation logic.
| // 1. Invalid plan | |
| // By default, the struct is zero-initialized, so valid might be false depending on compiler/initialization, | |
| // but we explicitly set it to false to be sure. | |
| // 1. Invalid plan: explicitly mark plan as invalid to exercise validation logic. |
Improved the
execute_rollback_planfunction insrc/raps/rollback_execution.hppby adding strict validation checks for the rollback plan and control inputs. This prevents invalid or unsafe commands (e.g., negative thrust, NaN angles) from being executed. Also added a new test suitetests/sil/test_rollback_execution.cppto verify these improvements.PR created automatically by Jules for task 17323931531489441353 started by @dfeen87