Audit finding
- ID:
AUD-003
- Status: Verified defect
- Severity: Critical
- Confidence: High
- Audited revision:
2f479320d805a1f9f35ebe4afaaeeded48913a94
Problem
The public generalized plant accepts D12, but BuildAugmented() never reads it and hardcodes the control weight to identity. For z = C1 x + D12 u, synthesis requires the D12^T D12 control term and the C1^T D12 cross-term. Changing D12 therefore cannot change the controller, so the implementation solves a different game from the advertised model.
Source:
|
std::size_t DisturbanceSize, |
|
std::size_t ControlSize, |
|
std::size_t ErrorSize> |
|
struct GeneralizedPlant |
|
{ |
|
static_assert(std::is_floating_point_v<T>, "GeneralizedPlant supports floating-point types"); |
|
|
|
using StateMatrix = math::SquareMatrix<T, StateSize>; |
|
using DisturbanceMatrix = math::Matrix<T, StateSize, DisturbanceSize>; |
|
using ControlMatrix = math::Matrix<T, StateSize, ControlSize>; |
|
using ErrorStateMatrix = math::Matrix<T, ErrorSize, StateSize>; |
|
using ErrorControlMatrix = math::Matrix<T, ErrorSize, ControlSize>; |
|
|
|
StateMatrix A{}; |
|
DisturbanceMatrix B1{}; |
|
ControlMatrix B2{}; |
|
ErrorStateMatrix C1{}; |
|
ErrorControlMatrix D12{}; |
|
}; |
and
|
typename HInfinityStateFeedback<T, StateSize, DisturbanceSize, ControlSize, ErrorSize>::Augmented |
|
HInfinityStateFeedback<T, StateSize, DisturbanceSize, ControlSize, ErrorSize>::BuildAugmented(T g) const |
|
{ |
|
Augmented aug{}; |
|
aug.B.SetBlock(plant.B2, 0, 0); |
|
aug.B.SetBlock(plant.B1, 0, ControlSize); |
|
|
|
auto controlWeight = math::SquareMatrix<T, ControlSize>::Identity(); |
|
auto disturbanceWeight = math::SquareMatrix<T, DisturbanceSize>::Identity(); |
|
disturbanceWeight *= -(g * g); |
|
aug.Rtilde.SetBlock(controlWeight, 0, 0); |
|
aug.Rtilde.SetBlock(disturbanceWeight, ControlSize, ControlSize); |
|
|
|
aug.Q = plant.C1.Transpose() * plant.C1; |
|
return aug; |
|
} |
|
|
Feasibility additionally checks only diagonal signs and permits an absolute Riccati residual up to 1.
Acceptance criteria
Audit finding
AUD-0032f479320d805a1f9f35ebe4afaaeeded48913a94Problem
The public generalized plant accepts
D12, butBuildAugmented()never reads it and hardcodes the control weight to identity. Forz = C1 x + D12 u, synthesis requires theD12^T D12control term and theC1^T D12cross-term. ChangingD12therefore cannot change the controller, so the implementation solves a different game from the advertised model.Source:
numerical-toolbox-cpp/numerical/robust_control/HInfinityStateFeedback.hpp
Lines 19 to 37 in 2f47932
numerical-toolbox-cpp/numerical/robust_control/HInfinityStateFeedback.hpp
Lines 96 to 112 in 2f47932
Feasibility additionally checks only diagonal signs and permits an absolute Riccati residual up to
1.Acceptance criteria
D12and cross-term formulation, or narrow the public API to the actually supported normalization.D12changes the synthesized gain and achieved bound.