From eaab5a5fd0790ae533bc5339d99c858464fe883b Mon Sep 17 00:00:00 2001 From: Bartok9 Date: Mon, 27 Jul 2026 05:21:44 -0400 Subject: [PATCH] fix(simple_flight): protect motor/PID clamps from Windows min/max macros Parenthesize std::min/max in Mixer, VelocityController, and PID helpers. --- .../simple_flight/firmware/Mixer.hpp | 4 +- .../simple_flight/firmware/PidController.hpp | 266 +++++++++--------- .../firmware/RungKuttaPidIntegrator.hpp | 2 +- .../firmware/StdPidIntegrator.hpp | 2 +- .../firmware/VelocityController.hpp | 2 +- 5 files changed, 138 insertions(+), 138 deletions(-) diff --git a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/Mixer.hpp b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/Mixer.hpp index eab9baa832..67a81b6eb1 100644 --- a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/Mixer.hpp +++ b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/Mixer.hpp @@ -43,8 +43,8 @@ class Mixer } for (int motor_index = 0; motor_index < kMotorCount; ++motor_index) - motor_outputs[motor_index] = std::max(params_->motor.min_motor_output, - std::min(motor_outputs[motor_index], params_->motor.max_motor_output)); + motor_outputs[motor_index] = (std::max)(params_->motor.min_motor_output, + (std::min)(motor_outputs[motor_index], params_->motor.max_motor_output)); } private: diff --git a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/PidController.hpp b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/PidController.hpp index 3664aba803..ed794288d6 100644 --- a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/PidController.hpp +++ b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/PidController.hpp @@ -1,133 +1,133 @@ -#pragma once - -#include -#include -#include "interfaces/CommonStructs.hpp" -#include "interfaces/IPidIntegrator.hpp" -#include "StdPidIntegrator.hpp" -#include "RungKuttaPidIntegrator.hpp" - -namespace simple_flight -{ - -template -class PidController : public IUpdatable -{ -public: - PidController(const IBoardClock* clock = nullptr, const PidConfig& config = PidConfig()) - : clock_(clock), config_(config) - { - switch (config.integrator_type) { - case PidConfig::IntegratorType::Standard: - integrator = std::unique_ptr>(new StdPidIntegrator(config_)); - break; - case PidConfig::IntegratorType::RungKutta: - integrator = std::unique_ptr>(new RungKuttaPidIntegrator(config_)); - break; - default: - throw std::invalid_argument("PID integrator type is not recognized"); - } - } - - void setGoal(const T& goal) - { - goal_ = goal; - } - const T& getGoal() const - { - return goal_; - } - - void setMeasured(const T& measured) - { - measured_ = measured; - } - const T& getMeasured() const - { - return measured_; - } - - const PidConfig& getConfig() const - { - return config_; - } - - //allow changing config at runtime - void setConfig(const PidConfig& config) - { - bool renabled = !config_.enabled && config.enabled; - config_ = config; - - if (renabled) { - last_error_ = goal_ - measured_; - integrator->set(output_); - } - } - - T getOutput() - { - return output_; - } - - virtual void reset() override - { - IUpdatable::reset(); - - goal_ = T(); - measured_ = T(); - last_time_ = clock_ == nullptr ? 0 : clock_->millis(); - integrator->reset(); - last_error_ = goal_ - measured_; - min_dt_ = config_.time_scale * config_.time_scale; - } - - virtual void update() override - { - IUpdatable::update(); - - if (!config_.enabled) - return; - - const T error = goal_ - measured_; - - float dt = clock_ == nullptr ? 1 : (clock_->millis() - last_time_) * config_.time_scale; - - float pterm = error * config_.kp; - float dterm = 0; - if (dt > min_dt_) { - integrator->update(dt, error, last_time_); - - float error_der = dt > 0 ? (error - last_error_) / dt : 0; - dterm = error_der * config_.kd; - last_error_ = error; - } - - output_ = config_.output_bias + pterm + integrator->getOutput() + dterm; - - //limit final output - output_ = clip(output_, config_.min_output, config_.max_output); - - last_time_ = clock_->millis(); - } - -private: - //TODO: replace with std::clamp after moving to C++17 - static T clip(T val, T min_value, T max_value) - { - return std::max(min_value, std::min(val, max_value)); - } - -private: - T goal_, measured_; - T output_; - uint64_t last_time_; - const IBoardClock* clock_; - - float last_error_; - float min_dt_; - const PidConfig config_; - - std::unique_ptr> integrator; -}; - -} //namespace +#pragma once + +#include +#include +#include "interfaces/CommonStructs.hpp" +#include "interfaces/IPidIntegrator.hpp" +#include "StdPidIntegrator.hpp" +#include "RungKuttaPidIntegrator.hpp" + +namespace simple_flight +{ + +template +class PidController : public IUpdatable +{ +public: + PidController(const IBoardClock* clock = nullptr, const PidConfig& config = PidConfig()) + : clock_(clock), config_(config) + { + switch (config.integrator_type) { + case PidConfig::IntegratorType::Standard: + integrator = std::unique_ptr>(new StdPidIntegrator(config_)); + break; + case PidConfig::IntegratorType::RungKutta: + integrator = std::unique_ptr>(new RungKuttaPidIntegrator(config_)); + break; + default: + throw std::invalid_argument("PID integrator type is not recognized"); + } + } + + void setGoal(const T& goal) + { + goal_ = goal; + } + const T& getGoal() const + { + return goal_; + } + + void setMeasured(const T& measured) + { + measured_ = measured; + } + const T& getMeasured() const + { + return measured_; + } + + const PidConfig& getConfig() const + { + return config_; + } + + //allow changing config at runtime + void setConfig(const PidConfig& config) + { + bool renabled = !config_.enabled && config.enabled; + config_ = config; + + if (renabled) { + last_error_ = goal_ - measured_; + integrator->set(output_); + } + } + + T getOutput() + { + return output_; + } + + virtual void reset() override + { + IUpdatable::reset(); + + goal_ = T(); + measured_ = T(); + last_time_ = clock_ == nullptr ? 0 : clock_->millis(); + integrator->reset(); + last_error_ = goal_ - measured_; + min_dt_ = config_.time_scale * config_.time_scale; + } + + virtual void update() override + { + IUpdatable::update(); + + if (!config_.enabled) + return; + + const T error = goal_ - measured_; + + float dt = clock_ == nullptr ? 1 : (clock_->millis() - last_time_) * config_.time_scale; + + float pterm = error * config_.kp; + float dterm = 0; + if (dt > min_dt_) { + integrator->update(dt, error, last_time_); + + float error_der = dt > 0 ? (error - last_error_) / dt : 0; + dterm = error_der * config_.kd; + last_error_ = error; + } + + output_ = config_.output_bias + pterm + integrator->getOutput() + dterm; + + //limit final output + output_ = clip(output_, config_.min_output, config_.max_output); + + last_time_ = clock_->millis(); + } + +private: + //TODO: replace with std::clamp after moving to C++17 + static T clip(T val, T min_value, T max_value) + { + return (std::max)(min_value, (std::min)(val, max_value)); + } + +private: + T goal_, measured_; + T output_; + uint64_t last_time_; + const IBoardClock* clock_; + + float last_error_; + float min_dt_; + const PidConfig config_; + + std::unique_ptr> integrator; +}; + +} //namespace diff --git a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/RungKuttaPidIntegrator.hpp b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/RungKuttaPidIntegrator.hpp index 0c80e0f15e..950c4a57ea 100644 --- a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/RungKuttaPidIntegrator.hpp +++ b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/RungKuttaPidIntegrator.hpp @@ -54,7 +54,7 @@ class RungKuttaPidIntegrator : public IPidIntegrator //TODO: replace with std::clamp after moving to C++17 static T clip(T val, T min_value, T max_value) { - return std::max(min_value, std::min(val, max_value)); + return (std::max)(min_value, (std::min)(val, max_value)); } void model(float* y_val, float last_time_, float* y_out) diff --git a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/StdPidIntegrator.hpp b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/StdPidIntegrator.hpp index 0df841390f..ca6d3d66d2 100644 --- a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/StdPidIntegrator.hpp +++ b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/StdPidIntegrator.hpp @@ -53,7 +53,7 @@ class StdPidIntegrator : public IPidIntegrator //TODO: replace with std::clamp after moving to C++17 static T clip(T val, T min_value, T max_value) { - return std::max(min_value, std::min(val, max_value)); + return (std::max)(min_value, (std::min)(val, max_value)); } private: diff --git a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/VelocityController.hpp b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/VelocityController.hpp index fb6a4a460b..25b518e247 100644 --- a/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/VelocityController.hpp +++ b/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/VelocityController.hpp @@ -114,7 +114,7 @@ class VelocityController : public IAxisController break; case 3: //+vz is -ve throttle (NED coordinates) output_ = (-pid_->getOutput() + 1) / 2; //-1 to 1 --> 0 to 1 - output_ = std::max(output_, params_->velocity_pid.min_throttle); + output_ = (std::max)(output_, params_->velocity_pid.min_throttle); break; default: throw std::invalid_argument("axis must be 0, 1 or 3 for VelocityController");