2017-10-04 23:19:22 -03:00
# include "AP_Winch.h"
2023-03-02 20:48:38 -04:00
# if AP_WINCH_ENABLED
2023-09-25 04:35:54 -03:00
# include <GCS_MAVLink/GCS.h>
2020-08-06 22:37:36 -03:00
# include "AP_Winch_PWM.h"
2020-07-24 05:29:43 -03:00
# include "AP_Winch_Daiwa.h"
2017-10-04 23:19:22 -03:00
extern const AP_HAL : : HAL & hal ;
const AP_Param : : GroupInfo AP_Winch : : var_info [ ] = {
2020-07-24 05:29:25 -03:00
// 0 was ENABLE
2017-10-04 23:19:22 -03:00
2020-08-07 01:12:23 -03:00
// @Param: _TYPE
2017-10-04 23:19:22 -03:00
// @DisplayName: Winch Type
// @Description: Winch Type
// @User: Standard
2020-08-06 22:37:36 -03:00
// @Values: 0:None, 1:PWM, 2:Daiwa
2020-07-24 05:29:25 -03:00
AP_GROUPINFO_FLAGS ( " _TYPE " , 1 , AP_Winch , config . type , ( int8_t ) WinchType : : NONE , AP_PARAM_FLAG_ENABLE ) ,
2017-10-04 23:19:22 -03:00
// @Param: _RATE_MAX
// @DisplayName: Winch deploy or retract rate maximum
// @Description: Winch deploy or retract rate maximum. Set to maximum rate with no load.
// @User: Standard
// @Range: 0 10
// @Units: m/s
AP_GROUPINFO ( " _RATE_MAX " , 2 , AP_Winch , config . rate_max , 1.0f ) ,
// @Param: _POS_P
// @DisplayName: Winch control position error P gain
// @Description: Winch control position error P gain
// @Range: 0.01 10.0
// @User: Standard
2020-07-24 05:29:25 -03:00
AP_GROUPINFO ( " _POS_P " , 3 , AP_Winch , config . pos_p , 1.0f ) ,
2017-10-04 23:19:22 -03:00
2023-09-25 04:35:54 -03:00
// @Param: _OPTIONS
// @DisplayName: Winch options
// @Description: Winch options
2023-10-02 02:02:40 -03:00
// @Bitmask: 0:Spin freely on startup, 1:Verbose output, 2:Retry if stuck (Daiwa only)
2023-09-25 04:35:54 -03:00
// @User: Standard
2023-10-02 02:02:40 -03:00
AP_GROUPINFO ( " _OPTIONS " , 4 , AP_Winch , config . options , 7.0f ) ,
2023-09-25 04:35:54 -03:00
2020-07-24 05:29:25 -03:00
// 4 was _RATE_PID
2017-10-04 23:19:22 -03:00
AP_GROUPEND
} ;
AP_Winch : : AP_Winch ( )
{
2020-07-24 05:29:25 -03:00
if ( _singleton ) {
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
AP_HAL : : panic ( " Too many winches " ) ;
# endif
return ;
}
_singleton = this ;
2017-10-04 23:19:22 -03:00
AP_Param : : setup_object_defaults ( this , var_info ) ;
}
// indicate whether this module is enabled
bool AP_Winch : : enabled ( ) const
{
2020-07-24 05:29:25 -03:00
return ( ( config . type > 0 ) & & ( backend ! = nullptr ) ) ;
2017-10-04 23:19:22 -03:00
}
2020-07-24 05:29:25 -03:00
// true if winch is healthy
bool AP_Winch : : healthy ( ) const
2017-10-04 23:19:22 -03:00
{
2020-07-24 05:29:25 -03:00
if ( backend ! = nullptr ) {
return backend - > healthy ( ) ;
2017-10-04 23:19:22 -03:00
}
2020-07-24 05:29:25 -03:00
return false ;
}
2017-10-04 23:19:22 -03:00
2020-07-24 05:29:25 -03:00
void AP_Winch : : init ( )
{
switch ( ( WinchType ) config . type . get ( ) ) {
case WinchType : : NONE :
2017-10-04 23:19:22 -03:00
break ;
2020-08-06 22:37:36 -03:00
case WinchType : : PWM :
2024-05-26 22:24:15 -03:00
backend = NEW_NOTHROW AP_Winch_PWM ( config ) ;
2017-10-04 23:19:22 -03:00
break ;
2020-07-24 05:29:43 -03:00
case WinchType : : DAIWA :
2024-05-26 22:24:15 -03:00
backend = NEW_NOTHROW AP_Winch_Daiwa ( config ) ;
2020-07-24 05:29:43 -03:00
break ;
2017-10-04 23:19:22 -03:00
default :
break ;
}
if ( backend ! = nullptr ) {
2020-07-24 05:29:25 -03:00
backend - > init ( ) ;
2023-09-25 04:35:54 -03:00
// initialise control mode
if ( backend - > option_enabled ( Options : : SpinFreelyOnStartup ) ) {
relax ( ) ;
} else {
set_desired_rate ( 0 ) ;
}
2017-10-04 23:19:22 -03:00
}
}
2020-08-06 22:23:27 -03:00
// release specified length of cable (in meters)
2020-07-24 05:29:25 -03:00
void AP_Winch : : release_length ( float length )
2017-10-04 23:19:22 -03:00
{
2020-07-24 05:29:25 -03:00
if ( backend = = nullptr ) {
return ;
2017-10-04 23:19:22 -03:00
}
2020-07-24 05:29:25 -03:00
config . length_desired = backend - > get_current_length ( ) + length ;
2020-08-06 22:23:27 -03:00
config . control_mode = ControlMode : : POSITION ;
2023-09-25 04:35:54 -03:00
// display verbose output to user
if ( backend - > option_enabled ( Options : : VerboseOutput ) ) {
2023-10-08 21:21:31 -03:00
GCS_SEND_TEXT ( MAV_SEVERITY_INFO , " Winch: %s %4.1fm to %4.1fm " , is_negative ( length ) ? " raising " : " lowering " , ( double ) fabsf ( length ) , ( double ) config . length_desired ) ;
2023-09-25 04:35:54 -03:00
}
2017-10-04 23:19:22 -03:00
}
// deploy line at specified speed in m/s (+ve deploys line, -ve retracts line, 0 stops)
void AP_Winch : : set_desired_rate ( float rate )
{
config . rate_desired = constrain_float ( rate , - get_rate_max ( ) , get_rate_max ( ) ) ;
2020-08-06 22:23:27 -03:00
config . control_mode = ControlMode : : RATE ;
2020-07-24 05:29:25 -03:00
}
// send status to ground station
void AP_Winch : : send_status ( const GCS_MAVLINK & channel )
{
if ( backend ! = nullptr ) {
backend - > send_status ( channel ) ;
}
}
// returns true if pre arm checks have passed
bool AP_Winch : : pre_arm_check ( char * failmsg , uint8_t failmsg_len ) const
{
// succeed if winch is disabled
if ( ( WinchType ) config . type . get ( ) = = WinchType : : NONE ) {
return true ;
}
// fail if unhealthy
if ( ! healthy ( ) ) {
2020-08-06 22:23:27 -03:00
hal . util - > snprintf ( failmsg , failmsg_len , " winch unhealthy " ) ;
2020-07-24 05:29:25 -03:00
return false ;
}
return true ;
2017-10-04 23:19:22 -03:00
}
// update - should be called at at least 10hz
# define PASS_TO_BACKEND(function_name) \
void AP_Winch : : function_name ( ) \
{ \
if ( ! enabled ( ) ) { \
return ; \
} \
if ( backend ! = nullptr ) { \
backend - > function_name ( ) ; \
} \
}
PASS_TO_BACKEND ( update )
2023-07-13 21:58:09 -03:00
# if HAL_LOGGING_ENABLED
2020-07-24 05:29:25 -03:00
PASS_TO_BACKEND ( write_log )
2023-07-13 21:58:09 -03:00
# endif
2018-07-17 21:55:53 -03:00
# undef PASS_TO_BACKEND
2020-07-24 05:29:25 -03:00
/*
* Get the AP_Winch singleton
*/
AP_Winch * AP_Winch : : _singleton ;
AP_Winch * AP_Winch : : get_singleton ( )
{
return _singleton ;
}
namespace AP {
AP_Winch * winch ( )
{
return AP_Winch : : get_singleton ( ) ;
}
} ;
2023-03-02 20:48:38 -04:00
# endif // AP_WINCH_ENABLED