#ifndef __CONTROLLER_HPP #define __CONTROLLER_HPP class Controller : public ODriveIntf::ControllerIntf { public: struct Anticogging_t { uint32_t index = 0; float cogging_map[3600]; bool pre_calibrated = false; bool calib_anticogging = false; float calib_pos_threshold = 1.0f; float calib_vel_threshold = 1.0f; float cogging_ratio = 1.0f; bool anticogging_enabled = true; }; struct Autotuning_t { float frequency = 0.0f; float pos_amplitude = 0.0f; float vel_amplitude = 0.0f; float torque_amplitude = 0.0f; }; struct Config_t { ControlMode control_mode = CONTROL_MODE_POSITION_CONTROL; //see: ControlMode_t InputMode input_mode = INPUT_MODE_PASSTHROUGH; //see: InputMode_t float pos_gain = 20.0f; // [(turn/s) / turn] float vel_gain = 1.0f / 6.0f; // [Nm/(turn/s)] // float vel_gain = 0.2f / 200.0f, // [Nm/(rad/s)] float vel_integrator_gain = 2.0f / 6.0f; // [Nm/(turn/s * s)] float vel_limit = 2.0f; // [turn/s] Infinity to disable. float vel_limit_tolerance = 1.2f; // ratio to vel_lim. Infinity to disable. float vel_integrator_limit = INFINITY; // Vel. integrator clamping value. Infinity to disable. float vel_ramp_rate = 1.0f; // [(turn/s) / s] float torque_ramp_rate = 0.01f; // Nm / sec bool circular_setpoints = false; float circular_setpoint_range = 1.0f; // Circular range when circular_setpoints is true. [turn] uint32_t steps_per_circular_range = 1024; float inertia = 0.0f; // [Nm/(turn/s^2)] float input_filter_bandwidth = 2.0f; // [1/s] float homing_speed = 0.25f; // [turn/s] Anticogging_t anticogging; float gain_scheduling_width = 10.0f; bool enable_gain_scheduling = false; bool enable_vel_limit = true; bool enable_overspeed_error = true; bool enable_torque_mode_vel_limit = true; // enable velocity limit in current control mode (requires a valid velocity estimator) uint8_t axis_to_mirror = -1; float mirror_ratio = 1.0f; float torque_mirror_ratio = 0.0f; uint8_t load_encoder_axis = -1; // default depends on Axis number and is set in load_configuration(). Set to -1 to select sensorless estimator. float mechanical_power_bandwidth = 20.0f; // [rad/s] filter cutoff for mechanical power for spinout detction float electrical_power_bandwidth = 20.0f; // [rad/s] filter cutoff for electrical power for spinout detection float spinout_electrical_power_threshold = 10.0f; // [W] electrical power threshold for spinout detection float spinout_mechanical_power_threshold = -10.0f; // [W] mechanical power threshold for spinout detection // custom setters Controller* parent; void set_input_filter_bandwidth(float value) { input_filter_bandwidth = value; parent->update_filter_gains(); } void set_steps_per_circular_range(uint32_t value) { steps_per_circular_range = value > 0 ? value : steps_per_circular_range; } void set_control_mode(ControlMode value) { control_mode = value; parent->control_mode_updated(); } }; bool apply_config(); void reset(); void set_error(Error error); constexpr void input_pos_updated() { input_pos_updated_ = true; } bool control_mode_updated(); void set_input_pos_and_steps(float pos); bool select_encoder(size_t encoder_num); // Trajectory-Planned control void move_to_pos(float goal_point); void move_incremental(float displacement, bool from_goal_point); // TODO: make this more similar to other calibration loops void start_anticogging_calibration(); float remove_anticogging_bias(); bool anticogging_calibration(float pos_estimate, float vel_estimate); float get_anticogging_value(uint32_t index) { return (index < 3600) ? config_.anticogging.cogging_map[index] : 0.0f; } void update_filter_gains(); bool update(); Config_t config_; Axis* axis_ = nullptr; // set by Axis constructor Error error_ = ERROR_NONE; float last_error_time_ = 0.0f; // Inputs InputPort pos_estimate_linear_src_; InputPort pos_estimate_circular_src_; InputPort vel_estimate_src_; InputPort pos_wrap_src_; float pos_setpoint_ = 0.0f; // [turns] float vel_setpoint_ = 0.0f; // [turn/s] // float vel_setpoint = 800.0f; float vel_integrator_torque_ = 0.0f; // [Nm] float torque_setpoint_ = 0.0f; // [Nm] float input_pos_ = 0.0f; // [turns] float input_vel_ = 0.0f; // [turn/s] float input_torque_ = 0.0f; // [Nm] float input_filter_kp_ = 0.0f; float input_filter_ki_ = 0.0f; Autotuning_t autotuning_; float autotuning_phase_ = 0.0f; bool input_pos_updated_ = false; bool trajectory_done_ = true; bool anticogging_valid_ = false; float mechanical_power_ = 0.0f; // [W] float electrical_power_ = 0.0f; // [W] // Outputs OutputPort torque_output_ = 0.0f; // custom setters void set_input_pos(float value) { set_input_pos_and_steps(value); input_pos_updated(); } }; #endif // __CONTROLLER_HPP