mirror of https://github.com/ArduPilot/ardupilot
AP_Camera: RunCam camera backend
RunCam parameter conversion add RunCam camera settings and control
This commit is contained in:
parent
90fc426fd5
commit
399f9f6f98
|
@ -6,6 +6,7 @@
|
||||||
#include <AP_Math/AP_Math.h>
|
#include <AP_Math/AP_Math.h>
|
||||||
#include <AP_HAL/AP_HAL.h>
|
#include <AP_HAL/AP_HAL.h>
|
||||||
#include <SRV_Channel/SRV_Channel.h>
|
#include <SRV_Channel/SRV_Channel.h>
|
||||||
|
#include <AP_Vehicle/AP_Vehicle.h>
|
||||||
#include "AP_Camera_Backend.h"
|
#include "AP_Camera_Backend.h"
|
||||||
#include "AP_Camera_Servo.h"
|
#include "AP_Camera_Servo.h"
|
||||||
#include "AP_Camera_Relay.h"
|
#include "AP_Camera_Relay.h"
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
#include "AP_Camera_MAVLink.h"
|
#include "AP_Camera_MAVLink.h"
|
||||||
#include "AP_Camera_MAVLinkCamV2.h"
|
#include "AP_Camera_MAVLinkCamV2.h"
|
||||||
#include "AP_Camera_Scripting.h"
|
#include "AP_Camera_Scripting.h"
|
||||||
|
#include "AP_RunCam.h"
|
||||||
|
|
||||||
const AP_Param::GroupInfo AP_Camera::var_info[] = {
|
const AP_Param::GroupInfo AP_Camera::var_info[] = {
|
||||||
|
|
||||||
|
@ -41,10 +43,24 @@ const AP_Param::GroupInfo AP_Camera::var_info[] = {
|
||||||
// @Path: AP_Camera_Params.cpp
|
// @Path: AP_Camera_Params.cpp
|
||||||
AP_SUBGROUPINFO(_params[1], "2", 13, AP_Camera, AP_Camera_Params),
|
AP_SUBGROUPINFO(_params[1], "2", 13, AP_Camera, AP_Camera_Params),
|
||||||
#endif
|
#endif
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
// @Group: 1_RC_
|
||||||
|
// @Path: AP_RunCam.cpp
|
||||||
|
AP_SUBGROUPVARPTR(_backends[0], "1_RC_", 14, AP_Camera, _backend_var_info[0]),
|
||||||
|
|
||||||
|
#if AP_CAMERA_MAX_INSTANCES > 1
|
||||||
|
// @Group: 2_RC_
|
||||||
|
// @Path: AP_RunCam.cpp
|
||||||
|
AP_SUBGROUPVARPTR(_backends[1], "2_RC_", 15, AP_Camera, _backend_var_info[1]),
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
AP_GROUPEND
|
AP_GROUPEND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
const AP_Param::GroupInfo *AP_Camera::_backend_var_info[AP_CAMERA_MAX_INSTANCES];
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const AP_HAL::HAL& hal;
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
AP_Camera::AP_Camera(uint32_t _log_camera_bit) :
|
AP_Camera::AP_Camera(uint32_t _log_camera_bit) :
|
||||||
|
@ -238,6 +254,17 @@ void AP_Camera::init()
|
||||||
case CameraType::SCRIPTING:
|
case CameraType::SCRIPTING:
|
||||||
_backends[instance] = NEW_NOTHROW AP_Camera_Scripting(*this, _params[instance], instance);
|
_backends[instance] = NEW_NOTHROW AP_Camera_Scripting(*this, _params[instance], instance);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
// check for RunCam driver
|
||||||
|
case CameraType::RUNCAM:
|
||||||
|
if (_backends[instance] == nullptr) { // may have already been created by the conversion code
|
||||||
|
_backends[instance] = NEW_NOTHROW AP_RunCam(*this, _params[instance], instance, _runcam_instances);
|
||||||
|
_backend_var_info[instance] = AP_RunCam::var_info;
|
||||||
|
AP_Param::load_object_from_eeprom(_backends[instance], _backend_var_info[instance]);
|
||||||
|
_runcam_instances++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case CameraType::NONE:
|
case CameraType::NONE:
|
||||||
break;
|
break;
|
||||||
|
@ -899,7 +926,11 @@ AP_Camera_Backend *AP_Camera::get_instance(uint8_t instance) const
|
||||||
void AP_Camera::convert_params()
|
void AP_Camera::convert_params()
|
||||||
{
|
{
|
||||||
// exit immediately if CAM1_TYPE has already been configured
|
// exit immediately if CAM1_TYPE has already been configured
|
||||||
if (_params[0].type.configured()) {
|
if (_params[0].type.configured()
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
&& _params[1].type.configured()
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,6 +950,42 @@ void AP_Camera::convert_params()
|
||||||
}
|
}
|
||||||
_params[0].type.set_and_save(cam1_type);
|
_params[0].type.set_and_save(cam1_type);
|
||||||
|
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
// RunCam PARAMETER_CONVERSION - Added: Nov-2024 ahead of 4.7 release
|
||||||
|
|
||||||
|
// Since slot 1 is essentially used by the trigger type, we will use slot 2 for runcam
|
||||||
|
int8_t rc_type = 0;
|
||||||
|
// find vehicle's top level key
|
||||||
|
uint16_t k_param_vehicle_key;
|
||||||
|
if (!AP_Param::find_top_level_key_by_pointer(AP::vehicle(), k_param_vehicle_key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCam protocol configured so set cam type to RunCam
|
||||||
|
bool rc_protocol_configured = false;
|
||||||
|
AP_SerialManager *serial_manager = AP_SerialManager::get_singleton();
|
||||||
|
if (serial_manager && serial_manager->find_serial(AP_SerialManager::SerialProtocol_RunCam, 0)) {
|
||||||
|
rc_protocol_configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AP_Param::ConversionInfo rc_type_info = {
|
||||||
|
k_param_vehicle_key, AP_GROUP_ELEM_IDX(1, 1), AP_PARAM_INT8, "CAM_RC_TYPE"
|
||||||
|
};
|
||||||
|
AP_Int8 rc_type_old;
|
||||||
|
const bool found_rc_type = AP_Param::find_old_parameter(&rc_type_info, &rc_type_old);
|
||||||
|
|
||||||
|
if (rc_protocol_configured || (found_rc_type && rc_type_old.get() > 0)) {
|
||||||
|
rc_type = int8_t(CameraType::RUNCAM);
|
||||||
|
_backends[1] = NEW_NOTHROW AP_RunCam(*this, _params[1], 1, _runcam_instances);
|
||||||
|
_backend_var_info[1] = AP_RunCam::var_info;
|
||||||
|
AP_Param::convert_class(k_param_vehicle_key, &_backends[1], _backend_var_info[1], 1, false);
|
||||||
|
AP_Param::invalidate_count();
|
||||||
|
_runcam_instances++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_params[1].type.set_and_save(rc_type);
|
||||||
|
#endif // AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
|
||||||
// convert CAM_DURATION (in deci-seconds) to CAM1_DURATION (in seconds)
|
// convert CAM_DURATION (in deci-seconds) to CAM1_DURATION (in seconds)
|
||||||
int8_t cam_duration = 0;
|
int8_t cam_duration = 0;
|
||||||
if (AP_Param::get_param_by_index(this, 1, AP_PARAM_INT8, &cam_duration) && (cam_duration > 0)) {
|
if (AP_Param::get_param_by_index(this, 1, AP_PARAM_INT8, &cam_duration) && (cam_duration > 0)) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ class AP_Camera_Mount;
|
||||||
class AP_Camera_MAVLink;
|
class AP_Camera_MAVLink;
|
||||||
class AP_Camera_MAVLinkCamV2;
|
class AP_Camera_MAVLinkCamV2;
|
||||||
class AP_Camera_Scripting;
|
class AP_Camera_Scripting;
|
||||||
|
class AP_RunCam;
|
||||||
|
|
||||||
/// @class Camera
|
/// @class Camera
|
||||||
/// @brief Object managing a Photo or video camera
|
/// @brief Object managing a Photo or video camera
|
||||||
|
@ -37,6 +38,7 @@ class AP_Camera {
|
||||||
friend class AP_Camera_MAVLink;
|
friend class AP_Camera_MAVLink;
|
||||||
friend class AP_Camera_MAVLinkCamV2;
|
friend class AP_Camera_MAVLinkCamV2;
|
||||||
friend class AP_Camera_Scripting;
|
friend class AP_Camera_Scripting;
|
||||||
|
friend class AP_RunCam;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -72,6 +74,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
#if AP_CAMERA_SCRIPTING_ENABLED
|
#if AP_CAMERA_SCRIPTING_ENABLED
|
||||||
SCRIPTING = 7, // Scripting backend
|
SCRIPTING = 7, // Scripting backend
|
||||||
|
#endif
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
RUNCAM = 8, // RunCam backend
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,6 +221,11 @@ protected:
|
||||||
|
|
||||||
// parameters for backends
|
// parameters for backends
|
||||||
AP_Camera_Params _params[AP_CAMERA_MAX_INSTANCES];
|
AP_Camera_Params _params[AP_CAMERA_MAX_INSTANCES];
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
// var info pointer for RunCam
|
||||||
|
static const struct AP_Param::GroupInfo *_backend_var_info[AP_CAMERA_MAX_INSTANCES];
|
||||||
|
uint8_t _runcam_instances;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const AP_Param::GroupInfo AP_Camera_Params::var_info[] = {
|
||||||
// @Param: _TYPE
|
// @Param: _TYPE
|
||||||
// @DisplayName: Camera shutter (trigger) type
|
// @DisplayName: Camera shutter (trigger) type
|
||||||
// @Description: how to trigger the camera to take a picture
|
// @Description: how to trigger the camera to take a picture
|
||||||
// @Values: 0:None, 1:Servo, 2:Relay, 3:GoPro in Solo Gimbal, 4:Mount (Siyi/Topotek/Viewpro/Xacti), 5:MAVLink, 6:MAVLinkCamV2, 7:Scripting
|
// @Values: 0:None, 1:Servo, 2:Relay, 3:GoPro in Solo Gimbal, 4:Mount (Siyi/Topotek/Viewpro/Xacti), 5:MAVLink, 6:MAVLinkCamV2, 7:Scripting, 8:RunCam
|
||||||
// @User: Standard
|
// @User: Standard
|
||||||
AP_GROUPINFO_FLAGS("_TYPE", 1, AP_Camera_Params, type, 0, AP_PARAM_FLAG_ENABLE),
|
AP_GROUPINFO_FLAGS("_TYPE", 1, AP_Camera_Params, type, 0, AP_PARAM_FLAG_ENABLE),
|
||||||
|
|
||||||
|
|
|
@ -62,3 +62,7 @@
|
||||||
#ifndef AP_CAMERA_INFO_FROM_SCRIPT_ENABLED
|
#ifndef AP_CAMERA_INFO_FROM_SCRIPT_ENABLED
|
||||||
#define AP_CAMERA_INFO_FROM_SCRIPT_ENABLED AP_CAMERA_SCRIPTING_ENABLED
|
#define AP_CAMERA_INFO_FROM_SCRIPT_ENABLED AP_CAMERA_SCRIPTING_ENABLED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
#define AP_CAMERA_RUNCAM_ENABLED AP_CAMERA_BACKEND_DEFAULT_ENABLED && HAL_RUNCAM_ENABLED
|
||||||
|
#endif
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
#include "AP_RunCam.h"
|
#include "AP_RunCam.h"
|
||||||
|
|
||||||
#if HAL_RUNCAM_ENABLED
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
|
||||||
#include <AP_Math/AP_Math.h>
|
#include <AP_Math/AP_Math.h>
|
||||||
#include <AP_Math/crc.h>
|
#include <AP_Math/crc.h>
|
||||||
|
@ -36,7 +36,7 @@ const AP_Param::GroupInfo AP_RunCam::var_info[] = {
|
||||||
// @DisplayName: RunCam device type
|
// @DisplayName: RunCam device type
|
||||||
// @Description: RunCam device type used to determine OSD menu structure and shutter options.
|
// @Description: RunCam device type used to determine OSD menu structure and shutter options.
|
||||||
// @Values: 0:Disabled, 1:RunCam Split Micro/RunCam with UART, 2:RunCam Split, 3:RunCam Split4 4k, 4:RunCam Hybrid/RunCam Thumb Pro, 5:Runcam 2 4k
|
// @Values: 0:Disabled, 1:RunCam Split Micro/RunCam with UART, 2:RunCam Split, 3:RunCam Split4 4k, 4:RunCam Hybrid/RunCam Thumb Pro, 5:Runcam 2 4k
|
||||||
AP_GROUPINFO_FLAGS("TYPE", 1, AP_RunCam, _cam_type, int(DeviceType::Disabled), AP_PARAM_FLAG_ENABLE),
|
AP_GROUPINFO_FLAGS("TYPE", 1, AP_RunCam, _cam_type, int(DeviceModel::SplitMicro), AP_PARAM_FLAG_ENABLE),
|
||||||
|
|
||||||
// @Param: FEATURES
|
// @Param: FEATURES
|
||||||
// @DisplayName: RunCam features available
|
// @DisplayName: RunCam features available
|
||||||
|
@ -55,13 +55,13 @@ const AP_Param::GroupInfo AP_RunCam::var_info[] = {
|
||||||
// @DisplayName: RunCam button delay before allowing further button presses
|
// @DisplayName: RunCam button delay before allowing further button presses
|
||||||
// @Description: Time it takes for the a RunCam button press to be actived in ms. If this is too short then commands can get out of sync.
|
// @Description: Time it takes for the a RunCam button press to be actived in ms. If this is too short then commands can get out of sync.
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("BTN_DELAY", 4, AP_RunCam, _button_delay_ms, RUNCAM_DEFAULT_BUTTON_PRESS_DELAY),
|
AP_GROUPINFO("BTN_DELY", 4, AP_RunCam, _button_delay_ms, RUNCAM_DEFAULT_BUTTON_PRESS_DELAY),
|
||||||
|
|
||||||
// @Param: MDE_DELAY
|
// @Param: MDE_DELAY
|
||||||
// @DisplayName: RunCam mode delay before allowing further button presses
|
// @DisplayName: RunCam mode delay before allowing further button presses
|
||||||
// @Description: Time it takes for the a RunCam mode button press to be actived in ms. If a mode change first requires a video recording change then double this value is used. If this is too short then commands can get out of sync.
|
// @Description: Time it takes for the a RunCam mode button press to be actived in ms. If a mode change first requires a video recording change then double this value is used. If this is too short then commands can get out of sync.
|
||||||
// @User: Advanced
|
// @User: Advanced
|
||||||
AP_GROUPINFO("MDE_DELAY", 5, AP_RunCam, _mode_delay_ms, 800),
|
AP_GROUPINFO("MDE_DELY", 5, AP_RunCam, _mode_delay_ms, 800),
|
||||||
|
|
||||||
// @Param: CONTROL
|
// @Param: CONTROL
|
||||||
// @DisplayName: RunCam control option
|
// @DisplayName: RunCam control option
|
||||||
|
@ -118,13 +118,24 @@ AP_RunCam::Menu AP_RunCam::_menus[RUNCAM_MAX_DEVICE_TYPES] = {
|
||||||
{ 6, { 3, 10, 2, 2, 8 }}, // Runcam 2 4K
|
{ 6, { 3, 10, 2, 2, 8 }}, // Runcam 2 4K
|
||||||
};
|
};
|
||||||
|
|
||||||
AP_RunCam::AP_RunCam()
|
const char* AP_RunCam::_models[RUNCAM_MAX_DEVICE_TYPES] = {
|
||||||
|
"SplitMicro",
|
||||||
|
"Split",
|
||||||
|
"Split4k",
|
||||||
|
"Hybrid",
|
||||||
|
"Run24k"
|
||||||
|
};
|
||||||
|
|
||||||
|
AP_RunCam::AP_RunCam(AP_Camera &frontend, AP_Camera_Params ¶ms, uint8_t instance, uint8_t runcam_instance)
|
||||||
|
: AP_Camera_Backend(frontend, params, instance), _runcam_instance(runcam_instance)
|
||||||
{
|
{
|
||||||
AP_Param::setup_object_defaults(this, var_info);
|
AP_Param::setup_object_defaults(this, var_info);
|
||||||
if (_singleton != nullptr) {
|
if (_singleton != nullptr && _singleton->_instance == instance) {
|
||||||
AP_HAL::panic("AP_RunCam must be singleton");
|
AP_HAL::panic("AP_RunCam instance must be a singleton %u\n", instance);
|
||||||
}
|
}
|
||||||
|
if (_singleton == nullptr) {
|
||||||
_singleton = this;
|
_singleton = this;
|
||||||
|
}
|
||||||
_cam_type.set(constrain_int16(_cam_type, 0, RUNCAM_MAX_DEVICE_TYPES));
|
_cam_type.set(constrain_int16(_cam_type, 0, RUNCAM_MAX_DEVICE_TYPES));
|
||||||
_video_recording = VideoOption(_cam_control_option & uint8_t(ControlOption::VIDEO_RECORDING_AT_BOOT));
|
_video_recording = VideoOption(_cam_control_option & uint8_t(ControlOption::VIDEO_RECORDING_AT_BOOT));
|
||||||
}
|
}
|
||||||
|
@ -134,19 +145,19 @@ void AP_RunCam::init()
|
||||||
{
|
{
|
||||||
AP_SerialManager *serial_manager = AP_SerialManager::get_singleton();
|
AP_SerialManager *serial_manager = AP_SerialManager::get_singleton();
|
||||||
if (serial_manager) {
|
if (serial_manager) {
|
||||||
uart = serial_manager->find_serial(AP_SerialManager::SerialProtocol_RunCam, 0);
|
uart = serial_manager->find_serial(AP_SerialManager::SerialProtocol_RunCam, _runcam_instance);
|
||||||
}
|
}
|
||||||
if (uart != nullptr) {
|
if (uart != nullptr) {
|
||||||
/*
|
/*
|
||||||
if the user has setup a serial port as a runcam then default
|
if the user has setup a serial port as a runcam then default
|
||||||
type to the split micro (Andy's development platform!). This makes setup a bit easier for most
|
type to the split micro (Andy's development platform!). This makes setup a bit easier for most
|
||||||
users while still enabling parameters to be hidden for users
|
users while still enabling parameters to be hidden for users
|
||||||
without a runcam
|
without a RunCam
|
||||||
*/
|
*/
|
||||||
_cam_type.set_default(int8_t(DeviceType::SplitMicro));
|
_cam_type.set_default(int8_t(DeviceModel::SplitMicro));
|
||||||
AP_Param::invalidate_count();
|
AP_Param::invalidate_count();
|
||||||
}
|
}
|
||||||
if (_cam_type.get() == int8_t(DeviceType::Disabled)) {
|
if (_cam_type.get() == int8_t(DeviceModel::Disabled)) {
|
||||||
uart = nullptr;
|
uart = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +167,7 @@ void AP_RunCam::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split and Runcam 2 4k requires two mode presses to get into the menu
|
// Split and Runcam 2 4k requires two mode presses to get into the menu
|
||||||
if (_cam_type.get() == int8_t(DeviceType::Split) || _cam_type.get() == int8_t(DeviceType::Run24k)) {
|
if (_cam_type.get() == int8_t(DeviceModel::Split) || _cam_type.get() == int8_t(DeviceModel::Run24k)) {
|
||||||
_menu_enter_level = -1;
|
_menu_enter_level = -1;
|
||||||
_in_menu = -1;
|
_in_menu = -1;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +232,7 @@ void AP_RunCam::osd_option() {
|
||||||
// input update loop
|
// input update loop
|
||||||
void AP_RunCam::update()
|
void AP_RunCam::update()
|
||||||
{
|
{
|
||||||
if (uart == nullptr || _cam_type.get() == int8_t(DeviceType::Disabled)) {
|
if (uart == nullptr || _cam_type.get() == int8_t(DeviceModel::Disabled)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,12 +562,12 @@ void AP_RunCam::handle_2_key_simulation_process(Event ev)
|
||||||
|
|
||||||
case Event::IN_MENU_ENTER:
|
case Event::IN_MENU_ENTER:
|
||||||
// in a sub-menu and save-and-exit was selected
|
// in a sub-menu and save-and-exit was selected
|
||||||
if (_in_menu > 1 && get_top_menu_length() > 0 && _sub_menu_pos == (get_sub_menu_length(_top_menu_pos) - 1) && DeviceType(_cam_type.get()) != DeviceType::Run24k) {
|
if (_in_menu > 1 && get_top_menu_length() > 0 && _sub_menu_pos == (get_sub_menu_length(_top_menu_pos) - 1) && DeviceModel(_cam_type.get()) != DeviceModel::Run24k) {
|
||||||
simulate_camera_button(ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_WIFI_BTN, _button_delay_ms);
|
simulate_camera_button(ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_WIFI_BTN, _button_delay_ms);
|
||||||
_sub_menu_pos = 0;
|
_sub_menu_pos = 0;
|
||||||
_in_menu--;
|
_in_menu--;
|
||||||
// in the top-menu and save-and-exit was selected
|
// in the top-menu and save-and-exit was selected
|
||||||
} else if (_in_menu == 1 && get_top_menu_length() > 0 && _top_menu_pos == (get_top_menu_length() - 1) && DeviceType(_cam_type.get()) != DeviceType::Run24k) {
|
} else if (_in_menu == 1 && get_top_menu_length() > 0 && _top_menu_pos == (get_top_menu_length() - 1) && DeviceModel(_cam_type.get()) != DeviceModel::Run24k) {
|
||||||
simulate_camera_button(ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_WIFI_BTN, _mode_delay_ms);
|
simulate_camera_button(ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_WIFI_BTN, _mode_delay_ms);
|
||||||
_in_menu--;
|
_in_menu--;
|
||||||
_state = State::EXITING_MENU;
|
_state = State::EXITING_MENU;
|
||||||
|
@ -712,7 +723,7 @@ void AP_RunCam::handle_5_key_simulation_response(const Request& request)
|
||||||
|
|
||||||
// command to start recording
|
// command to start recording
|
||||||
AP_RunCam::ControlOperation AP_RunCam::start_recording_command() const {
|
AP_RunCam::ControlOperation AP_RunCam::start_recording_command() const {
|
||||||
if (DeviceType(_cam_type.get()) == DeviceType::Split4k || DeviceType(_cam_type.get()) == DeviceType::Hybrid || DeviceType(_cam_type.get()) == DeviceType::Run24k) {
|
if (DeviceModel(_cam_type.get()) == DeviceModel::Split4k || DeviceModel(_cam_type.get()) == DeviceModel::Hybrid || DeviceModel(_cam_type.get()) == DeviceModel::Run24k) {
|
||||||
return ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_POWER_BTN;
|
return ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_POWER_BTN;
|
||||||
} else {
|
} else {
|
||||||
return ControlOperation::RCDEVICE_PROTOCOL_CHANGE_START_RECORDING;
|
return ControlOperation::RCDEVICE_PROTOCOL_CHANGE_START_RECORDING;
|
||||||
|
@ -721,7 +732,7 @@ AP_RunCam::ControlOperation AP_RunCam::start_recording_command() const {
|
||||||
|
|
||||||
// command to stop recording
|
// command to stop recording
|
||||||
AP_RunCam::ControlOperation AP_RunCam::stop_recording_command() const {
|
AP_RunCam::ControlOperation AP_RunCam::stop_recording_command() const {
|
||||||
if (DeviceType(_cam_type.get()) == DeviceType::Split4k || DeviceType(_cam_type.get()) == DeviceType::Hybrid || DeviceType(_cam_type.get()) == DeviceType::Run24k) {
|
if (DeviceModel(_cam_type.get()) == DeviceModel::Split4k || DeviceModel(_cam_type.get()) == DeviceModel::Hybrid || DeviceModel(_cam_type.get()) == DeviceModel::Run24k) {
|
||||||
return ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_POWER_BTN;
|
return ControlOperation::RCDEVICE_PROTOCOL_SIMULATE_POWER_BTN;
|
||||||
} else {
|
} else {
|
||||||
return ControlOperation::RCDEVICE_PROTOCOL_CHANGE_STOP_RECORDING;
|
return ControlOperation::RCDEVICE_PROTOCOL_CHANGE_STOP_RECORDING;
|
||||||
|
@ -1058,8 +1069,86 @@ uint8_t AP_RunCam::Request::get_expected_response_length(const Command command)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AP_Camera API
|
||||||
|
|
||||||
|
// return true if healthy
|
||||||
|
bool AP_RunCam::healthy() const
|
||||||
|
{
|
||||||
|
return camera_ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
// momentary switch to change camera between picture and video modes
|
||||||
|
void AP_RunCam::cam_mode_toggle() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry point to actually take a picture. returns true on success
|
||||||
|
bool AP_RunCam::trigger_pic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send camera information message to GCS
|
||||||
|
void AP_RunCam::send_camera_information(mavlink_channel_t chan) const
|
||||||
|
{
|
||||||
|
// exit immediately if not initialised
|
||||||
|
if (!camera_ready() || _cam_type.get() == 0 || _cam_type.get() > int8_t(ARRAY_SIZE(_models))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t vendor_name[32] = "RunCam";
|
||||||
|
uint8_t model_name[32] {};
|
||||||
|
strncpy((char *)model_name, _models[_cam_type.get()-1], MIN(sizeof(model_name), sizeof(_models[_cam_type.get()-1])));
|
||||||
|
const char cam_definition_uri[140] {};
|
||||||
|
|
||||||
|
// capability flags
|
||||||
|
uint32_t flags = 0;
|
||||||
|
|
||||||
|
if (has_feature(Feature::RCDEVICE_PROTOCOL_FEATURE_START_RECORDING)) {
|
||||||
|
flags = CAMERA_CAP_FLAGS_CAPTURE_VIDEO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_feature(Feature::RCDEVICE_PROTOCOL_FEATURE_CHANGE_MODE)) {
|
||||||
|
flags |= CAMERA_CAP_FLAGS_CAPTURE_IMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send CAMERA_INFORMATION message
|
||||||
|
mavlink_msg_camera_information_send(
|
||||||
|
chan,
|
||||||
|
AP_HAL::millis(), // time_boot_ms
|
||||||
|
vendor_name, // vendor_name uint8_t[32]
|
||||||
|
model_name, // model_name uint8_t[32]
|
||||||
|
0, // firmware version uint32_t
|
||||||
|
NaNf, // sensor_size_h float (mm)
|
||||||
|
NaNf, // sensor_size_v float (mm)
|
||||||
|
0, // sensor_size_v float (mm)
|
||||||
|
0, // resolution_h uint16_t (pix)
|
||||||
|
0, // resolution_v uint16_t (pix)
|
||||||
|
0, // lens_id uint8_t
|
||||||
|
flags, // flags uint32_t (CAMERA_CAP_FLAGS)
|
||||||
|
0, // cam_definition_version uint16_t
|
||||||
|
cam_definition_uri, // cam_definition_uri char[140]
|
||||||
|
_instance + 1); // gimbal_device_id uint8_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// send camera settings message to GCS
|
||||||
|
void AP_RunCam::send_camera_settings(mavlink_channel_t chan) const
|
||||||
|
{
|
||||||
|
// exit immediately if not initialised
|
||||||
|
if (!camera_ready()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send CAMERA_SETTINGS message
|
||||||
|
mavlink_msg_camera_settings_send(
|
||||||
|
chan,
|
||||||
|
AP_HAL::millis(), // time_boot_ms
|
||||||
|
_video_recording == VideoOption::RECORDING ? CAMERA_MODE_VIDEO : CAMERA_MODE_IMAGE, // camera mode (0:image, 1:video, 2:image survey)
|
||||||
|
NaNf, // zoomLevel float, percentage from 0 to 100, NaN if unknown
|
||||||
|
NaNf); // focusLevel float, percentage from 0 to 100, NaN if unknown
|
||||||
|
}
|
||||||
|
|
||||||
AP_RunCam *AP::runcam() {
|
AP_RunCam *AP::runcam() {
|
||||||
return AP_RunCam::get_singleton();
|
return AP_RunCam::get_singleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAL_RUNCAM_ENABLED
|
#endif // AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
|
|
||||||
#include "AP_Camera_config.h"
|
#include "AP_Camera_config.h"
|
||||||
|
|
||||||
#if HAL_RUNCAM_ENABLED
|
#include "AP_Camera_Backend.h"
|
||||||
|
|
||||||
|
#if AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
|
||||||
#include <AP_Param/AP_Param.h>
|
#include <AP_Param/AP_Param.h>
|
||||||
#include <RC_Channel/RC_Channel.h>
|
#include <RC_Channel/RC_Channel.h>
|
||||||
|
@ -38,10 +40,10 @@
|
||||||
|
|
||||||
/// @class AP_RunCam
|
/// @class AP_RunCam
|
||||||
/// @brief Object managing a RunCam device
|
/// @brief Object managing a RunCam device
|
||||||
class AP_RunCam
|
class AP_RunCam : public AP_Camera_Backend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AP_RunCam();
|
AP_RunCam(AP_Camera &frontend, AP_Camera_Params ¶ms, uint8_t instance, uint8_t runcam_instance);
|
||||||
|
|
||||||
// do not allow copies
|
// do not allow copies
|
||||||
CLASS_NO_COPY(AP_RunCam);
|
CLASS_NO_COPY(AP_RunCam);
|
||||||
|
@ -51,7 +53,7 @@ public:
|
||||||
return _singleton;
|
return _singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class DeviceType {
|
enum class DeviceModel {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
SplitMicro = 1, // video support only
|
SplitMicro = 1, // video support only
|
||||||
Split = 2, // camera and video support
|
Split = 2, // camera and video support
|
||||||
|
@ -79,22 +81,49 @@ public:
|
||||||
VIDEO_RECORDING_AT_BOOT = (1 << 4)
|
VIDEO_RECORDING_AT_BOOT = (1 << 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// return true if healthy
|
||||||
|
bool healthy() const override;
|
||||||
|
|
||||||
|
// momentary switch to change camera between picture and video modes
|
||||||
|
void cam_mode_toggle() override;
|
||||||
|
|
||||||
|
// entry point to actually take a picture. returns true on success
|
||||||
|
bool trigger_pic() override;
|
||||||
|
|
||||||
|
// send camera information message to GCS
|
||||||
|
void send_camera_information(mavlink_channel_t chan) const override;
|
||||||
|
|
||||||
|
// send camera settings message to GCS
|
||||||
|
void send_camera_settings(mavlink_channel_t chan) const override;
|
||||||
|
|
||||||
// initialize the RunCam driver
|
// initialize the RunCam driver
|
||||||
void init();
|
void init() override;
|
||||||
// camera button simulation
|
// camera button simulation
|
||||||
bool simulate_camera_button(const ControlOperation operation, const uint32_t transition_timeout = RUNCAM_DEFAULT_BUTTON_PRESS_DELAY);
|
bool simulate_camera_button(const ControlOperation operation, const uint32_t transition_timeout = RUNCAM_DEFAULT_BUTTON_PRESS_DELAY);
|
||||||
// start the video
|
// start the video
|
||||||
void start_recording();
|
void start_recording();
|
||||||
// stop the video
|
// stop the video
|
||||||
void stop_recording();
|
void stop_recording();
|
||||||
|
// start or stop video recording. returns true on success
|
||||||
|
// set start_recording = true to start record, false to stop recording
|
||||||
|
bool record_video(bool _start_recording) override {
|
||||||
|
if (_start_recording) {
|
||||||
|
start_recording();
|
||||||
|
} else {
|
||||||
|
stop_recording();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// enter the OSD menu
|
// enter the OSD menu
|
||||||
void enter_osd();
|
void enter_osd();
|
||||||
// exit the OSD menu
|
// exit the OSD menu
|
||||||
void exit_osd();
|
void exit_osd();
|
||||||
// OSD control determined by camera options
|
// OSD control determined by camera options
|
||||||
void osd_option();
|
void osd_option();
|
||||||
// update loop
|
// update - should be called at 50hz
|
||||||
void update();
|
void update() override;
|
||||||
// Check whether arming is allowed
|
// Check whether arming is allowed
|
||||||
bool pre_arm_check(char *failure_msg, const uint8_t failure_msg_len) const;
|
bool pre_arm_check(char *failure_msg, const uint8_t failure_msg_len) const;
|
||||||
|
|
||||||
|
@ -265,6 +294,10 @@ private:
|
||||||
static uint8_t _sub_menu_lengths[RUNCAM_NUM_SUB_MENUS];
|
static uint8_t _sub_menu_lengths[RUNCAM_NUM_SUB_MENUS];
|
||||||
// shared inbound scratch space
|
// shared inbound scratch space
|
||||||
uint8_t _recv_buf[RUNCAM_MAX_PACKET_SIZE]; // all the response contexts use same recv buffer
|
uint8_t _recv_buf[RUNCAM_MAX_PACKET_SIZE]; // all the response contexts use same recv buffer
|
||||||
|
// the runcam instance
|
||||||
|
uint8_t _runcam_instance;
|
||||||
|
|
||||||
|
static const char* _models[RUNCAM_MAX_DEVICE_TYPES];
|
||||||
|
|
||||||
class Request;
|
class Request;
|
||||||
|
|
||||||
|
@ -435,4 +468,4 @@ namespace AP
|
||||||
AP_RunCam *runcam();
|
AP_RunCam *runcam();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAL_RUNCAM_ENABLED
|
#endif // AP_CAMERA_RUNCAM_ENABLED
|
||||||
|
|
Loading…
Reference in New Issue