Giter Club home page Giter Club logo

mavsdk-proto's Introduction

Build Status

MAVLink

MAVLink -- Micro Air Vehicle Message Marshalling Library.

MAVLink is a very lightweight, header-only message library for communication between drones and/or ground control stations. It consists primarily of message-set specifications for different systems ("dialects") defined in XML files, and Python tools that convert these into appropriate source code for supported languages. There are additional Python scripts providing examples and utilities for working with MAVLink data.

Tip MAVLink is very well suited for applications with very limited communication bandwidth. Its reference implementation in C is highly optimized for resource-constrained systems with limited RAM and flash memory. It is field-proven and deployed in many products where it serves as interoperability interface between components of different manufacturers.

Quick start

Generate C headers

To install the minimal MAVLink environment on Ubuntu LTS 20.04 or 22.04, enter the following on a terminal:

# Dependencies
sudo apt install python3-pip

# Clone mavlink into the directory of your choice
git clone https://github.com/mavlink/mavlink.git --recursive
cd mavlink

python3 -m pip install -r pymavlink/requirements.txt

You can then build the MAVLink2 C-library for message_definitions/v1.0/common.xml from the /mavlink directory as shown:

python3 -m pymavlink.tools.mavgen --lang=C --wire-protocol=2.0 --output=generated/include/mavlink/v2.0 message_definitions/v1.0/common.xml

Use from cmake

To include the headers in cmake, install them locally, e.g. into the directory install:

cmake -Bbuild -H. -DCMAKE_INSTALL_PREFIX=install -DMAVLINK_DIALECT=common -DMAVLINK_VERSION=2.0
cmake --build build --target install

Then use find_package to get the dependency in CMakeLists.txt:

find_package(MAVLink REQUIRED)

add_executable(my_program my_program.c)

target_link_libraries(my_program PRIVATE MAVLink::mavlink)

And pass the local install directory to cmake (adapt to your directory structure):

cd ../my_program
cmake -Bbuild -H. -DCMAKE_PREFIX_PATH=../mavlink/install

For a full example, check examples/c.

Note: even though we use target_link_libraries in cmake, it doesn't actually "link" to MAVLink as it's just a header-only library.

Other instructions

Instructions for using the C libraries are then covered in Using C MAVLink Libraries (mavgen).

Note: Installing the MAVLink Toolchain explains how to install MAVLink on other Ubuntu platforms and Windows, while Generating MAVLink Libraries explains how to build MAVLink for the other programming languages supported by the project. The sub-topics of Using MAVLink Libraries explain how to use the generated libraries.

Key Links

mavsdk-proto's People

Contributors

avinash-palleti avatar bkueng avatar bozkurthan avatar chepdelair avatar coderkalyan avatar coolkesword avatar dayjaby avatar ddatsko avatar dlech avatar dopplegangster avatar douglaswsilva avatar helo9 avatar hrnbot avatar irsdkv avatar iwishiwasaneagle avatar jonasvautherin avatar julianoes avatar junwoo091400 avatar katawann avatar ken-voly avatar markusachtelik avatar mattes-bru avatar persuader72 avatar potaito avatar rligocki avatar romain-chiap avatar tbago avatar tsc21 avatar xvzf avatar yalamareddychaitanya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mavsdk-proto's Issues

"mavsdk_options.proto: File not found" error with default example

Running the example in http://github.com/mavlink/MAVSDK-Proto/blob/790d2c1/pb_plugins/README.rst :

export TEMPLATE_PATH="$(pwd)/templates/swift"
protoc --plugin=protoc-gen-custom=$(which protoc-gen-mavsdk) \
        -I../protos/action \
        --custom_out=. \
        --custom_opt=swift \
        ../protos/action/action.proto

results in an error:

mavsdk_options.proto: File not found.
action.proto: Import "mavsdk_options.proto" was not found or had errors.

The reason for this is the -I flag only included the protos/action directory, but the mavsdk_options.proto file is in the protos directory. A possible fix would be changing the include flag -I../protos/action to -I../protos

Add callbacks that provide a result (for server commands)

While defining the proto API for MAVSDK autopilot server plugins I ran into an issue where I needed to provide logic to allow or disallow a certain action in a timely manner. for example with an arming request MAV_CMD_COMPONENT_ARM_DISARM

As this request is a mavlink command, it requires an ack to be successful, failed or unsupported almost immediately. The only way for me to fulfil this at current was to store the state of is_armable in the plugin and provide proto to change that state. This state is checked when a command is observed and the ack is sent immediately. It works, but not an ideal solution.

https://github.com/mavlink/MAVSDK/blob/main/src/plugins/action_server/action_server_impl.cpp#L57

I would like to be able to do something like the following:

action_server.subscribe_arm_request([](action_server::ArmRequest arm_request)
{
  return some_check_to_see_if_can_arm(arm_request); // True if allow // False if not
});

In the plugin, this callback result could then be used to ack the command correctly.

The return value should probably map to command ack states really - instead of just a boolean.

Create proto file for logging plugin

Hi all
I want to implement LOGGING_DATA plugin in proto.
I think that related requests should be located in own proto module logging (one of the reasons), but may be for some reasons it should still locate in telemetry (or other existing module)?

Autogenerate documentation

Our protoc-gen-dcsdk protoc plugin already parses the proto files to feed them to our language templates in order to autogenerate language bindings in different languages. As an example, the MAVSDK-Swift templates end up in the MAVSDK-Swift generated source files.

Ideally, we would like to add documentation (doxygen-like) inside this generated code, e.g. to document the Action class or the arm() completable.

We would want this documentation to come respectively from here and here, so that we write it once for all languages.

It is possible to parse comments in proto files, as is proven by protoc-gen-doc, a protoc plugin written in go that does just that. However, we want to go one step further: instead of generating documentation for the proto files, we want to feed that documentation into our templates so that it ends up in our generated source code. This commit seems to be parsing documentation as well, in java.

I don't know how to parse documentation out of a proto file (but protoc-gen-doc seems to do that nicely), and I don't know how we should structure that documentation in the proto files in such a way that it can be used to generate language-specific documentation through templates (e.g. javadoc in Java, etc...).

The first step would be to make a proof of concept going in that direction, any contribution is welcome!

Differentiating between Fixedwing, Multicopter and VTOL (and others?)

Right now, MAVSDK is developed and tested against multicopters. Some functions are generic and will work with any MAVLink system (e.g. receiving telemetry messages). But some are not: action.land() makes no sense for a rover, and requires more information for a fixedwing (e.g. direction of the landing).

There had been discussions about having different plugins for different types. E.g. FwMission, McMission and VtolMission, possibly all extending a Mission base class. But I believe this will look weird from the user's perspective. Let's assume that a multicopter has action.land(), but a fixedwing needs action.land(param1, param2). The code will need some casting in static-typed languages. In pseudocode:

Action().land() // This won't work, because there is no common 'land()' in the base class

((McAction)Action()).land() // landing for a multicopter
((FwAction)Action()).land(param1, param2) // landing for a fixedwing

On top of that, if the user makes a wrong cast, they will have to deal with the consequences (e.g. catch an exception?) and therefore, probably they will want to do more something like this (at least I would):

if (Drone.isMulticopter()) {
    ((McAction)Action()).land() // landing for a multicopter
} else if (Drone.isFixedwing()) {
    ((FwAction)Action()).land(param1, param2) // landing for a fixedwing
}

But at this point, why would we need a cast? If we offer Drone.isMulticopter(), maybe we could just have everything in the same class.

My suggestion here would be the following:

  • We offer some kind of Drone.isMulticopter()/Drone.isRover() interface to the user.
  • Plugins may have functions for different platforms, i.e. mission.proto is here for all platforms, and we do not create mission_fixedwing.proto and similar.
  • If the user calls the wrong function (e.g. drone.action.transition_to_multicopter() on a fixedwing), then the function's implementation deals with that (e.g. by ignoring the call, showing a warning, or throwing an exception).

As a result, still with the land() pseudo-code, it would look like this:

// This works
if (Drone.isMulticopter()) {
    drone.action.land()
} else if (Drone.isFixedwing()) {
    drone.action.land(param1, param2)
}

// This fails (throws an exception, or something), because a fixedwing can't land with the land() function (it needs more info)
if (Drone.isFixedwing()) {
    drone.action.land()
}

// This may or may not fail, depending on our implementation choice, because it seems safe to ignore the fixedwing parameters when landing a multicopter
if (Drone.isMulticopter()) {
    drone.action.land(param1, param2)
}

@hamishwillee @julianoes: FYI

Provide type conversions between languages

Related to #46, but slightly different.

Different languages name the same primitive types differently (be it because of naming conventions, or bigger differences like "bool vs boolean"). We need a way to convert the type to each of our generated languages.

Following a discussion with @xvzf, a proposition would be to set the mapping between types in some configuration file. The reference could be C primitive types. The following example illustrates such a configuration file for Java:

int -> int
double -> double
bool -> boolean
string -> String

This file would be read and used by the parser to generate the correct type for jinja2. This time, the conversion would be done on the parser side (e.g. one would pass return_type = TypeConverter.format("string") to jinja2, and a java template would hence have "String" for return_type).

@julianoes @xvzf

tag a first version?

Hi,
I was curious about mavlink and MAVSDK.
I was wondering how hard it is to work without a versioned proto definition? I see different projects depends on different commit hashes of MAVSDK-Proto.

What's missing before we could have a v0.0.1 ?
Thanks!

Create proto file for action plugin

Right now, we only have a few examples for a subset of our plugins.

We need to write the full proto files and review them before we can start implementing the frontends (e.g. DroneCore-Python and DroneCore-Java).

More explanation in the pb_plugins README

After installing everything needed, there is no more explanation on how to go further. "How to use it" contains commands, but not where to use the commands. More explanation to help newcomers would be really appreciated!

Consistently capitalize names in jinja2

Different languages have different naming conventions (upper/lower camel case, snake case, ...). We need a way for the jinja2 templates to use the naming convention specific to their need. Note that our proto files use upper camel case.

Following discussions with @xvzf, a proposition would be to have class representing a name (/string) and providing conversions. For instance:

name = CaseName("CalibrateGimbalGyro") would provide:

  • name.upper_camel_case
  • name.lower_camel_case
  • name.snake_case

name would then be passed to the jinja2 template and could be used there (e.g. {{ name.snake_case }}() would call calibrate_gimbal_gyro()).

@julianoes @xvzf

Is it a drone, a system, a vehicle, a robot?

@julianoes suggests replacing drone by system, vehicle or robot. He said in a PR:

I'm not sold on using the word drone because it can also be a plane or a rover or whatnot. On the C++ side this is called a system.

My opinion is that anyway, it is used once in the code, to instantiate the main object, and the user can choose another name there. For instance:

drone = Drone()

or

rover = Drone()

An argument for System is that it doesn't have to be a vehicle, and it could be just a gimbal. My opinion is that System is too generic and doesn't mean anything (like Object or Thing). Drone is maybe not always technically correct (e.g. it may be a bit weird to write gimbal = Drone()), but most of the time it is perfectly fine. Vehicle is slightly more general, but doesn't solve gimbal = Vehicle() either.

Note that I'm biased towards Drone() because it's already written in Python, Java and Swift, and therefore I wouldn't need to rename all the code and examples ๐Ÿ™ˆ. I can rename everything if necessary, but then we should stick to it, trying to move towards a 1.0 release.

Create a "discovery" proto interface

Clients need an entrypoint to the backend. Because even the core component might end up managing only one vehicle (i.e. there will be multiple core components running at the same time), we need some way to get a list of the core components (e.g. with their "device uuid" and "gRPC server address:port").

This should be defined as a protobuf interface before it can be implemented on the backend side.

Example

A client wants to control a vehicle B through its plugins B1, B2, B3. It goes through the following:

  1. The client contacts the entrypoint and gets a list of running core servers [A, B, C], each of them having its own IP:port pair (it could be the same one for all of them, but that is an implementation detail for the client).
  2. The client selects the IP:port of core B and contacts it to fetch the list of plugins for vehicle B.
  3. core B sends the list [B1, B2, B3] to the client, each component having its own IP:port pair. Again, whether the components share the IP:port pair or not is an implementation detail for the client.
  4. The client can now interact with the drone through core and its corresponding plugins.

Design camera server implement discussion

When check the camera.proto and camera_server.proto, I found something need a discussion.

  1. The camera.proto and camera_server.proto have some same definition (e.g. Position in client Position in server ). Maybe better define in the camera_common.proto. The camera_server.proto also need to add camera_mode camera_status

  2. The camera status proto define. The camera status is packed in two mavlink message(MAVLINK_MSG_ID_CAMERA_CAPTURE_STATUS MAVLINK_MSG_ID_STORAGE_INFORMATION). The camera need to check the two status value. When implement the camera server side also have the same problem.

  3. The camera parameter is not in the param list and need to be set by ParamServer.

  4. But the value type is just string type. I read some camera define xml.The define type has various types. So I want to change the param_server.proto to support more custom define type.

enum ParamType {
    INT16_TYPE = 1;
    INT32_TYPE = 2;
   FLOAT_TYPE = 3;
  ....
    }
message ProvideParamCustomRequest {
    string name = 1; // Name of the parameter to provide
    ParamType type = 2; // In the param server convert to special type
    string value = 3; // Value the parameter should be set to
}

I have already test the param server use the e90.xml.
First add the param server in camera_server side.

    auto param_server = mavsdk::ParamServer(server_component);
    param_server.provide_param_custom("CAM_PHOTOQUAL", "1");

and the camera client will echo the following message:
[05:31:12|Error] Param types don't match for CAM_PHOTORATIO.

Is this a good design?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.