AP_Camera: add semaphore to allow multi-threaded access

This commit is contained in:
Randy Mackay 2023-04-12 09:11:26 +09:00 committed by Peter Barker
parent ffc3ad1c1a
commit de4b1890f5
6 changed files with 57 additions and 9 deletions

View File

@ -61,6 +61,8 @@ AP_Camera::AP_Camera(uint32_t _log_camera_bit) :
// set camera trigger distance in a mission // set camera trigger distance in a mission
void AP_Camera::set_trigger_distance(float distance_m) void AP_Camera::set_trigger_distance(float distance_m)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return; return;
} }
@ -70,6 +72,8 @@ void AP_Camera::set_trigger_distance(float distance_m)
// momentary switch to change camera between picture and video modes // momentary switch to change camera between picture and video modes
void AP_Camera::cam_mode_toggle() void AP_Camera::cam_mode_toggle()
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return; return;
} }
@ -79,6 +83,8 @@ void AP_Camera::cam_mode_toggle()
// take a picture // take a picture
void AP_Camera::take_picture() void AP_Camera::take_picture()
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return; return;
} }
@ -89,6 +95,8 @@ void AP_Camera::take_picture()
// start_recording should be true to start recording, false to stop recording // start_recording should be true to start recording, false to stop recording
bool AP_Camera::record_video(bool start_recording) bool AP_Camera::record_video(bool start_recording)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return false; return false;
} }
@ -99,6 +107,8 @@ bool AP_Camera::record_video(bool start_recording)
// zoom out = -1, hold = 0, zoom in = 1 // zoom out = -1, hold = 0, zoom in = 1
bool AP_Camera::set_zoom_step(int8_t zoom_step) bool AP_Camera::set_zoom_step(int8_t zoom_step)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return false; return false;
} }
@ -109,6 +119,8 @@ bool AP_Camera::set_zoom_step(int8_t zoom_step)
// focus in = -1, focus hold = 0, focus out = 1 // focus in = -1, focus hold = 0, focus out = 1
bool AP_Camera::set_manual_focus_step(int8_t focus_step) bool AP_Camera::set_manual_focus_step(int8_t focus_step)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return false; return false;
} }
@ -118,6 +130,8 @@ bool AP_Camera::set_manual_focus_step(int8_t focus_step)
// auto focus // auto focus
bool AP_Camera::set_auto_focus() bool AP_Camera::set_auto_focus()
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return false; return false;
} }
@ -199,6 +213,8 @@ void AP_Camera::init()
// handle incoming mavlink messages // handle incoming mavlink messages
void AP_Camera::handle_message(mavlink_channel_t chan, const mavlink_message_t &msg) void AP_Camera::handle_message(mavlink_channel_t chan, const mavlink_message_t &msg)
{ {
WITH_SEMAPHORE(_rsem);
if (msg.msgid == MAVLINK_MSG_ID_DIGICAM_CONTROL) { if (msg.msgid == MAVLINK_MSG_ID_DIGICAM_CONTROL) {
// decode deprecated MavLink message that controls camera. // decode deprecated MavLink message that controls camera.
__mavlink_digicam_control_t packet; __mavlink_digicam_control_t packet;
@ -287,6 +303,8 @@ MAV_RESULT AP_Camera::handle_command_long(const mavlink_command_long_t &packet)
// set camera trigger distance in a mission // set camera trigger distance in a mission
void AP_Camera::set_trigger_distance(uint8_t instance, float distance_m) void AP_Camera::set_trigger_distance(uint8_t instance, float distance_m)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return; return;
@ -299,6 +317,8 @@ void AP_Camera::set_trigger_distance(uint8_t instance, float distance_m)
// momentary switch to change camera between picture and video modes // momentary switch to change camera between picture and video modes
void AP_Camera::cam_mode_toggle(uint8_t instance) void AP_Camera::cam_mode_toggle(uint8_t instance)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return; return;
@ -311,6 +331,8 @@ void AP_Camera::cam_mode_toggle(uint8_t instance)
// configure camera // configure camera
void AP_Camera::configure(float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time) void AP_Camera::configure(float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return; return;
} }
@ -319,6 +341,8 @@ void AP_Camera::configure(float shooting_mode, float shutter_speed, float apertu
void AP_Camera::configure(uint8_t instance, float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time) void AP_Camera::configure(uint8_t instance, float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return; return;
@ -331,6 +355,8 @@ void AP_Camera::configure(uint8_t instance, float shooting_mode, float shutter_s
// handle camera control // handle camera control
void AP_Camera::control(float session, float zoom_pos, float zoom_step, float focus_lock, float shooting_cmd, float cmd_id) void AP_Camera::control(float session, float zoom_pos, float zoom_step, float focus_lock, float shooting_cmd, float cmd_id)
{ {
WITH_SEMAPHORE(_rsem);
if (primary == nullptr) { if (primary == nullptr) {
return; return;
} }
@ -339,6 +365,8 @@ void AP_Camera::control(float session, float zoom_pos, float zoom_step, float fo
void AP_Camera::control(uint8_t instance, float session, float zoom_pos, float zoom_step, float focus_lock, float shooting_cmd, float cmd_id) void AP_Camera::control(uint8_t instance, float session, float zoom_pos, float zoom_step, float focus_lock, float shooting_cmd, float cmd_id)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return; return;
@ -351,8 +379,10 @@ void AP_Camera::control(uint8_t instance, float session, float zoom_pos, float z
/* /*
Send camera feedback to the GCS Send camera feedback to the GCS
*/ */
void AP_Camera::send_feedback(mavlink_channel_t chan) const void AP_Camera::send_feedback(mavlink_channel_t chan)
{ {
WITH_SEMAPHORE(_rsem);
// call each instance // call each instance
for (uint8_t instance = 0; instance < AP_CAMERA_MAX_INSTANCES; instance++) { for (uint8_t instance = 0; instance < AP_CAMERA_MAX_INSTANCES; instance++) {
if (_backends[instance] != nullptr) { if (_backends[instance] != nullptr) {
@ -366,6 +396,8 @@ void AP_Camera::send_feedback(mavlink_channel_t chan) const
*/ */
void AP_Camera::update() void AP_Camera::update()
{ {
WITH_SEMAPHORE(_rsem);
// call each instance // call each instance
for (uint8_t instance = 0; instance < AP_CAMERA_MAX_INSTANCES; instance++) { for (uint8_t instance = 0; instance < AP_CAMERA_MAX_INSTANCES; instance++) {
if (_backends[instance] != nullptr) { if (_backends[instance] != nullptr) {
@ -377,6 +409,8 @@ void AP_Camera::update()
// take_picture - take a picture // take_picture - take a picture
void AP_Camera::take_picture(uint8_t instance) void AP_Camera::take_picture(uint8_t instance)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return; return;
@ -390,6 +424,8 @@ void AP_Camera::take_picture(uint8_t instance)
// start_recording should be true to start recording, false to stop recording // start_recording should be true to start recording, false to stop recording
bool AP_Camera::record_video(uint8_t instance, bool start_recording) bool AP_Camera::record_video(uint8_t instance, bool start_recording)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return false; return false;
@ -403,6 +439,8 @@ bool AP_Camera::record_video(uint8_t instance, bool start_recording)
// zoom out = -1, hold = 0, zoom in = 1 // zoom out = -1, hold = 0, zoom in = 1
bool AP_Camera::set_zoom_step(uint8_t instance, int8_t zoom_step) bool AP_Camera::set_zoom_step(uint8_t instance, int8_t zoom_step)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return false; return false;
@ -416,6 +454,8 @@ bool AP_Camera::set_zoom_step(uint8_t instance, int8_t zoom_step)
// focus in = -1, focus hold = 0, focus out = 1 // focus in = -1, focus hold = 0, focus out = 1
bool AP_Camera::set_manual_focus_step(uint8_t instance, int8_t focus_step) bool AP_Camera::set_manual_focus_step(uint8_t instance, int8_t focus_step)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return false; return false;
@ -428,6 +468,8 @@ bool AP_Camera::set_manual_focus_step(uint8_t instance, int8_t focus_step)
// auto focus. returns true on success // auto focus. returns true on success
bool AP_Camera::set_auto_focus(uint8_t instance) bool AP_Camera::set_auto_focus(uint8_t instance)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return false; return false;
@ -440,8 +482,10 @@ bool AP_Camera::set_auto_focus(uint8_t instance)
#if AP_CAMERA_SCRIPTING_ENABLED #if AP_CAMERA_SCRIPTING_ENABLED
// accessor to allow scripting backend to retrieve state // accessor to allow scripting backend to retrieve state
// returns true on success and cam_state is filled in // returns true on success and cam_state is filled in
bool AP_Camera::get_state(uint8_t instance, camera_state_t& cam_state) const bool AP_Camera::get_state(uint8_t instance, camera_state_t& cam_state)
{ {
WITH_SEMAPHORE(_rsem);
auto *backend = get_instance(instance); auto *backend = get_instance(instance);
if (backend == nullptr) { if (backend == nullptr) {
return false; return false;

View File

@ -96,7 +96,7 @@ public:
// MAVLink methods // MAVLink methods
void handle_message(mavlink_channel_t chan, const mavlink_message_t &msg); void handle_message(mavlink_channel_t chan, const mavlink_message_t &msg);
MAV_RESULT handle_command_long(const mavlink_command_long_t &packet); MAV_RESULT handle_command_long(const mavlink_command_long_t &packet);
void send_feedback(mavlink_channel_t chan) const; void send_feedback(mavlink_channel_t chan);
// configure camera // configure camera
void configure(float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time); void configure(float shooting_mode, float shutter_speed, float aperture, float ISO, float exposure_type, float cmd_id, float engine_cutoff_time);
@ -143,9 +143,12 @@ public:
#if AP_CAMERA_SCRIPTING_ENABLED #if AP_CAMERA_SCRIPTING_ENABLED
// accessor to allow scripting backend to retrieve state // accessor to allow scripting backend to retrieve state
// returns true on success and cam_state is filled in // returns true on success and cam_state is filled in
bool get_state(uint8_t instance, camera_state_t& cam_state) const; bool get_state(uint8_t instance, camera_state_t& cam_state);
#endif #endif
// allow threads to lock against AHRS update
HAL_Semaphore &get_semaphore() { return _rsem; }
// parameter var table // parameter var table
static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info[];
@ -177,6 +180,7 @@ private:
// perform any required parameter conversion // perform any required parameter conversion
void convert_params(); void convert_params();
HAL_Semaphore _rsem; // semaphore for multi-thread access
AP_Camera_Backend *primary; // primary camera backed AP_Camera_Backend *primary; // primary camera backed
bool _is_in_auto_mode; // true if in AUTO mode bool _is_in_auto_mode; // true if in AUTO mode
uint32_t log_camera_bit; // logging bit (from LOG_BITMASK) to enable camera logging uint32_t log_camera_bit; // logging bit (from LOG_BITMASK) to enable camera logging

View File

@ -107,7 +107,7 @@ void AP_Camera_Backend::control(float session, float zoom_pos, float zoom_step,
} }
// send camera feedback message to GCS // send camera feedback message to GCS
void AP_Camera_Backend::send_camera_feedback(mavlink_channel_t chan) const void AP_Camera_Backend::send_camera_feedback(mavlink_channel_t chan)
{ {
int32_t altitude = 0; int32_t altitude = 0;
if (camera_feedback.location.initialised() && !camera_feedback.location.get_alt_cm(Location::AltFrame::ABSOLUTE, altitude)) { if (camera_feedback.location.initialised() && !camera_feedback.location.get_alt_cm(Location::AltFrame::ABSOLUTE, altitude)) {

View File

@ -80,12 +80,12 @@ public:
void set_trigger_distance(float distance_m) { _params.trigg_dist.set(distance_m); } void set_trigger_distance(float distance_m) { _params.trigg_dist.set(distance_m); }
// send camera feedback message to GCS // send camera feedback message to GCS
void send_camera_feedback(mavlink_channel_t chan) const; void send_camera_feedback(mavlink_channel_t chan);
#if AP_CAMERA_SCRIPTING_ENABLED #if AP_CAMERA_SCRIPTING_ENABLED
// accessor to allow scripting backend to retrieve state // accessor to allow scripting backend to retrieve state
// returns true on success and cam_state is filled in // returns true on success and cam_state is filled in
virtual bool get_state(camera_state_t& cam_state) const { return false; } virtual bool get_state(camera_state_t& cam_state) { return false; }
#endif #endif
protected: protected:

View File

@ -47,7 +47,7 @@ bool AP_Camera_Scripting::set_auto_focus()
// access for scripting backend to retrieve state // access for scripting backend to retrieve state
// returns true on success and cam_state is filled in // returns true on success and cam_state is filled in
bool AP_Camera_Scripting::get_state(camera_state_t& cam_state) const bool AP_Camera_Scripting::get_state(camera_state_t& cam_state)
{ {
cam_state = _cam_state; cam_state = _cam_state;
return true; return true;

View File

@ -51,7 +51,7 @@ public:
bool set_auto_focus() override; bool set_auto_focus() override;
// returns true on success and cam_state is filled in // returns true on success and cam_state is filled in
bool get_state(camera_state_t& cam_state) const override; bool get_state(camera_state_t& cam_state) override;
private: private: