mirror of
https://github.com/ArduPilot/ardupilot.git
synced 2026-10-06 19:00:27 +08:00
Cache bounded stream lists and resume replies independently on each GCS link after transmit backpressure. Expire remote capture status after three seconds, retain locally scheduled interval capture, and back off unanswered status requests. Preserve native camera identity in cached replies and isolated-link broadcasts, and suppress synthetic FC-owned status for native cameras. Restore configured mount associations in cached information only when a same-system camera advertises none. Add CAMn_COMPID (0 or 7-255) so camera-v2 discovery can use a non-default component ID. The first slot owns a colliding ID; duplicate or invalid IDs warn and disable discovery. Resolve command selectors as component IDs or legacy slots 1-6 with the same rules for live commands and missions. NaN in formerly reserved selector fields means unset. Video commands with a nonzero camera selector treat param1 as a stream ID and pass the status frequency through; without one they keep the old camera-slot interpretation. Fill camera_device_id in camera information, settings, capture status, field of view and stream messages, and document the routing and selector design.
136 lines
4.8 KiB
C++
136 lines
4.8 KiB
C++
#include "AP_Camera_Servo.h"
|
|
|
|
#if AP_CAMERA_SERVO_ENABLED
|
|
|
|
#include <SRV_Channel/SRV_Channel.h>
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
// initialize the AP_Camera_Servo driver
|
|
void AP_Camera_Servo::init()
|
|
{
|
|
// call parent init to set default camera info (flags, focal length, etc.)
|
|
AP_Camera_Backend::init();
|
|
|
|
// set the zoom and focus to the trim point
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_zoom, 500);
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_focus, 500);
|
|
}
|
|
|
|
// update - should be called at 50hz
|
|
void AP_Camera_Servo::update()
|
|
{
|
|
// shutter counter
|
|
if (trigger_counter > 0) {
|
|
trigger_counter--;
|
|
} else {
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_trigger, _params.servo_off_pwm);
|
|
}
|
|
|
|
// iso counter
|
|
if (iso_counter > 0) {
|
|
iso_counter--;
|
|
} else {
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_iso, _params.servo_off_pwm);
|
|
}
|
|
float current_zoom = SRV_Channels::get_output_scaled(SRV_Channel::k_cam_zoom);
|
|
float new_zoom = constrain_float(current_zoom + zoom_current_rate, 0, 1000);
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_zoom, new_zoom);
|
|
|
|
float current_focus = SRV_Channels::get_output_scaled(SRV_Channel::k_cam_focus);
|
|
float new_focus = constrain_float(current_focus + focus_current_rate, 0, 1000);
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_focus, new_focus);
|
|
|
|
// call parent update
|
|
AP_Camera_Backend::update();
|
|
}
|
|
|
|
// entry point to actually take a picture. returns true on success
|
|
bool AP_Camera_Servo::trigger_pic()
|
|
{
|
|
// fail if have not completed previous picture
|
|
if (trigger_counter > 0) {
|
|
return false;
|
|
}
|
|
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_trigger, _params.servo_on_pwm);
|
|
|
|
// set counter to move servo to off position after this many iterations of update (assumes 50hz update rate)
|
|
trigger_counter = constrain_float(_params.trigger_duration * 50, 0, UINT16_MAX);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool AP_Camera_Servo::set_zoom(ZoomType zoom_type, float zoom_value)
|
|
{
|
|
switch (zoom_type) {
|
|
case ZoomType::RATE:
|
|
zoom_current_rate = zoom_value;
|
|
return true;
|
|
case ZoomType::PCT:
|
|
// expects to receive a value between 0 and 100
|
|
// This maps it to our 0-1000 range
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_zoom, constrain_float(zoom_value * 10, 0, 1000));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// set focus specified as rate
|
|
SetFocusResult AP_Camera_Servo::set_focus(FocusType focus_type, float focus_value)
|
|
{
|
|
switch (focus_type) {
|
|
case FocusType::RATE:
|
|
focus_current_rate = focus_value;
|
|
return SetFocusResult::ACCEPTED;
|
|
case FocusType::PCT:
|
|
// expects to receive a value between 0 and 100
|
|
// This maps it to our 0-1000 range
|
|
SRV_Channels::set_output_scaled(SRV_Channel::k_cam_focus, constrain_float(focus_value * 10, 0, 1000));
|
|
return SetFocusResult::ACCEPTED;
|
|
case FocusType::AUTO:
|
|
return SetFocusResult::UNSUPPORTED;
|
|
}
|
|
return SetFocusResult::UNSUPPORTED;
|
|
}
|
|
|
|
// configure camera
|
|
void AP_Camera_Servo::configure(float shooting_mode, float shutter_speed, float aperture, float ISO, int32_t exposure_type, int32_t cmd_id, float engine_cutoff_time)
|
|
{
|
|
// designed to control Blackmagic Micro Cinema Camera (BMMCC) cameras
|
|
// if the message contains non zero values then use them for the below functions
|
|
if (ISO > 0) {
|
|
// set a trigger for the iso function that is flip controlled
|
|
iso_counter = constrain_float(_params.trigger_duration * 50, 0, UINT16_MAX);
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_iso, _params.servo_on_pwm);
|
|
}
|
|
|
|
if (aperture > 0) {
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_aperture, (uint16_t)aperture);
|
|
}
|
|
|
|
if (shutter_speed > 0) {
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_shutter_speed, (uint16_t)shutter_speed);
|
|
}
|
|
|
|
// Use the shooting mode PWM value for the BMMCC as the focus control - no need to modify or create a new MAVlink message type.
|
|
if (shooting_mode > 0) {
|
|
SRV_Channels::set_output_pwm(SRV_Channel::k_cam_focus, (uint16_t)shooting_mode);
|
|
}
|
|
}
|
|
|
|
// send camera settings message to GCS
|
|
void AP_Camera_Servo::send_camera_settings(mavlink_channel_t chan) const
|
|
{
|
|
mavlink_msg_camera_settings_send(
|
|
chan,
|
|
AP_HAL::millis(), // time_boot_ms
|
|
CAMERA_MODE_IMAGE, // camera mode (0:image, 1:video, 2:image survey)
|
|
SRV_Channels::get_output_scaled(SRV_Channel::k_cam_zoom) / 10.0f, // zoomLevel float, percentage from 0 to 100, 0 if unassigned
|
|
SRV_Channels::get_output_scaled(SRV_Channel::k_cam_focus) / 10.0f, // focusLevel float, percentage from 0 to 100, 0 if unassigned
|
|
_instance + 1); // camera_device_id
|
|
}
|
|
|
|
#endif // AP_CAMERA_SERVO_ENABLED
|