2013-05-29 20:51:24 -03:00
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
2012-06-13 15:55:19 -03:00
2012-07-02 21:21:01 -03:00
# include <AP_Common.h>
2012-11-12 17:42:33 -04:00
# include <AP_Progmem.h>
2012-07-02 21:21:01 -03:00
# include <AP_Param.h>
2012-06-13 15:55:19 -03:00
# include <AP_Mount.h>
2012-08-26 20:33:45 -03:00
// Just so that it's completely clear...
# define ENABLED 1
# define DISABLED 0
# if defined( __AVR_ATmega1280__ )
# define MNT_JSTICK_SPD_OPTION DISABLED // Allow RC joystick to control the speed of the mount movements instead of the position of the mount
# define MNT_RETRACT_OPTION DISABLED // Use a servo to retract the mount inside the fuselage (i.e. for landings)
# define MNT_GPSPOINT_OPTION ENABLED // Point the mount to a GPS point defined via a mouse click in the Mission Planner GUI
# define MNT_STABILIZE_OPTION DISABLED // stabilize camera using frame attitude information
# define MNT_MOUNT2_OPTION DISABLED // second mount, can for example be used to keep an antenna pointed at the home position
# else
# define MNT_JSTICK_SPD_OPTION ENABLED // uses 844 bytes of memory
# define MNT_RETRACT_OPTION ENABLED // uses 244 bytes of memory
# define MNT_GPSPOINT_OPTION ENABLED // uses 580 bytes of memory
# define MNT_STABILIZE_OPTION ENABLED // uses 2424 bytes of memory
# define MNT_MOUNT2_OPTION ENABLED // uses 58 bytes of memory (must also be enabled in APM_Config.h)
# endif
2012-07-02 21:21:01 -03:00
const AP_Param : : GroupInfo AP_Mount : : var_info [ ] PROGMEM = {
2012-08-17 03:20:30 -03:00
// @Param: MODE
// @DisplayName: Mount operation mode
// @Description: Camera or antenna mount operation mode
// @Values: 0:retract,1:neutral,2:MavLink_targeting,3:RC_targeting,4:GPS_point
// @User: Standard
2012-08-08 00:04:49 -03:00
AP_GROUPINFO ( " MODE " , 0 , AP_Mount , _mount_mode , MAV_MOUNT_MODE_RETRACT ) , // see MAV_MOUNT_MODE at ardupilotmega.h
2012-07-03 18:36:34 -03:00
2012-08-26 20:33:45 -03:00
# if MNT_RETRACT_OPTION == ENABLED
2013-01-02 03:47:39 -04:00
// @Param: RETRACT_X
// @DisplayName: Mount roll angle when in retracted position
// @Description: Mount roll angle when in retracted position
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
// @Param: RETRACT_Y
// @DisplayName: Mount tilt/pitch angle when in retracted position
// @Description: Mount tilt/pitch angle when in retracted position
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
// @Param: RETRACT_Z
// @DisplayName: Mount yaw/pan angle when in retracted position
// @Description: Mount yaw/pan angle when in retracted position
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " RETRACT " , 1 , AP_Mount , _retract_angles , 0 ) ,
2012-08-26 20:33:45 -03:00
# endif
2012-07-03 18:36:34 -03:00
2013-01-02 03:47:39 -04:00
// @Param: NEUTRAL_X
// @DisplayName: Mount roll angle when in neutral position
// @Description: Mount roll angle when in neutral position
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
2012-07-03 18:36:34 -03:00
2013-01-02 03:47:39 -04:00
// @Param: NEUTRAL_Y
// @DisplayName: Mount tilt/pitch angle when in neutral position
// @Description: Mount tilt/pitch angle when in neutral position
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
2013-01-02 03:47:39 -04:00
// @Param: NEUTRAL_Z
// @DisplayName: Mount pan/yaw angle when in neutral position
// @Description: Mount pan/yaw angle when in neutral position
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " NEUTRAL " , 2 , AP_Mount , _neutral_angles , 0 ) ,
// @Param: CONTROL_X
// @DisplayName: Mount roll angle command from groundstation
// @Description: Mount roll angle when in MavLink or RC control operation mode
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
// @Param: CONTROL_Y
// @DisplayName: Mount tilt/pitch angle command from groundstation
// @Description: Mount tilt/pitch angle when in MavLink or RC control operation mode
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
// @Param: CONTROL_Z
// @DisplayName: Mount pan/yaw angle command from groundstation
// @Description: Mount pan/yaw angle when in MavLink or RC control operation mode
// @Units: Centi-Degrees
// @Range: -18000 17999
// @Increment: 1
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " CONTROL " , 3 , AP_Mount , _control_angles , 0 ) ,
2012-07-03 18:36:34 -03:00
2012-08-26 20:33:45 -03:00
# if MNT_STABILIZE_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// @Param: STAB_ROLL
2013-01-02 03:47:39 -04:00
// @DisplayName: Stabilize mount's roll angle
2012-08-17 03:20:30 -03:00
// @Description:enable roll stabilisation relative to Earth
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " STAB_ROLL " , 4 , AP_Mount , _stab_roll , 0 ) ,
2012-07-03 18:36:34 -03:00
2012-08-17 03:20:30 -03:00
// @Param: STAB_TILT
2013-01-02 03:47:39 -04:00
// @DisplayName: Stabilize mount's pitch/tilt angle
// @Description: enable tilt/pitch stabilisation relative to Earth
2012-08-17 03:20:30 -03:00
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " STAB_TILT " , 5 , AP_Mount , _stab_tilt , 0 ) ,
2012-07-03 18:36:34 -03:00
2012-08-17 03:20:30 -03:00
// @Param: STAB_PAN
2013-01-02 03:47:39 -04:00
// @DisplayName: Stabilize mount pan/yaw angle
// @Description: enable pan/yaw stabilisation relative to Earth
2012-08-17 03:20:30 -03:00
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " STAB_PAN " , 6 , AP_Mount , _stab_pan , 0 ) ,
2012-08-26 20:33:45 -03:00
# endif
2012-08-05 18:48:57 -03:00
2012-08-17 03:20:30 -03:00
// @Param: RC_IN_ROLL
// @DisplayName: roll RC input channel
// @Description: 0 for none, any other for the RC channel to be used to control roll movements
// @Values: 0:Disabled,5:RC5,6:RC6,7:RC7,8:RC8
// @User: Standard
AP_GROUPINFO ( " RC_IN_ROLL " , 7 , AP_Mount , _roll_rc_in , 0 ) ,
// @Param: ANGMIN_ROL
// @DisplayName: Minimum roll angle
// @Description: Minimum physical roll angular position of mount.
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMIN_ROL " , 8 , AP_Mount , _roll_angle_min , - 4500 ) ,
// @Param: ANGMAX_ROL
// @DisplayName: Maximum roll angle
// @Description: Maximum physical roll angular position of the mount
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMAX_ROL " , 9 , AP_Mount , _roll_angle_max , 4500 ) ,
// @Param: RC_IN_TILT
// @DisplayName: tilt (pitch) RC input channel
// @Description: 0 for none, any other for the RC channel to be used to control tilt (pitch) movements
// @Values: 0:Disabled,5:RC5,6:RC6,7:RC7,8:RC8
// @User: Standard
AP_GROUPINFO ( " RC_IN_TILT " , 10 , AP_Mount , _tilt_rc_in , 0 ) ,
// @Param: ANGMIN_TIL
// @DisplayName: Minimum tilt angle
// @Description: Minimum physical tilt (pitch) angular position of mount.
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMIN_TIL " , 11 , AP_Mount , _tilt_angle_min , - 4500 ) ,
// @Param: ANGMAX_TIL
// @DisplayName: Maximum tilt angle
// @Description: Maximum physical tilt (pitch) angular position of the mount
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMAX_TIL " , 12 , AP_Mount , _tilt_angle_max , 4500 ) ,
// @Param: RC_IN_PAN
// @DisplayName: pan (yaw) RC input channel
// @Description: 0 for none, any other for the RC channel to be used to control pan (yaw) movements
// @Values: 0:Disabled,5:RC5,6:RC6,7:RC7,8:RC8
// @User: Standard
AP_GROUPINFO ( " RC_IN_PAN " , 13 , AP_Mount , _pan_rc_in , 0 ) ,
// @Param: ANGMIN_PAN
// @DisplayName: Minimum pan angle
// @Description: Minimum physical pan (yaw) angular position of mount.
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMIN_PAN " , 14 , AP_Mount , _pan_angle_min , - 4500 ) ,
// @Param: ANGMAX_PAN
// @DisplayName: Maximum pan angle
// @Description: Maximum physical pan (yaw) angular position of the mount
2013-01-02 03:47:39 -04:00
// @Units: Centi-Degrees
2012-08-17 03:20:30 -03:00
// @Range: -18000 17999
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " ANGMAX_PAN " , 15 , AP_Mount , _pan_angle_max , 4500 ) ,
2012-08-26 20:33:45 -03:00
# if MNT_JSTICK_SPD_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// @Param: JSTICK_SPD
// @DisplayName: mount joystick speed
2013-03-07 23:39:32 -04:00
// @Description: 0 for position control, small for low speeds, 100 for max speed. A good general value is 10 which gives a movement speed of 3 degrees per second.
// @Range: 0 100
2012-08-17 03:20:30 -03:00
// @Increment: 1
// @User: Standard
AP_GROUPINFO ( " JSTICK_SPD " , 16 , AP_Mount , _joystick_speed , 0 ) ,
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
AP_GROUPEND
2012-07-02 21:21:01 -03:00
} ;
2012-08-17 03:20:30 -03:00
AP_Mount : : AP_Mount ( const struct Location * current_loc , GPS * & gps , AP_AHRS * ahrs , uint8_t id ) :
_gps ( gps )
2012-06-13 15:55:19 -03:00
{
2012-12-12 17:52:04 -04:00
AP_Param : : setup_object_defaults ( this , var_info ) ;
2012-08-17 03:20:30 -03:00
_ahrs = ahrs ;
_current_loc = current_loc ;
// default to zero angles
_retract_angles = Vector3f ( 0 , 0 , 0 ) ;
_neutral_angles = Vector3f ( 0 , 0 , 0 ) ;
_control_angles = Vector3f ( 0 , 0 , 0 ) ;
// default unknown mount type
_mount_type = k_unknown ;
2012-08-26 20:33:45 -03:00
# if MNT_MOUNT2_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
if ( id = = 0 ) {
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
_roll_idx = RC_Channel_aux : : k_mount_roll ;
_tilt_idx = RC_Channel_aux : : k_mount_tilt ;
_pan_idx = RC_Channel_aux : : k_mount_pan ;
_open_idx = RC_Channel_aux : : k_mount_open ;
2012-08-26 20:33:45 -03:00
# if MNT_MOUNT2_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
} else {
_roll_idx = RC_Channel_aux : : k_mount2_roll ;
_tilt_idx = RC_Channel_aux : : k_mount2_tilt ;
_pan_idx = RC_Channel_aux : : k_mount2_pan ;
_open_idx = RC_Channel_aux : : k_mount2_open ;
}
2012-08-26 20:33:45 -03:00
# endif
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// Auto-detect the mount gimbal type depending on the functions assigned to the servos
void
AP_Mount : : update_mount_type ( )
2012-07-24 23:00:38 -03:00
{
2012-09-08 02:12:52 -03:00
bool have_roll , have_tilt , have_pan ;
have_roll = RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount_roll ) | |
RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount2_roll ) ;
have_tilt = RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount_tilt ) | |
RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount2_tilt ) ;
have_pan = RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount_pan ) | |
RC_Channel_aux : : function_assigned ( RC_Channel_aux : : k_mount2_pan ) ;
if ( have_pan & & have_tilt & & ! have_roll ) {
2012-08-17 03:20:30 -03:00
_mount_type = k_pan_tilt ;
}
2012-09-08 02:12:52 -03:00
if ( ! have_pan & & have_tilt & & have_roll ) {
2012-08-17 03:20:30 -03:00
_mount_type = k_tilt_roll ;
}
2012-09-08 02:12:52 -03:00
if ( have_pan & & have_tilt & & have_roll ) {
2012-08-17 03:20:30 -03:00
_mount_type = k_pan_tilt_roll ;
}
2012-07-24 23:00:38 -03:00
}
2012-08-05 18:48:57 -03:00
/// sets the servo angles for retraction, note angles are in degrees
void AP_Mount : : set_retract_angles ( float roll , float tilt , float pan )
2012-06-13 15:55:19 -03:00
{
2012-08-17 03:20:30 -03:00
_retract_angles = Vector3f ( roll , tilt , pan ) ;
2012-06-13 15:55:19 -03:00
}
2012-07-02 21:21:01 -03:00
//sets the servo angles for neutral, note angles are in degrees
2012-08-05 18:48:57 -03:00
void AP_Mount : : set_neutral_angles ( float roll , float tilt , float pan )
2012-06-13 15:55:19 -03:00
{
2012-08-17 03:20:30 -03:00
_neutral_angles = Vector3f ( roll , tilt , pan ) ;
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// sets the servo angles for MAVLink, note angles are in degrees
void AP_Mount : : set_control_angles ( float roll , float tilt , float pan )
2012-06-13 15:55:19 -03:00
{
2012-08-17 03:20:30 -03:00
_control_angles = Vector3f ( roll , tilt , pan ) ;
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// used to tell the mount to track GPS location
2012-06-13 15:55:19 -03:00
void AP_Mount : : set_GPS_target_location ( Location targetGPSLocation )
{
2012-08-17 03:20:30 -03:00
_target_GPS_location = targetGPSLocation ;
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// This one should be called periodically
2012-06-13 15:55:19 -03:00
void AP_Mount : : update_mount_position ( )
{
2012-11-07 10:29:25 -04:00
# if MNT_RETRACT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
static bool mount_open = 0 ; // 0 is closed
2012-11-07 10:29:25 -04:00
# endif
2012-08-17 03:20:30 -03:00
switch ( ( enum MAV_MOUNT_MODE ) _mount_mode . get ( ) )
{
2012-08-26 20:33:45 -03:00
# if MNT_RETRACT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// move mount to a "retracted position" or to a position where a fourth servo can retract the entire mount into the fuselage
case MAV_MOUNT_MODE_RETRACT :
{
Vector3f vec = _retract_angles . get ( ) ;
_roll_angle = vec . x ;
_tilt_angle = vec . y ;
_pan_angle = vec . z ;
break ;
}
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
// move mount to a neutral position, typically pointing forward
case MAV_MOUNT_MODE_NEUTRAL :
{
Vector3f vec = _neutral_angles . get ( ) ;
_roll_angle = vec . x ;
_tilt_angle = vec . y ;
_pan_angle = vec . z ;
break ;
}
// point to the angles given by a mavlink message
case MAV_MOUNT_MODE_MAVLINK_TARGETING :
{
Vector3f vec = _control_angles . get ( ) ;
_roll_control_angle = radians ( vec . x ) ;
_tilt_control_angle = radians ( vec . y ) ;
_pan_control_angle = radians ( vec . z ) ;
stabilize ( ) ;
break ;
}
// RC radio manual angle control, but with stabilization from the AHRS
case MAV_MOUNT_MODE_RC_TARGETING :
{
2013-06-03 03:10:33 -03:00
# define rc_ch(i) RC_Channel::rc_channel(i-1)
2012-08-26 20:33:45 -03:00
# if MNT_JSTICK_SPD_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
if ( _joystick_speed ) { // for spring loaded joysticks
// allow pilot speed position input to come directly from an RC_Channel
2013-06-03 03:10:33 -03:00
if ( _roll_rc_in & & rc_ch ( _roll_rc_in ) ) {
_roll_control_angle + = rc_ch ( _roll_rc_in ) - > norm_input ( ) * 0.0001f * _joystick_speed ;
2013-01-10 14:42:24 -04:00
if ( _roll_control_angle < radians ( _roll_angle_min * 0.01f ) ) _roll_control_angle = radians ( _roll_angle_min * 0.01f ) ;
if ( _roll_control_angle > radians ( _roll_angle_max * 0.01f ) ) _roll_control_angle = radians ( _roll_angle_max * 0.01f ) ;
2012-08-17 03:20:30 -03:00
}
2013-06-03 03:10:33 -03:00
if ( _tilt_rc_in & & ( rc_ch ( _tilt_rc_in ) ) ) {
_tilt_control_angle + = rc_ch ( _tilt_rc_in ) - > norm_input ( ) * 0.0001f * _joystick_speed ;
2013-01-10 14:42:24 -04:00
if ( _tilt_control_angle < radians ( _tilt_angle_min * 0.01f ) ) _tilt_control_angle = radians ( _tilt_angle_min * 0.01f ) ;
if ( _tilt_control_angle > radians ( _tilt_angle_max * 0.01f ) ) _tilt_control_angle = radians ( _tilt_angle_max * 0.01f ) ;
2012-08-17 03:20:30 -03:00
}
2013-06-03 03:10:33 -03:00
if ( _pan_rc_in & & ( rc_ch ( _pan_rc_in ) ) ) {
_pan_control_angle + = rc_ch ( _pan_rc_in ) - > norm_input ( ) * 0.0001f * _joystick_speed ;
2013-01-10 14:42:24 -04:00
if ( _pan_control_angle < radians ( _pan_angle_min * 0.01f ) ) _pan_control_angle = radians ( _pan_angle_min * 0.01f ) ;
if ( _pan_control_angle > radians ( _pan_angle_max * 0.01f ) ) _pan_control_angle = radians ( _pan_angle_max * 0.01f ) ;
2012-08-17 03:20:30 -03:00
}
} else {
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
// allow pilot position input to come directly from an RC_Channel
2013-06-03 03:10:33 -03:00
if ( _roll_rc_in & & ( rc_ch ( _roll_rc_in ) ) ) {
_roll_control_angle = angle_input_rad ( rc_ch ( _roll_rc_in ) , _roll_angle_min , _roll_angle_max ) ;
2012-08-17 03:20:30 -03:00
}
2013-06-03 03:10:33 -03:00
if ( _tilt_rc_in & & ( rc_ch ( _tilt_rc_in ) ) ) {
_tilt_control_angle = angle_input_rad ( rc_ch ( _tilt_rc_in ) , _tilt_angle_min , _tilt_angle_max ) ;
2012-08-17 03:20:30 -03:00
}
2013-06-03 03:10:33 -03:00
if ( _pan_rc_in & & ( rc_ch ( _pan_rc_in ) ) ) {
_pan_control_angle = angle_input_rad ( rc_ch ( _pan_rc_in ) , _pan_angle_min , _pan_angle_max ) ;
2012-08-17 03:20:30 -03:00
}
2012-08-26 20:33:45 -03:00
# if MNT_JSTICK_SPD_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
}
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
stabilize ( ) ;
break ;
}
2012-08-26 20:33:45 -03:00
# if MNT_GPSPOINT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// point mount to a GPS point given by the mission planner
case MAV_MOUNT_MODE_GPS_POINT :
{
if ( _gps - > fix ) {
calc_GPS_target_angle ( & _target_GPS_location ) ;
stabilize ( ) ;
}
break ;
}
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
default :
//do nothing
break ;
}
2012-08-26 20:33:45 -03:00
# if MNT_RETRACT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// move mount to a "retracted position" into the fuselage with a fourth servo
2012-09-08 02:12:52 -03:00
bool mount_open_new = ( enum MAV_MOUNT_MODE ) _mount_mode . get ( ) = = MAV_MOUNT_MODE_RETRACT ? 0 : 1 ;
if ( mount_open ! = mount_open_new ) {
mount_open = mount_open_new ;
move_servo ( _open_idx , mount_open_new , 0 , 1 ) ;
2012-08-17 03:20:30 -03:00
}
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
// write the results to the servos
2013-01-10 14:42:24 -04:00
move_servo ( _roll_idx , _roll_angle * 10 , _roll_angle_min * 0.1f , _roll_angle_max * 0.1f ) ;
move_servo ( _tilt_idx , _tilt_angle * 10 , _tilt_angle_min * 0.1f , _tilt_angle_max * 0.1f ) ;
move_servo ( _pan_idx , _pan_angle * 10 , _pan_angle_min * 0.1f , _pan_angle_max * 0.1f ) ;
2012-06-13 15:55:19 -03:00
}
void AP_Mount : : set_mode ( enum MAV_MOUNT_MODE mode )
{
2012-08-17 03:20:30 -03:00
_mount_mode = ( int8_t ) mode ;
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// Change the configuration of the mount
/// triggered by a MavLink packet.
2012-06-13 15:55:19 -03:00
void AP_Mount : : configure_msg ( mavlink_message_t * msg )
{
2012-08-17 03:20:30 -03:00
__mavlink_mount_configure_t packet ;
mavlink_msg_mount_configure_decode ( msg , & packet ) ;
if ( mavlink_check_target ( packet . target_system , packet . target_component ) ) {
// not for us
return ;
}
set_mode ( ( enum MAV_MOUNT_MODE ) packet . mount_mode ) ;
_stab_roll = packet . stab_roll ;
_stab_tilt = packet . stab_pitch ;
_stab_pan = packet . stab_yaw ;
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// Control the mount (depends on the previously set mount configuration)
/// triggered by a MavLink packet.
2011-10-31 18:55:58 -03:00
void AP_Mount : : control_msg ( mavlink_message_t * msg )
{
2012-08-17 03:20:30 -03:00
__mavlink_mount_control_t packet ;
mavlink_msg_mount_control_decode ( msg , & packet ) ;
if ( mavlink_check_target ( packet . target_system , packet . target_component ) ) {
// not for us
return ;
}
switch ( ( enum MAV_MOUNT_MODE ) _mount_mode . get ( ) )
{
2012-08-26 20:33:45 -03:00
# if MNT_RETRACT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_RETRACT : // Load and keep safe position (Roll,Pitch,Yaw) from EEPROM and stop stabilization
2013-01-10 14:42:24 -04:00
set_retract_angles ( packet . input_b * 0.01f , packet . input_a * 0.01f , packet . input_c * 0.01f ) ;
2012-08-17 03:20:30 -03:00
if ( packet . save_position )
{
_retract_angles . save ( ) ;
}
break ;
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_NEUTRAL : // Load and keep neutral position (Roll,Pitch,Yaw) from EEPROM
2013-01-10 14:42:24 -04:00
set_neutral_angles ( packet . input_b * 0.01f , packet . input_a * 0.01f , packet . input_c * 0.01f ) ;
2012-08-17 03:20:30 -03:00
if ( packet . save_position )
{
_neutral_angles . save ( ) ;
}
break ;
case MAV_MOUNT_MODE_MAVLINK_TARGETING : // Load neutral position and start MAVLink Roll,Pitch,Yaw control with stabilization
2013-01-10 14:42:24 -04:00
set_control_angles ( packet . input_b * 0.01f , packet . input_a * 0.01f , packet . input_c * 0.01f ) ;
2012-08-17 03:20:30 -03:00
break ;
case MAV_MOUNT_MODE_RC_TARGETING : // Load neutral position and start RC Roll,Pitch,Yaw control with stabilization
{
Vector3f vec = _neutral_angles . get ( ) ;
_roll_angle = vec . x ;
_tilt_angle = vec . y ;
_pan_angle = vec . z ;
}
break ;
2012-08-26 20:33:45 -03:00
# if MNT_GPSPOINT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_GPS_POINT : // Load neutral position and start to point to Lat,Lon,Alt
Location targetGPSLocation ;
targetGPSLocation . lat = packet . input_a ;
targetGPSLocation . lng = packet . input_b ;
targetGPSLocation . alt = packet . input_c ;
set_GPS_target_location ( targetGPSLocation ) ;
break ;
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_ENUM_END :
break ;
default :
// do nothing
break ;
}
2011-10-31 18:55:58 -03:00
}
2012-08-05 18:48:57 -03:00
/// Return mount status information (depends on the previously set mount configuration)
/// triggered by a MavLink packet.
2011-10-31 18:55:58 -03:00
void AP_Mount : : status_msg ( mavlink_message_t * msg )
{
2012-08-17 03:20:30 -03:00
__mavlink_mount_status_t packet ;
mavlink_msg_mount_status_decode ( msg , & packet ) ;
if ( mavlink_check_target ( packet . target_system , packet . target_component ) ) {
// not for us
return ;
}
switch ( ( enum MAV_MOUNT_MODE ) _mount_mode . get ( ) )
{
case MAV_MOUNT_MODE_RETRACT : // safe position (Roll,Pitch,Yaw) from EEPROM and stop stabilization
case MAV_MOUNT_MODE_NEUTRAL : // neutral position (Roll,Pitch,Yaw) from EEPROM
case MAV_MOUNT_MODE_MAVLINK_TARGETING : // neutral position and start MAVLink Roll,Pitch,Yaw control with stabilization
case MAV_MOUNT_MODE_RC_TARGETING : // neutral position and start RC Roll,Pitch,Yaw control with stabilization
2012-08-26 20:32:27 -03:00
packet . pointing_b = _roll_angle * 100 ; // degrees*100
packet . pointing_a = _tilt_angle * 100 ; // degrees*100
packet . pointing_c = _pan_angle * 100 ; // degrees*100
2012-08-17 03:20:30 -03:00
break ;
2012-08-26 20:33:45 -03:00
# if MNT_GPSPOINT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_GPS_POINT : // neutral position and start to point to Lat,Lon,Alt
2012-08-26 20:32:27 -03:00
packet . pointing_a = _target_GPS_location . lat ; // latitude
packet . pointing_b = _target_GPS_location . lng ; // longitude
packet . pointing_c = _target_GPS_location . alt ; // altitude
2012-08-17 03:20:30 -03:00
break ;
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
case MAV_MOUNT_MODE_ENUM_END :
break ;
}
// status reply
// TODO: is COMM_3 correct ?
mavlink_msg_mount_status_send ( MAVLINK_COMM_3 , packet . target_system , packet . target_component ,
packet . pointing_a , packet . pointing_b , packet . pointing_c ) ;
2011-10-31 18:55:58 -03:00
}
2012-08-05 18:48:57 -03:00
/// Set mount point/region of interest, triggered by mission script commands
2013-03-26 08:58:54 -03:00
void AP_Mount : : set_roi_cmd ( const struct Location * target_loc )
2012-06-13 15:55:19 -03:00
{
2012-08-26 20:33:45 -03:00
# if MNT_GPSPOINT_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
// set the target gps location
_target_GPS_location = * target_loc ;
2012-07-24 23:00:38 -03:00
2012-08-17 03:20:30 -03:00
// set the mode to GPS tracking mode
set_mode ( MAV_MOUNT_MODE_GPS_POINT ) ;
2012-08-26 20:33:45 -03:00
# endif
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// Set mount configuration, triggered by mission script commands
2012-06-13 15:55:19 -03:00
void AP_Mount : : configure_cmd ( )
{
2012-08-17 03:20:30 -03:00
// TODO get the information out of the mission command and use it
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// Control the mount (depends on the previously set mount configuration), triggered by mission script commands
2012-06-13 15:55:19 -03:00
void AP_Mount : : control_cmd ( )
{
2012-08-17 03:20:30 -03:00
// TODO get the information out of the mission command and use it
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/// returns the angle (degrees*100) that the RC_Channel input is receiving
int32_t
AP_Mount : : angle_input ( RC_Channel * rc , int16_t angle_min , int16_t angle_max )
{
2012-08-17 03:20:30 -03:00
return ( rc - > get_reverse ( ) ? - 1 : 1 ) * ( rc - > radio_in - rc - > radio_min ) * ( int32_t ) ( angle_max - angle_min ) / ( rc - > radio_max - rc - > radio_min ) + ( rc - > get_reverse ( ) ? angle_max : angle_min ) ;
2012-08-05 18:48:57 -03:00
}
/// returns the angle (radians) that the RC_Channel input is receiving
float
AP_Mount : : angle_input_rad ( RC_Channel * rc , int16_t angle_min , int16_t angle_max )
{
2013-01-10 14:42:24 -04:00
return radians ( angle_input ( rc , angle_min , angle_max ) * 0.01f ) ;
2012-08-05 18:48:57 -03:00
}
2012-06-13 15:55:19 -03:00
void
2013-03-26 08:58:54 -03:00
AP_Mount : : calc_GPS_target_angle ( const struct Location * target )
2012-06-13 15:55:19 -03:00
{
2013-01-10 14:42:24 -04:00
float GPS_vector_x = ( target - > lng - _current_loc - > lng ) * cosf ( ToRad ( ( _current_loc - > lat + target - > lat ) * 0.00000005f ) ) * 0.01113195f ;
float GPS_vector_y = ( target - > lat - _current_loc - > lat ) * 0.01113195f ;
2012-08-17 03:20:30 -03:00
float GPS_vector_z = ( target - > alt - _current_loc - > alt ) ; // baro altitude(IN CM) should be adjusted to known home elevation before take off (Set altimeter).
2013-01-10 14:42:24 -04:00
float target_distance = 100.0f * pythagorous2 ( GPS_vector_x , GPS_vector_y ) ; // Careful , centimeters here locally. Baro/alt is in cm, lat/lon is in meters.
2012-08-17 03:20:30 -03:00
_roll_control_angle = 0 ;
2013-01-10 14:42:24 -04:00
_tilt_control_angle = atan2f ( GPS_vector_z , target_distance ) ;
_pan_control_angle = atan2f ( GPS_vector_x , GPS_vector_y ) ;
2012-06-13 15:55:19 -03:00
}
2012-07-07 16:56:56 -03:00
/// Stabilizes mount relative to the Earth's frame
/// Inputs:
/// _roll_control_angle desired roll angle in radians,
2012-08-05 18:48:57 -03:00
/// _tilt_control_angle desired tilt/pitch angle in radians,
/// _pan_control_angle desired pan/yaw angle in radians
2012-07-07 16:56:56 -03:00
/// Outputs:
/// _roll_angle stabilized roll angle in degrees,
2012-08-05 18:48:57 -03:00
/// _tilt_angle stabilized tilt/pitch angle in degrees,
/// _pan_angle stabilized pan/yaw angle in degrees
2012-06-13 15:55:19 -03:00
void
2012-07-07 16:56:56 -03:00
AP_Mount : : stabilize ( )
2012-06-13 15:55:19 -03:00
{
2012-08-26 20:33:45 -03:00
# if MNT_STABILIZE_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
if ( _ahrs ) {
// only do the full 3D frame transform if we are doing pan control
if ( _stab_pan ) {
Matrix3f m ; ///< holds 3 x 3 matrix, var is used as temp in calcs
Matrix3f cam ; ///< Rotation matrix earth to camera. Desired camera from input.
Matrix3f gimbal_target ; ///< Rotation matrix from plane to camera. Then Euler angles to the servos.
m = _ahrs - > get_dcm_matrix ( ) ;
m . transpose ( ) ;
cam . from_euler ( _roll_control_angle , _tilt_control_angle , _pan_control_angle ) ;
gimbal_target = m * cam ;
gimbal_target . to_euler ( & _roll_angle , & _tilt_angle , & _pan_angle ) ;
_roll_angle = _stab_roll ? degrees ( _roll_angle ) : degrees ( _roll_control_angle ) ;
_tilt_angle = _stab_tilt ? degrees ( _tilt_angle ) : degrees ( _tilt_control_angle ) ;
_pan_angle = degrees ( _pan_angle ) ;
} else {
// otherwise base mount roll and tilt on the ahrs
// roll/tilt attitude, plus any requested angle
_roll_angle = degrees ( _roll_control_angle ) ;
_tilt_angle = degrees ( _tilt_control_angle ) ;
_pan_angle = degrees ( _pan_control_angle ) ;
if ( _stab_roll ) {
_roll_angle - = degrees ( _ahrs - > roll ) ;
}
if ( _stab_tilt ) {
_tilt_angle - = degrees ( _ahrs - > pitch ) ;
}
}
} else {
2012-08-26 20:33:45 -03:00
# endif
2012-08-17 03:20:30 -03:00
_roll_angle = degrees ( _roll_control_angle ) ;
_tilt_angle = degrees ( _tilt_control_angle ) ;
_pan_angle = degrees ( _pan_control_angle ) ;
2012-08-26 20:33:45 -03:00
# if MNT_STABILIZE_OPTION == ENABLED
2012-08-17 03:20:30 -03:00
}
2012-08-26 20:33:45 -03:00
# endif
2012-06-13 15:55:19 -03:00
}
2012-08-05 18:48:57 -03:00
/*
2012-08-17 03:20:30 -03:00
* /// For testing and development. Called in the medium loop.
* void
* AP_Mount : : debug_output ( )
* { Serial3 . print ( " current - " ) ;
* Serial3 . print ( " lat " ) ;
* Serial3 . print ( _current_loc - > lat ) ;
* Serial3 . print ( " ,lon " ) ;
* Serial3 . print ( _current_loc - > lng ) ;
* Serial3 . print ( " ,alt " ) ;
* Serial3 . println ( _current_loc - > alt ) ;
*
* Serial3 . print ( " gps - " ) ;
* Serial3 . print ( " lat " ) ;
* Serial3 . print ( _gps - > latitude ) ;
* Serial3 . print ( " ,lon " ) ;
* Serial3 . print ( _gps - > longitude ) ;
* Serial3 . print ( " ,alt " ) ;
* Serial3 . print ( _gps - > altitude ) ;
* Serial3 . println ( ) ;
*
* Serial3 . print ( " target - " ) ;
* Serial3 . print ( " lat " ) ;
* Serial3 . print ( _target_GPS_location . lat ) ;
* Serial3 . print ( " ,lon " ) ;
* Serial3 . print ( _target_GPS_location . lng ) ;
* Serial3 . print ( " ,alt " ) ;
* Serial3 . print ( _target_GPS_location . alt ) ;
* Serial3 . print ( " hdg to targ " ) ;
* Serial3 . print ( degrees ( _pan_control_angle ) ) ;
* Serial3 . println ( ) ;
* }
*/
2012-08-05 18:48:57 -03:00
/// saturate to the closest angle limit if outside of [min max] angle interval
/// input angle is in degrees * 10
int16_t
AP_Mount : : closest_limit ( int16_t angle , int16_t * angle_min , int16_t * angle_max )
{
2012-08-17 03:20:30 -03:00
// Make sure the angle lies in the interval [-180 .. 180[ degrees
while ( angle < - 1800 ) angle + = 3600 ;
while ( angle > = 1800 ) angle - = 3600 ;
// Make sure the angle limits lie in the interval [-180 .. 180[ degrees
while ( * angle_min < - 1800 ) * angle_min + = 3600 ;
while ( * angle_min > = 1800 ) * angle_min - = 3600 ;
while ( * angle_max < - 1800 ) * angle_max + = 3600 ;
while ( * angle_max > = 1800 ) * angle_max - = 3600 ;
// TODO call this function somehow, otherwise this will never work
//set_range(min, max);
// If the angle is outside servo limits, saturate the angle to the closest limit
// On a circle the closest angular position must be carefully calculated to account for wrap-around
if ( ( angle < * angle_min ) & & ( angle > * angle_max ) ) {
// angle error if min limit is used
int16_t err_min = * angle_min - angle + ( angle < * angle_min ? 0 : 3600 ) ; // add 360 degrees if on the "wrong side"
// angle error if max limit is used
int16_t err_max = angle - * angle_max + ( angle > * angle_max ? 0 : 3600 ) ; // add 360 degrees if on the "wrong side"
angle = err_min < err_max ? * angle_min : * angle_max ;
}
return angle ;
2012-08-05 18:48:57 -03:00
}
/// all angles are degrees * 10 units
void
2012-09-08 02:12:52 -03:00
AP_Mount : : move_servo ( uint8_t function_idx , int16_t angle , int16_t angle_min , int16_t angle_max )
2012-08-05 18:48:57 -03:00
{
2012-09-08 02:12:52 -03:00
// saturate to the closest angle limit if outside of [min max] angle interval
int16_t servo_out = closest_limit ( angle , & angle_min , & angle_max ) ;
RC_Channel_aux : : move_servo ( ( RC_Channel_aux : : Aux_servo_function_t ) function_idx , servo_out , angle_min , angle_max ) ;
2012-08-05 18:48:57 -03:00
}