mirror of https://github.com/ArduPilot/ardupilot
106 lines
3.3 KiB
C++
106 lines
3.3 KiB
C++
#include "AP_Winch_PWM.h"
|
|
#include <GCS_MAVLink/GCS.h>
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
// true if winch is healthy
|
|
bool AP_Winch_PWM::healthy() const
|
|
{
|
|
// return immediately if no servo is assigned to control the winch
|
|
if (!SRV_Channels::function_assigned(SRV_Channel::k_winch)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AP_Winch_PWM::update()
|
|
{
|
|
// return immediately if no servo is assigned to control the winch
|
|
if (!SRV_Channels::function_assigned(SRV_Channel::k_winch)) {
|
|
return;
|
|
}
|
|
|
|
// read pilot input
|
|
read_pilot_desired_rate();
|
|
|
|
// send outputs to winch
|
|
control_winch();
|
|
}
|
|
|
|
// update pwm outputs to control winch
|
|
void AP_Winch_PWM::control_winch()
|
|
{
|
|
const uint32_t now_ms = AP_HAL::millis();
|
|
float dt = (now_ms - control_update_ms) / 1000.0f;
|
|
if (dt > 1.0f) {
|
|
dt = 0.0f;
|
|
}
|
|
control_update_ms = now_ms;
|
|
|
|
// if relaxed stop outputting pwm signals
|
|
if (config.control_mode == AP_Winch::ControlMode::RELAXED) {
|
|
// if not doing any control stop sending pwm to winch
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_winch, 0);
|
|
|
|
// rate used for acceleration limiting reset to zero
|
|
set_previous_rate(0.0f);
|
|
return;
|
|
}
|
|
|
|
// if doing position control, calculate position error to desired rate
|
|
if ((config.control_mode == AP_Winch::ControlMode::POSITION) && healthy()) {
|
|
float position_error = config.length_desired - line_length;
|
|
config.rate_desired = constrain_float(position_error * config.pos_p, -config.rate_max, config.rate_max);
|
|
}
|
|
|
|
// apply acceleration limited to rate
|
|
const float rate_limited = get_rate_limited_by_accel(config.rate_desired, dt);
|
|
|
|
// use linear interpolation to calculate output to move winch at desired rate
|
|
const int16_t scaled_output = linear_interpolate(-1000, 1000, rate_limited, -config.rate_max, config.rate_max);
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_winch, scaled_output);
|
|
|
|
// update distance estimate assuming winch will move exactly as requested
|
|
line_length += config.rate_desired * dt;
|
|
}
|
|
|
|
//send generator status
|
|
void AP_Winch_PWM::send_status(const GCS_MAVLINK &channel)
|
|
{
|
|
// prepare status bitmask
|
|
uint32_t status_bitmask = 0;
|
|
if (healthy()) {
|
|
status_bitmask |= MAV_WINCH_STATUS_HEALTHY;
|
|
}
|
|
|
|
// send status
|
|
mavlink_msg_winch_status_send(
|
|
channel.get_chan(),
|
|
AP_HAL::micros64(), // time_usec
|
|
line_length, // line_length
|
|
config.rate_desired, // speed
|
|
std::numeric_limits<double>::quiet_NaN(), // tension
|
|
std::numeric_limits<double>::quiet_NaN(), // voltage
|
|
std::numeric_limits<double>::quiet_NaN(), // current
|
|
INT16_MAX, // temperature
|
|
status_bitmask); // status flags
|
|
}
|
|
|
|
// write log
|
|
void AP_Winch_PWM::write_log()
|
|
{
|
|
AP::logger().Write_Winch(
|
|
healthy(),
|
|
0, // thread end (unsupported)
|
|
0, // moving (unsupported)
|
|
0, // clutch (unsupported)
|
|
(uint8_t)config.control_mode,
|
|
config.length_desired,
|
|
get_current_length(),
|
|
config.rate_desired,
|
|
0, // tension (unsupported)
|
|
0, // voltage (unsupported)
|
|
0); // temp (unsupported)
|
|
}
|