#include extern const AP_HAL::HAL& hal; void AP_Winch_Servo::init(const AP_WheelEncoder* wheel_encoder) { _wheel_encoder = wheel_encoder; // set servo output range SRV_Channels::set_angle(SRV_Channel::k_winch, 1000); } void AP_Winch_Servo::update() { // return immediately if no servo is assigned to control the winch if (!SRV_Channels::function_assigned(SRV_Channel::k_winch)) { return; } // return immediately if no wheel encoder if (_wheel_encoder == nullptr) { return; } // if not doing any control output trim value if (config.state == AP_Winch::STATE_RELAXED) { SRV_Channels::set_output_limit(SRV_Channel::k_winch, SRV_Channel::SRV_CHANNEL_LIMIT_TRIM); return; } // calculate dt since last iteration uint32_t now = AP_HAL::millis(); float dt = (now - last_update_ms) / 1000.0f; if (dt > 1.0f) { dt = 0.0f; } last_update_ms = now; // calculate latest rate float distance = _wheel_encoder->get_distance(0); float rate = 0.0f; if (is_positive(dt)) { rate = (distance - config.length_curr) / dt; } // update distance from wheel encoder config.length_curr = distance; // if doing position control, calculate position error to desired rate float rate_desired = 0.0f; if (config.state == AP_Winch::STATE_POSITION) { float position_error = config.length_desired - config.length_curr; rate_desired = constrain_float(position_error * config.pos_p, -config.rate_desired, config.rate_desired); } // if doing rate control, set desired rate if (config.state == AP_Winch::STATE_RATE) { rate_desired = config.rate_desired; } // calculate base output float base = 0.0f; if (is_positive(config.rate_max)) { base = rate_desired / config.rate_max; } // constrain and set limit flags float output = base + config.rate_pid.update_all(rate_desired, rate, (limit_low || limit_high)); limit_low = (output <= -1.0f); limit_high = (output >= 1.0f); output = constrain_float(output, -1.0f, 1.0f); // output to servo SRV_Channels::set_output_scaled(SRV_Channel::k_winch, output * 1000); }