Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More camera server functionality #2088

Merged
merged 25 commits into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2413639
camera server : add start stop video subscribe, add start stop video …
tbago Jun 16, 2023
5014dfc
camera server : add start stop video streaming, add stream id in came…
tbago Jun 17, 2023
ce1bcf7
camera server: add subscribe camera mode and sample code
tbago Jun 17, 2023
cabd727
camera server: add storage information and capture stauts subscribe
tbago Jun 17, 2023
0a2bfd4
add unit on image interval and available capacity
tbago Jun 18, 2023
3086da3
storage information : add unit on read speed and write speed
tbago Jun 23, 2023
ccd3520
camera : add format storage and reset settings function
tbago Jun 24, 2023
2d15978
camera server: add feedback for all camera server command
tbago Jun 24, 2023
207bffc
proto: small updates
julianoes Nov 1, 2023
a11edb4
camera_server: add video stream info
julianoes Nov 2, 2023
d263021
core: don't complain about ping
julianoes Nov 2, 2023
5eceed7
camera_server: remove confusing duplicate logic
julianoes Nov 2, 2023
eebc377
camera_server: remove sleeps (and some docstrings)
julianoes Nov 2, 2023
e3f23f0
camera_server: set capture video flag
julianoes Nov 2, 2023
14c60fc
camera_server: fix capture status
julianoes Nov 2, 2023
c465bc6
camera_server: don't forget to send mode flag
julianoes Nov 2, 2023
c3067b7
core: allow change param unsubscriptions
julianoes Nov 3, 2023
01ce134
param_server: add param changed subscriptions
julianoes Nov 3, 2023
2b7be2a
examples: add missing include
julianoes Dec 23, 2023
1103cb8
camera: fix a few casts
julianoes Dec 23, 2023
9e70232
camera: remove non-sensical tests
julianoes Dec 23, 2023
e07d875
integration_tests: fix after rebase
julianoes Dec 24, 2023
7399fc7
third_party: update mavlink to latest master
julianoes Dec 24, 2023
c8d3afb
camera: fix cast
julianoes Dec 24, 2023
38424a4
proto: update to main
julianoes Dec 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions examples/camera_server/camera_client.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include <chrono>
#include <future>
#include <iostream>
#include <thread>

#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/camera/camera.h>

static void do_camera_operation(mavsdk::Camera& camera);

int main(int argc, const char* argv[])
{
// we run client plugins to act as the GCS
Expand Down Expand Up @@ -47,8 +50,50 @@ int main(int argc, const char* argv[])
std::cout << info << std::endl;
});

auto take_photo_result = camera.take_photo();
std::cout << "Take phto return : " << take_photo_result << std::endl;
camera.subscribe_status([](mavsdk::Camera::Status status) {
std::cout << "Camera status:" << std::endl;
std::cout << status << std::endl;
});

do_camera_operation(camera);

// for test subscribe camera status, so don't end the process
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}

void do_camera_operation(mavsdk::Camera& camera)
{
// switch to photo mode to take photo
auto operation_result = camera.set_mode(mavsdk::Camera::Mode::Photo);
std::cout << "Set camera to photo mode result : " << operation_result << std::endl;

operation_result = camera.take_photo();
std::cout << "Take photo result : " << operation_result << std::endl;

// switch to video mode to recording video
operation_result = camera.set_mode(mavsdk::Camera::Mode::Video);
std::cout << "Set camera to video mode result : " << operation_result << std::endl;

operation_result = camera.start_video();
std::cout << "Start video result : " << operation_result << std::endl;

operation_result = camera.stop_video();
std::cout << "Stop video result : " << operation_result << std::endl;

// the camera can have multi video stream so may need the stream id
operation_result = camera.start_video_streaming(2);
std::cout << "start video streaming result : " << operation_result << std::endl;

operation_result = camera.stop_video_streaming(2);
std::cout << "stop video streaming result : " << operation_result << std::endl;

// format the storage with special storage id test
operation_result = camera.format_storage(11);
std::cout << "format storage result : " << operation_result << std::endl;

operation_result = camera.reset_settings();
std::cout << "Reset camera settings result : " << operation_result << std::endl;
}
149 changes: 120 additions & 29 deletions examples/camera_server/camera_server.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#include <iostream>
#include <thread>
#include <chrono>
#include <future>
#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/camera_server/camera_server.h>

static void subscribe_camera_operation(mavsdk::CameraServer& camera_server);

int main(int argc, char** argv)
{
mavsdk::Mavsdk mavsdk{mavsdk::Mavsdk::Configuration{mavsdk::Mavsdk::ComponentType::Camera}};
Expand All @@ -18,10 +22,54 @@ int main(int argc, char** argv)
auto camera_server = mavsdk::CameraServer{mavsdk.server_component()};

// First add all subscriptions. This defines the camera capabilities.
subscribe_camera_operation(camera_server);

// TODO: this state is not guaranteed, e.g. a new system appears
// while a capture is in progress
camera_server.set_in_progress(false);

// Finally call set_information() to "activate" the camera plugin.

auto ret = camera_server.set_information({
.vendor_name = "MAVSDK",
.model_name = "Example Camera Server",
.firmware_version = "1.0.0",
.focal_length_mm = 3.0,
.horizontal_sensor_size_mm = 3.68,
.vertical_sensor_size_mm = 2.76,
.horizontal_resolution_px = 3280,
.vertical_resolution_px = 2464,
.lens_id = 0,
.definition_file_version = 0, // TODO: add this
.definition_file_uri = "", // TODO: implement this using MAVLink FTP
});

if (ret != mavsdk::CameraServer::Result::Success) {
std::cerr << "Failed to set camera info, exiting" << std::endl;
return 2;
}

// works as a server and never quit
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}

return 0;
}

// sample for camera current status
std::chrono::steady_clock::time_point start_video_time;
bool is_recording_video = false;
bool is_capture_in_progress = false;
int32_t image_count = 0;

static void subscribe_camera_operation(mavsdk::CameraServer& camera_server)
{
camera_server.subscribe_take_photo([&camera_server](int32_t index) {
camera_server.set_in_progress(true);

is_capture_in_progress = true;

std::cout << "taking a picture (" << +index << ")..." << std::endl;

// TODO : actually capture image here
Expand All @@ -36,11 +84,11 @@ int main(int argc, char** argv)
std::chrono::system_clock::now().time_since_epoch())
.count();
auto success = true;

image_count++;
camera_server.set_in_progress(false);

camera_server.respond_take_photo(
mavsdk::CameraServer::TakePhotoFeedback::Ok,
mavsdk::CameraServer::CameraFeedback::Ok,
mavsdk::CameraServer::CaptureInfo{
.position = position,
.attitude_quaternion = attitude,
Expand All @@ -49,39 +97,82 @@ int main(int argc, char** argv)
.index = index,
.file_url = {},
});

is_capture_in_progress = false;
});

// Then set the initial state of everything.
camera_server.subscribe_start_video([&camera_server](int32_t stream_id) {
std::cout << "Start video record" << std::endl;
is_recording_video = true;
start_video_time = std::chrono::steady_clock::now();
camera_server.respond_start_video(mavsdk::CameraServer::CameraFeedback::Ok);
});

// TODO: this state is not guaranteed, e.g. a new system appears
// while a capture is in progress
camera_server.set_in_progress(false);
camera_server.subscribe_stop_video([&camera_server](int32_t stream_id) {
std::cout << "Stop video record" << std::endl;
is_recording_video = false;
camera_server.respond_stop_video(mavsdk::CameraServer::CameraFeedback::Ok);
});

// Finally call set_information() to "activate" the camera plugin.
camera_server.subscribe_start_video_streaming([&camera_server](int32_t stream_id) {
std::cout << "Start video streaming " << stream_id << std::endl;
camera_server.respond_start_video_streaming(mavsdk::CameraServer::CameraFeedback::Ok);
});

auto ret = camera_server.set_information({
.vendor_name = "MAVSDK",
.model_name = "Example Camera Server",
.firmware_version = "1.0.0",
.focal_length_mm = 3.0,
.horizontal_sensor_size_mm = 3.68,
.vertical_sensor_size_mm = 2.76,
.horizontal_resolution_px = 3280,
.vertical_resolution_px = 2464,
.lens_id = 0,
.definition_file_version = 0, // TODO: add this
.definition_file_uri = "", // TODO: implement this using MAVLink FTP
camera_server.subscribe_stop_video_streaming([&camera_server](int32_t stream_id) {
std::cout << "Stop video streaming " << stream_id << std::endl;
camera_server.respond_stop_video_streaming(mavsdk::CameraServer::CameraFeedback::Ok);
});

if (ret != mavsdk::CameraServer::Result::Success) {
std::cerr << "Failed to set camera info, exiting" << std::endl;
return 2;
}
camera_server.subscribe_set_mode([&camera_server](mavsdk::CameraServer::Mode mode) {
std::cout << "Set camera mode " << mode << std::endl;
camera_server.respond_set_mode(mavsdk::CameraServer::CameraFeedback::Ok);
});

// works as a server and never quit
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
camera_server.subscribe_storage_information([&camera_server](int32_t storage_id) {
mavsdk::CameraServer::StorageInformation storage_information;
constexpr int kTotalStorage = 4 * 1024 * 1024;
storage_information.total_storage_mib = kTotalStorage;
storage_information.used_storage_mib = 100;
storage_information.available_storage_mib =
kTotalStorage - storage_information.used_storage_mib;
storage_information.storage_status =
mavsdk::CameraServer::StorageInformation::StorageStatus::Formatted;
storage_information.storage_type =
mavsdk::CameraServer::StorageInformation::StorageType::Microsd;

camera_server.respond_storage_information(
mavsdk::CameraServer::CameraFeedback::Ok, storage_information);
});

return 0;
}
camera_server.subscribe_capture_status([&camera_server](int32_t reserved) {
mavsdk::CameraServer::CaptureStatus capture_status;
capture_status.image_count = image_count;
capture_status.image_status =
is_capture_in_progress ?
mavsdk::CameraServer::CaptureStatus::ImageStatus::CaptureInProgress :
mavsdk::CameraServer::CaptureStatus::ImageStatus::Idle;
capture_status.video_status =
is_recording_video ?
mavsdk::CameraServer::CaptureStatus::VideoStatus::CaptureInProgress :
mavsdk::CameraServer::CaptureStatus::VideoStatus::Idle;
auto current_time = std::chrono::steady_clock::now();
if (is_recording_video) {
capture_status.recording_time_s =
std::chrono::duration_cast<std::chrono::seconds>(current_time - start_video_time)
.count();
}
camera_server.respond_capture_status(
mavsdk::CameraServer::CameraFeedback::Ok, capture_status);
});

camera_server.subscribe_format_storage([&camera_server](int storage_id) {
std::cout << "format storage with id : " << storage_id << std::endl;
camera_server.respond_format_storage(mavsdk::CameraServer::CameraFeedback::Ok);
});

camera_server.subscribe_reset_settings([&camera_server](int camera_id) {
std::cout << "reset camera settings" << std::endl;
camera_server.respond_reset_settings(mavsdk::CameraServer::CameraFeedback::Ok);
});
}
1 change: 1 addition & 0 deletions src/integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ add_executable(integration_tests_runner
camera_take_photo.cpp
camera_take_photo_interval.cpp
camera_format.cpp
camera_reset_settings.cpp
camera_test_helpers.cpp
connection.cpp
follow_me.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/integration_tests/camera_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ TEST(CameraTest, Format)

auto camera = std::make_shared<Camera>(system);

EXPECT_EQ(Camera::Result::Success, camera->format_storage());
EXPECT_EQ(Camera::Result::Success, camera->format_storage(1));
}
26 changes: 26 additions & 0 deletions src/integration_tests/camera_reset_settings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "integration_test_helper.h"
#include "mavsdk.h"
#include <iostream>
#include <functional>
#include <atomic>
#include "plugins/camera/camera.h"

using namespace mavsdk;

TEST(CameraTest, ResetSettings)
{
Mavsdk mavsdk{Mavsdk::Configuration{Mavsdk::ComponentType::GroundStation}};

ConnectionResult ret = mavsdk.add_udp_connection();
ASSERT_EQ(ret, ConnectionResult::Success);

// Wait for system to connect via heartbeat.
std::this_thread::sleep_for(std::chrono::seconds(2));

auto system = mavsdk.systems().at(0);
ASSERT_TRUE(system->has_camera());

auto camera = std::make_shared<Camera>(system);

EXPECT_EQ(Camera::Result::Success, camera->reset_settings());
}
2 changes: 1 addition & 1 deletion src/integration_tests/camera_take_photo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ TEST(CameraTest, TakePhotoSingle)
info.index = index;
info.is_success = true;

camera_server.respond_take_photo(CameraServer::TakePhotoFeedback::Ok, info);
camera_server.respond_take_photo(CameraServer::CameraFeedback::Ok, info);
});

// Wait for system to connect via heartbeat.
Expand Down
15 changes: 10 additions & 5 deletions src/mavsdk/core/mavlink_mission_transfer_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ void MavlinkMissionTransferClient::UploadWorkItem::send_count()
_target_system_id,
MAV_COMP_ID_AUTOPILOT1,
_items.size(),
_type);
_type,
0);
return message;
})) {
_timeout_handler.remove(_cookie);
Expand Down Expand Up @@ -303,7 +304,8 @@ void MavlinkMissionTransferClient::UploadWorkItem::send_cancel_and_finish()
_target_system_id,
MAV_COMP_ID_AUTOPILOT1,
MAV_MISSION_OPERATION_CANCELLED,
_type);
_type,
0);
return message;
})) {
callback_and_reset(Result::ConnectionError);
Expand Down Expand Up @@ -350,7 +352,8 @@ void MavlinkMissionTransferClient::UploadWorkItem::process_mission_request(
request_message.sysid,
request_message.compid,
MAV_MISSION_UNSUPPORTED,
_type);
_type,
0);
return message;
})) {
_timeout_handler.remove(_cookie);
Expand Down Expand Up @@ -670,7 +673,8 @@ void MavlinkMissionTransferClient::DownloadWorkItem::send_ack_and_finish()
_target_system_id,
MAV_COMP_ID_AUTOPILOT1,
MAV_MISSION_ACCEPTED,
_type);
_type,
0);
return message;
})) {
callback_and_reset(Result::ConnectionError);
Expand All @@ -693,7 +697,8 @@ void MavlinkMissionTransferClient::DownloadWorkItem::send_cancel_and_finish()
_target_system_id,
MAV_COMP_ID_AUTOPILOT1,
MAV_MISSION_OPERATION_CANCELLED,
_type);
_type,
0);
return message;
})) {
callback_and_reset(Result::ConnectionError);
Expand Down
8 changes: 5 additions & 3 deletions src/mavsdk/core/mavlink_mission_transfer_client_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ mavlink_message_t make_mission_count(unsigned count)
target_address.system_id,
target_address.component_id,
count,
MAV_MISSION_TYPE_MISSION);
MAV_MISSION_TYPE_MISSION,
0);
return message;
}

Expand Down Expand Up @@ -419,7 +420,8 @@ mavlink_message_t make_mission_ack(uint8_t type, uint8_t result)
target_address.system_id,
target_address.component_id,
result,
type);
type,
0);
return message;
}

Expand Down Expand Up @@ -1695,7 +1697,7 @@ mavlink_message_t make_mission_current(uint16_t seq)
{
mavlink_message_t message;
mavlink_msg_mission_current_pack(
own_address.system_id, own_address.component_id, &message, seq, 0, 0, 0);
own_address.system_id, own_address.component_id, &message, seq, 0, 0, 0, 0, 0, 0);
return message;
}

Expand Down
Loading