-
-
Notifications
You must be signed in to change notification settings - Fork 511
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
Added camera plugin with basic functionality #338
Conversation
c14cc29
to
ce6cb7a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Does the plugin deal only with first camera ?
We need to implement MAVLink Camera protocol isn't it?
I mean that, we should first request for camera information and on response we receive available cameras, etc. I can probably contribute that part if you are ok with that.
We don't seem to handle heartbeat of camera component ? Did you disable autopilot heartbeats while testing ?
plugins/camera/camera_impl.cpp
Outdated
return camera_result_from_command_result( | ||
_parent.send_command_with_ack( | ||
MAV_CMD_IMAGE_START_CAPTURE, | ||
MavlinkCommands::Params {0.0f, // all camera IDs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between Camera ID and Camera Component ID ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Camera ID should actually be a thing of the past. I removed the comments.
plugins/camera/camera_impl.cpp
Outdated
1.0f, // take only one picture | ||
float(_capture_sequence++), | ||
NAN, NAN, NAN}, | ||
MAV_COMP_ID_CAMERA)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed, there'll be one instance per camera; so, camera component ID would be a member. Isn't it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. For now I'm just going to add the current single device plugin. Later we can extend it.
plugins/camera/camera.h
Outdated
class Device; | ||
|
||
/** | ||
* @brief The Camera class allows to control generic mavlink cameras. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps to
The Camera class can be used to manage cameras that implement the MAVLink Camera Protocol: https://mavlink.io/en/protocol/camera.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This plugin is different in that multiple instances can be used with one device. We should capture that here too.
plugins/camera/camera.h
Outdated
{ | ||
public: | ||
/** | ||
* @brief Constructor. Creates the plugin for a specific Device. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, if that rename for System
goes in then this will have to change.
This looks like it supports just a single camera per device (if not, then need to explain the "how"here). There is also no example. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good :) I just added few suggestions and questions.
auto prom = std::make_shared<std::promise<void>>(); | ||
auto ret = prom->get_future(); | ||
|
||
// Let's get the mode first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're setting mode, not get isn't it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this comment is here by mistake, possibly due to the copy paste error: https://github.com/dronecore/DroneCore/pull/338/files#diff-ac9feaa7a785b954819058e5ec940b4fR18
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed in 3bba620.
plugins/camera/camera.h
Outdated
* @param result The enum value for which a human readable string is required. | ||
* @return Human readable string for the Camera::Result. | ||
*/ | ||
static const char *result_str(Result result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should make
static std::string result_str(Result result);
in all the plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Will change it.
plugins/camera/camera.h
Outdated
/** | ||
* @brief Stop video capture (synchronous). | ||
* | ||
* This stops a video recording again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"again" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments for stopping image capture.
plugins/camera/camera_definition.h
Outdated
~CameraDefinition(); | ||
|
||
|
||
void load_file(const char *filename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be
void load_file(const std::string &filepath);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's nicer, I'll change it.
plugins/camera/camera_definition.h
Outdated
void load_string(const std::string &content); | ||
|
||
const char *get_vendor() const; | ||
const char *get_model() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const std::string &get_vendor() const;
const std::string &get_model() const;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done but not with a reference but a copy.
|
||
TEST(CameraDefinition, LoadE90InfoFile) | ||
{ | ||
CameraDefinition cd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice name cd
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😄
plugins/camera/camera_impl.cpp
Outdated
MAV_COMP_ID_CAMERA); | ||
|
||
_parent.send_command_with_ack_async( | ||
MAV_CMD_REQUEST_STORAGE_INFORMATION, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
http://mavlink.org/messages/common/#MAV_CMD_REQUEST_STORAGE_INFORMATION,
http://mavlink.org/messages/common/#STORAGE_INFORMATION
are WIP. So, we are just adding hooks in the plugin right now, isn't it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yer we should probably remove the WIP soon. It has been there for a long time.
mavlink_camera_information_t camera_information; | ||
mavlink_msg_camera_information_decode(&message, &camera_information); | ||
|
||
load_definition_file(camera_information.cam_definition_uri); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we store camera definition version ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet, good point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So as long as we don't cache the file there is no value in having the definition version.
std::this_thread::sleep_for(std::chrono::seconds(2)); | ||
|
||
set_mode(camera, Camera::Mode::VIDEO); | ||
std::this_thread::sleep_for(std::chrono::seconds(2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is just like pausing and not mandatory for set mode activity ? Because, I see you're already waiting in set_mode()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, double is probably not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I removed most of these.
|
||
LogDebug() << "Possible settings in photo mode: "; | ||
for (auto setting : settings) { | ||
LogDebug() << "- " << setting.second; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good if both name and value are printed. Isn't it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, I need to work on this, it's far from finished.
/** | ||
* @brief Information about a picture just captured. | ||
*/ | ||
struct CaptureInfo { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add a flag that tells whether its a standalone camera.
struct CaptureInfo {
bool is_standalone;
struct Position { ... };
struct Quaternion { ... };
...
};
So, if is_standalone
is true, then application need not look into position and quaternion details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say if it is standalone you actually need to look into it because you can't look at the autopilot's telemetry.
plugins/camera/camera.h
Outdated
bool get_possible_settings(std::map<std::string, std::string> &settings); | ||
bool get_possible_options(const std::string &setting_name, std::vector<std::string> &options); | ||
|
||
typedef std::function<void(Result, const std::string &)> get_option_callback_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a suggestion: How about grouping all typedefs together to ease reading ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to group together with methods that use the typedefs, so that you don't need to scroll around when looking at a method signature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
* @return Result of request. | ||
*/ | ||
Result stop_photo_interval(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about providing a static method that tells the number of cameras on the drone.
static size_t Camera::how_many_cameras() const;
OR
static size_t Camera::total_cameras() const;
whatever is more intuitive. We get to know this info in CAMERA_INFORMATION
. We get one response for each camera found on the drone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As said, I'll work on multi camera support when single camera support is merged and properly working. I can't do all at once 😄.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lazy! So hard to find good help now days :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hamishwillee in what context ? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a gazillion things I could do every day and I'm always trying to figure out what's most relevant 😕.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just teasing (I thought obviously?). You do plenty of good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understood that actually 😃 and it's probably how it always goes.
plugins/camera/camera.h
Outdated
bool get_possible_settings(std::map<std::string, std::string> &settings); | ||
bool get_possible_options(const std::string &setting_name, std::vector<std::string> &options); | ||
|
||
typedef std::function<void(Result, const std::string &)> get_option_callback_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
plugins/camera/camera_definition.cpp
Outdated
std::cout << content; | ||
} | ||
|
||
const char *CameraDefinition::get_model() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as here.
plugins/camera/camera_definition.cpp
Outdated
FirstChildElement("model")->GetText(); | ||
} | ||
|
||
const char *CameraDefinition::get_vendor() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as here.
plugins/camera/camera_definition.cpp
Outdated
{ | ||
} | ||
|
||
void CameraDefinition::load_file(const char *filename) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as here.
plugins/camera/camera_definition.cpp
Outdated
{ | ||
std::vector<std::string> exclusion_parameter_names {}; | ||
|
||
parameters.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
plugins/camera/camera_impl.cpp
Outdated
LogWarn() << "Error: no camera defnition available yet."; | ||
if (callback) { | ||
callback(Camera::Result::ERROR, ""); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure. Don't we need to return from here ? It seems falling through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good catch, thank you!
plugins/camera/camera_definition.h
Outdated
void update_setting(const std::string &name, const ParameterValue &value); | ||
|
||
typedef std::map<std::string, std::shared_ptr<Parameter>> parameter_map_t; | ||
bool get_parameters(parameter_map_t ¶meters, bool filter_possible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a selector, isn't it ? If so, it should be
bool get_parameters(parameter_map_t ¶meters, bool filter_possible) const;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to make a few of these methods const
but could not because when the map[key]
is used it can insert an entry in the map if not available and thus change the map. Presumably map[key]
is the wrong way and map.at(key)
should be used instead.
|
||
using namespace dronecore; | ||
|
||
static const char *e90_unit_test_file = "extensions/plugins/camera/e90_unit_test.xml"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::string
is better. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
plugins/camera/camera_impl.cpp
Outdated
} | ||
|
||
Camera::Result CameraImpl::start_video() | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to check whether video capture in progress ? Also, we need to make sure we're in Video mode. Same applies to async versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a TODO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
plugins/camera/camera_impl.cpp
Outdated
{ | ||
std::lock_guard<std::mutex> lock(_capture.mutex); | ||
|
||
return camera_result_from_command_result( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to make sure we're in Photo mode? Same applies to async versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yap, thx.
plugins/camera/camera_impl.cpp
Outdated
} | ||
|
||
Camera::Result CameraImpl::start_video() | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
plugins/camera/camera_impl.h
Outdated
void receive_int_param(const std::string &name, bool success, int value); | ||
void receive_float_param(const std::string &name, bool success, float value); | ||
|
||
CameraDefinition *_camera_definition = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be a unique pointer, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
cmake/compiler_flags.cmake
Outdated
if(APPLE) | ||
# We need a define if on APPLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here: if(APPLE) add_definitions("-DAPPLE")
tells me that "if APPLE
is defined, we add the definition called 'APPLE'". And I assume it is needed, otherwise we would not do it.
The comment represents 25% of this piece of code and just says exactly the same :P. Even worse: maybe at some point, the comment will get disconnected from the add_definitions
call, and it will be misguiding.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I wrote these comments because I'm a cmake noob so for me it wasn't trivial that the variable APPLE
would not result in a define APPLE
while compiling. Now I know 😄 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed it :)
cmake/compiler_flags.cmake
Outdated
@@ -40,3 +40,6 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") | |||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} --coverage") | |||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_COVERAGE} --coverage") | |||
set(CMAKE_LINKER_FLAGS_COVERAGE "${CMAKE_LINKER_FLAGS_COVERAGE} --coverage") | |||
|
|||
# Otherwise tinyxml2 complains. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I believe this one is useful, because that's a bit peculiar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, anyway I appreciate the discussion 👍
std::mutex mutex {}; | ||
Camera::mode_callback_t callback {nullptr}; | ||
void *timeout_cookie {nullptr}; | ||
} _get_mode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should store camera mode here. We can use this mode to validate whether we're in Photo or Video mode in APIs like start_video(), take_photo(), etc. Isn't it ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually store the camera mode in the camera_definition, so I'm not sure if we need it here as well.
@julianoes please rebase to develop. Thanks. |
plugins/camera/camera_impl.cpp
Outdated
MAV_CMD_VIDEO_START_CAPTURE, | ||
MAVLinkCommands::Params {0.0f, // Reserved, set to 0 | ||
NAN, // fps not set yet | ||
NAN, // resolution not set yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no resolution parameter in Video capture command.
2500 | MAV_CMD_VIDEO_START_CAPTURE | Starts video capture (recording). Use NAN for reserved values. |
---|---|---|
Mission Param #1 | Reserved (Set to 0) | |
Mission Param #2 | Frequency CAMERA_CAPTURE_STATUS messages should be sent while recording (0 for no messages, otherwise frequency in Hz) | |
Mission Param #3 | Reserved (all remaining params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh you're right, that changed.
This adds more camera features and some integration tests for it.
This is a mavlink spec leftover that has been removed.
The cURL headers leave a define for ERROR which causes compile errors on Windows.
With a recent E90 update, this is not needed anymore.
Ok, integration tests work against E90, E50, ET, and I've tried to address all comments so this should be ok to merge, finally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work @julianoes !
plugins/camera/camera.h
Outdated
* MAVLink Camera Protocol: https://mavlink.io/en/protocol/camera.html. | ||
* | ||
* Currently only a single camera is supported. | ||
* When multiple cameras are supported the plugin will need to instantiated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to be
plugins/camera/camera.h
Outdated
|
||
|
||
/** | ||
* @brief Get camera status. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get camera status (asynchronous).
(just for consistency with all other methdos)
plugins/camera/camera.h
Outdated
uint16_t rotation_deg = 0u; /**< @brief Video image rotation clockwise (0-359 degrees). */ | ||
std::string uri {}; /**< @brief Video stream URI. */ | ||
|
||
void set_highest() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation
plugins/camera/camera.h
Outdated
bit_rate_b_s = BIT_RATE_AUTO; | ||
} | ||
|
||
constexpr static const float FRAME_RATE_HIGHEST = -1.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation for these ones.
Looks good. I added some minor docs fixes. There is still a method and a few constants to document (marked up). |
MAVLink Video stream spec needs to be changed as raised here: mavlink/mavlink#883. So, we've a dependency on mavlink/mavlink#885. |
@hamishwillee thanks for making the doc fixes, appreciated! |
Added camera plugin with basic functionality
Depends on mavlink/mavlink#872.Todos:
camera definition and settings inspired by https://github.com/mavlink/qgroundcontrol/blob/master/src/Camera/QGCCameraControl.cc.
Fixes #154.