2017-02-10 01:26:12 -04:00
|
|
|
/*
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* AP_MotorsTailsitter.cpp - ArduCopter motors library for tailsitters
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <AP_HAL/AP_HAL.h>
|
|
|
|
#include <AP_Math/AP_Math.h>
|
|
|
|
#include "AP_MotorsTailsitter.h"
|
|
|
|
#include <GCS_MAVLink/GCS.h>
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
|
|
|
#define SERVO_OUTPUT_RANGE 4500
|
|
|
|
#define THROTTLE_RANGE 100
|
|
|
|
|
|
|
|
// init
|
|
|
|
void AP_MotorsTailsitter::init(motor_frame_class frame_class, motor_frame_type frame_type)
|
|
|
|
{
|
|
|
|
// record successful initialisation if what we setup was the desired frame_class
|
|
|
|
_flags.initialised_ok = (frame_class == MOTOR_FRAME_TAILSITTER);
|
|
|
|
}
|
|
|
|
|
2017-04-10 01:51:00 -03:00
|
|
|
|
|
|
|
/// Constructor
|
|
|
|
AP_MotorsTailsitter::AP_MotorsTailsitter(uint16_t loop_rate, uint16_t speed_hz) :
|
|
|
|
AP_MotorsMulticopter(loop_rate, speed_hz)
|
|
|
|
{
|
|
|
|
SRV_Channels::set_rc_frequency(SRV_Channel::k_throttleLeft, speed_hz);
|
|
|
|
SRV_Channels::set_rc_frequency(SRV_Channel::k_throttleRight, speed_hz);
|
|
|
|
}
|
|
|
|
|
2017-02-10 01:26:12 -04:00
|
|
|
void AP_MotorsTailsitter::output_to_motors()
|
|
|
|
{
|
|
|
|
if (!_flags.initialised_ok) {
|
|
|
|
return;
|
|
|
|
}
|
2017-11-03 19:27:54 -03:00
|
|
|
float throttle = _throttle;
|
2017-04-14 00:01:48 -03:00
|
|
|
float throttle_left = 0;
|
|
|
|
float throttle_right = 0;
|
|
|
|
|
2017-02-10 01:26:12 -04:00
|
|
|
switch (_spool_mode) {
|
|
|
|
case SHUT_DOWN:
|
2017-11-03 19:27:54 -03:00
|
|
|
throttle = 0;
|
2017-05-04 18:33:30 -03:00
|
|
|
// set limits flags
|
|
|
|
limit.roll_pitch = true;
|
|
|
|
limit.yaw = true;
|
|
|
|
limit.throttle_lower = true;
|
|
|
|
limit.throttle_upper = true;
|
2017-02-10 01:26:12 -04:00
|
|
|
break;
|
|
|
|
case SPIN_WHEN_ARMED:
|
|
|
|
// sends output to motors when armed but not flying
|
2017-11-03 19:27:54 -03:00
|
|
|
throttle = constrain_float(_spin_up_ratio, 0.0f, 1.0f) * _spin_min;
|
2017-05-04 18:33:30 -03:00
|
|
|
// set limits flags
|
|
|
|
limit.roll_pitch = true;
|
|
|
|
limit.yaw = true;
|
|
|
|
limit.throttle_lower = true;
|
|
|
|
limit.throttle_upper = true;
|
2017-02-10 01:26:12 -04:00
|
|
|
break;
|
|
|
|
case SPOOL_UP:
|
|
|
|
case THROTTLE_UNLIMITED:
|
2017-11-03 19:27:54 -03:00
|
|
|
case SPOOL_DOWN: {
|
|
|
|
throttle = _spin_min + throttle * (1 - _spin_min);
|
2017-11-03 21:41:05 -03:00
|
|
|
throttle_left = constrain_float(throttle + _rudder*0.5, _spin_min, 1);
|
|
|
|
throttle_right = constrain_float(throttle - _rudder*0.5, _spin_min, 1);
|
2017-05-04 18:33:30 -03:00
|
|
|
// initialize limits flags
|
|
|
|
limit.roll_pitch = false;
|
|
|
|
limit.yaw = false;
|
|
|
|
limit.throttle_lower = false;
|
|
|
|
limit.throttle_upper = false;
|
2017-02-10 01:26:12 -04:00
|
|
|
break;
|
2017-11-03 19:27:54 -03:00
|
|
|
}
|
2017-02-10 01:26:12 -04:00
|
|
|
}
|
|
|
|
// outputs are setup here, and written to the HAL by the plane servos loop
|
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_aileron, _aileron*SERVO_OUTPUT_RANGE);
|
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_elevator, _elevator*SERVO_OUTPUT_RANGE);
|
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_rudder, _rudder*SERVO_OUTPUT_RANGE);
|
2017-11-03 19:27:54 -03:00
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_throttle, throttle*THROTTLE_RANGE);
|
2017-02-12 21:26:59 -04:00
|
|
|
|
|
|
|
// also support differential roll with twin motors
|
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_throttleLeft, throttle_left*THROTTLE_RANGE);
|
|
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_throttleRight, throttle_right*THROTTLE_RANGE);
|
|
|
|
|
2017-02-11 07:27:50 -04:00
|
|
|
#if APM_BUILD_TYPE(APM_BUILD_ArduCopter)
|
|
|
|
SRV_Channels::calc_pwm();
|
|
|
|
SRV_Channels::output_ch_all();
|
|
|
|
#endif
|
2017-02-10 01:26:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// calculate outputs to the motors
|
|
|
|
void AP_MotorsTailsitter::output_armed_stabilizing()
|
|
|
|
{
|
|
|
|
_aileron = -_yaw_in;
|
|
|
|
_elevator = _pitch_in;
|
|
|
|
_rudder = _roll_in;
|
|
|
|
_throttle = get_throttle();
|
|
|
|
|
|
|
|
// sanity check throttle is above zero and below current limited throttle
|
|
|
|
if (_throttle <= 0.0f) {
|
|
|
|
_throttle = 0.0f;
|
|
|
|
limit.throttle_lower = true;
|
|
|
|
}
|
|
|
|
if (_throttle >= _throttle_thrust_max) {
|
|
|
|
_throttle = _throttle_thrust_max;
|
|
|
|
limit.throttle_upper = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_throttle = constrain_float(_throttle, 0.1, 1);
|
|
|
|
}
|
|
|
|
|