goodrobots / maverick-api

API backend for maverick-web
MIT License
8 stars 5 forks source link

Mission load and save #86

Open SamuelDudley opened 5 years ago

SamuelDudley commented 5 years ago

Modifications to the database occur via a separate mechanism (possibly mutation on missionDatabase)

SamuelDudley commented 5 years ago

mission list query example: http://newdev.maverick.one:7000/graphiql?query=%7B%0A%20%20MissionList(id%3A%20%22loaded%22)%20%7B%0A%20%20%20%20id%0A%20%20%20%20mission%20%7B%0A%20%20%20%20%20%20seq%0A%20%20%20%20%20%20isCurrent%0A%20%20%20%20%20%20autocontinue%0A%20%20%20%20%20%20frame%0A%20%20%20%20%20%20command%0A%20%20%20%20%20%20param1%0A%20%20%20%20%20%20param2%0A%20%20%20%20%20%20param3%0A%20%20%20%20%20%20param4%0A%20%20%20%20%20%20latitude%0A%20%20%20%20%20%20longitude%0A%20%20%20%20%20%20altitude%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A

This returns the current mission that is loaded on the flight controller / autopilot

SamuelDudley commented 5 years ago

mission database query example: http://newdev.maverick.one:7000/graphiql?query=%7B%0A%20%20MissionDatabase(id%3A%20%22*%22)%20%7B%0A%20%20%20%20id%0A%20%20%20%20missions%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20mission%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A

This returns all missions that are save in the database in the api to the client.

SamuelDudley commented 5 years ago

Uploading a mission to the autopilot from the client. This is achieved by submitting a mission mutation with an id == loaded. Example: http://newdev.maverick.one:7000/graphiql?query=mutation%20%7B%0A%20%20MissionList(id%3A%20%22loaded%22%2C%20mission%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%200%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%200%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36326217651367%2C%0A%20%20%20%20%20%20longitude%3A%20149.1652374267578%2C%0A%20%20%20%20%20%20altitude%3A%20584.010009765625%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%201%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2022%2C%0A%20%20%20%20%20%20param1%3A%2015%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%200%2C%0A%20%20%20%20%20%20longitude%3A%200%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%202%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36441421508789%2C%0A%20%20%20%20%20%20longitude%3A%20149.16445922851562%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%0A%09%5D)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D%0A

SamuelDudley commented 5 years ago

As per above the same mutation call can be used to save the mission back to the database. This is achieved by making the id something other than loaded (in this example it is test): http://newdev.maverick.one:7000/graphiql?query=mutation%20%7B%0A%20%20MissionList(id%3A%20%22test%22%2C%20mission%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%200%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%200%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36326217651367%2C%0A%20%20%20%20%20%20longitude%3A%20149.1652374267578%2C%0A%20%20%20%20%20%20altitude%3A%20584.010009765625%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%201%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2022%2C%0A%20%20%20%20%20%20param1%3A%2015%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%200%2C%0A%20%20%20%20%20%20longitude%3A%200%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%202%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36441421508789%2C%0A%20%20%20%20%20%20longitude%3A%20149.16445922851562%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%0A%09%5D)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D%0A

SamuelDudley commented 5 years ago

@fnoop Can you please review the above to make sure it aligns with what was discussed in gitter? Thanks!

fnoop commented 5 years ago

Could we please have a 'name' and 'description' field as well as 'id' field? this is so we can list the missions in the interface and the user will have some way of differentiating between different missions. Name could be a short title (eg. Map Field 1) of say max 16 or 32 chars and Description could be a longer text eg. 'Auto take off, Start from bottom left of field 1 and perform linear transects until field is entirely mapped, then auto land at takeoff point'.

SamuelDudley commented 5 years ago

Sure, no problem. We can keep adding fields to missionlist as we require them.

SamuelDudley commented 5 years ago

@fnoop I have added the values. Currently the loaded mission will not return a name or description, but all database missions will

query http://dev.maverick.one:7000/graphiql?query=%7B%0A%20%20MissionList(id%3A%20%22test%22)%20%7B%0A%20%20%20%20id%0A%20%20%20%20total%0A%20%20%20%20updateTime%0A%20%20%20%20name%0A%20%20%20%20description%0A%20%20%20%20mission%20%7B%0A%20%20%20%20%20%20seq%0A%20%20%20%20%20%20isCurrent%0A%20%20%20%20%20%20autocontinue%0A%20%20%20%20%20%20frame%0A%20%20%20%20%20%20command%0A%20%20%20%20%20%20param1%0A%20%20%20%20%20%20param2%0A%20%20%20%20%20%20param3%0A%20%20%20%20%20%20param4%0A%20%20%20%20%20%20latitude%0A%20%20%20%20%20%20longitude%0A%20%20%20%20%20%20altitude%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A

mutation http://newdev.maverick.one:7000/graphiql?query=mutation%20%7B%0A%20%20MissionList(id%3A%20%22test%22%2C%20name%3A%20%22Test%20Mission%20%231%22%2C%20description%3A%20%22This%20is%20a%20test%20of%20the%20api%20mission%20mutation!%22%2C%20mission%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%200%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%200%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36326217651367%2C%0A%20%20%20%20%20%20longitude%3A%20149.1652374267578%2C%0A%20%20%20%20%20%20altitude%3A%20584.010009765625%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%201%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2022%2C%0A%20%20%20%20%20%20param1%3A%2015%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%200%2C%0A%20%20%20%20%20%20longitude%3A%200%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20seq%3A%202%2C%0A%20%20%20%20%20%20isCurrent%3A%20false%2C%0A%20%20%20%20%20%20autocontinue%3A%20true%2C%0A%20%20%20%20%20%20frame%3A%203%2C%0A%20%20%20%20%20%20command%3A%2016%2C%0A%20%20%20%20%20%20param1%3A%200%2C%0A%20%20%20%20%20%20param2%3A%200%2C%0A%20%20%20%20%20%20param3%3A%200%2C%0A%20%20%20%20%20%20param4%3A%200%2C%0A%20%20%20%20%20%20latitude%3A%20-35.36441421508789%2C%0A%20%20%20%20%20%20longitude%3A%20149.16445922851562%2C%0A%20%20%20%20%20%20altitude%3A%2050%0A%20%20%20%20%7D%0A%09%5D)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D%0A

fnoop commented 5 years ago

Great! Thanks :)

fnoop commented 5 years ago

Is it possible to have a proper name+description for loaded mission, or is there a reason you leave it blank?

SamuelDudley commented 5 years ago

Yes it is possible but more complex than the 10min it took to add the other feature :) If the loaded mission is coming from the database then we can pass the name and description over, but as the loaded mission is initially populated from ROS (i.e. from the vehicle) we don't have access to that information for display.

One way around this might be to add a computationally cheap hash to each of the missions in the database. When we first get the mission from the vehicle we can generate a hash and compare against the database. If we find a match, keep the mission items as is but apply the name and description that we have stored.

This also might fail as the home point is updated, changing the mission hash? Perhaps we would need two hashes, one with a home point for an exact match and one without the home point as a more general match... unsure until we try...

Can you think of another way of persisting the mission name and description?

fnoop commented 5 years ago

I actually meant just something simpler than that - to manually add a fixed name/description to the 'loaded' id mission?

fnoop commented 5 years ago

So eg. for a waypoint, the current MissionList message provides these fields:

screenshot 2019-01-30 at 09 15 49

However there are more available, eg in the mavlink meta data for the waypoint command, it says these are available params:

    "MAV_CMD": {
        "16": {
            "name": "NAV_WAYPOINT",
            "description": "Navigate to waypoint.",
            "param": {
                "1": "Hold time in decimal seconds. (ignored by fixed wing, time to stay at waypoint for rotary wing)",
                "2": "Acceptance radius in meters (if the sphere with this radius is hit, the waypoint counts as reached)",
                "3": "0 to pass through the WP, if > 0 radius in meters to pass by WP. Positive value for clockwise orbit, negative value for counter-clockwise orbit. Allows traje
ctory control.",
                "4": "Desired yaw angle at waypoint (rotary wing). NaN for unchanged.",
                "5": "Latitude",
                "6": "Longitude",
                "7": "Altitude"

Two questions:

  1. Are these extra parameters available and can they be exposed in graphql?
  2. Can the mavlink metadata be output with the fieldname instead of enumerated index? (ie. 'latitude' instead of '5')?
SamuelDudley commented 5 years ago

Re 1 the all the required fields are already exposed (see below). Re 2 I'm struggling to work out why you would want that. as there are always 7 params and they map to the seven fields of the graphql message isn't it easier to access each text string by its index and display that in a form 7 columns wide?

Taking the example of NAV_WAYPOINT above the parameters are already exposed in graphql.

1: param1 2: param2 3: param3 4: param4 5: latitude 6: longitude 7: altitude

For example Based on the text information above I know that the param in index 1 of NAV_WAYPOINT will control the hold time for a waypoint. This can be passed into the graphql mission by mutating a float value in the param1 field of the graphql mission.

The mission schema always has these 7 fields so normally the following occurs as you plan a mission:

Make a new mission item. The user selects from the list of actions, waypoints, do commands etc. The corresponding interger to this action is stored in the command graphql field. Next the seven parameter are looked up for that particular command and the discription text is displayed informing the user what each of the seven fields do for that particular command. The seven param fields map back to the graphql message as I described before. Lastly they select the frame which is also looked up to provide discriptions to the user. The mission item is then complete and another can be added to form a missionList.

SamuelDudley commented 5 years ago

@fnoop I'm not saying it has to occur that way, but that is what I have experienced and it seems to work reasonably well. I feel that if we index the parameters by the labels they will always be changing, where as by using the numbers you can easily map what each param does to the correct graphql message field. I hope this makes sense, let me know if I'm not explaining myself clearly :)

fnoop commented 5 years ago

Ah no, that makes perfect sense! Me being stupid.

fnoop commented 5 years ago

Params 5, 6, 7 are not always latitude, longitude and altitude, eg:

       "23": {
            "name": "NAV_LAND_LOCAL",
            "description": "Land at local position (local frame only)",
            "param": {
                "1": "Landing target number (if available)",
                "2": "Maximum accepted offset from desired landing position [m] - computed magnitude from spherical coordinates: d = sqrt(x^2 + y^2 + z^2), which gives the maximum acce
pted distance between the desired landing position and the position where the vehicle is about to land",
                "3": "Landing descend rate [ms^-1]",
                "4": "Desired yaw angle [rad]",
                "5": "Y-axis position [m]",
                "6": "X-axis position [m]",
                "7": "Z-axis / ground level position [m]"
            }
        },
        "30": {
            "name": "NAV_CONTINUE_AND_CHANGE_ALT",
            "description": "Continue on the current course and climb/descend to specified altitude.  When the altitude is reached continue to the next command (i.e., don't proceed to t
he next command until the desired altitude is reached.",
            "param": {
                "1": "Climb or Descend (0 = Neutral, command completes when within 5m of this command's altitude, 1 = Climbing, command completes when at or above this command's altitu
de, 2 = Descending, command completes when at or below this command's altitude.",
                "2": "Empty",
                "3": "Empty",
                "4": "Empty",
                "5": "Empty",
                "6": "Empty",
                "7": "Desired altitude in meters"
            }
        },
        "32": {
            "name": "DO_FOLLOW",
            "description": "Being following a target",
            "param": {
                "1": "System ID (the system ID of the FOLLOW_TARGET beacon). Send 0 to disable follow-me and return to the default position hold mode",
                "2": "RESERVED",
                "3": "RESERVED",
                "4": "altitude flag: 0: Keep current altitude, 1: keep altitude difference to target, 2: go to a fixed altitude above home",
                "5": "altitude",
                "6": "RESERVED",
                "7": "TTL in seconds in which the MAV should go to the default position hold mode after a message rx timeout"
            }
        },

Should the message fields be renamed to param5, param6, param7?

fnoop commented 5 years ago

Also looks like the param values are descriptions, are short names available?

        "23": {
            "name": "NAV_LAND_LOCAL",
            "description": "Land at local position (local frame only)",
            "param": {
                "1": "Landing target number (if available)",
                "2": "Maximum accepted offset from desired landing position [m] - computed magnitude from spherical coordinates: d = sqrt(x^2 + y^2 + z^2), which gives the maximum acce
pted distance between the desired landing position and the position where the vehicle is about to land",
                "3": "Landing descend rate [ms^-1]",
                "4": "Desired yaw angle [rad]",
                "5": "Y-axis position [m]",
                "6": "X-axis position [m]",
                "7": "Z-axis / ground level position [m]"
SamuelDudley commented 5 years ago

Should the message fields be renamed to param5, param6, param7?

Yes. I think this is a good idea.

Also looks like the param values are descriptions, are short names available?

When I wrote the extraction tool (some time ago) there was no further information available. This may have changed with later versions. As I recall MAVProxy was doing some level of hackery to generate units and short names from the longer descriptions

SamuelDudley commented 5 years ago

Just confirming the point about the lack of short name or units for the params: https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/common.xml#L756

As you can see the information isn't available. If we require it we will need to try and extract it before generating the json... How badly do you want it? :)

cglusky commented 5 years ago

Can we just create our own (average) human readable name and map it to the name value on the client? Perhaps something like what they do to make UI's multi-lingual. Just a flat file with a look-up.

fnoop commented 5 years ago

Yes but trying to avoid manual work where possible. If it already exists elsewhere then best to use other people's hard work :)

cglusky commented 5 years ago

you could strip off the prefix and underscores of the name field.

name="MAV_CMD_NAV_WAYPOINT"

WAYPOINT

"MAV_CMD_NAV_LOITER_UNLIM"

LOITER UNLIM

And then use the description in a tool tip.

fnoop commented 5 years ago

Yes that's effectively what we're doing for the waypoint types - this is more about the waypoint parameters now. From the example above:

"1": "Landing target number (if available)",
                "2": "Maximum accepted offset from desired landing position [m] - computed magnitude from spherical coordinates: d = sqrt(x^2 + y^2 + z^2), which gives the maximum acce
pted distance between the desired landing position and the position where the vehicle is about to land",
                "3": "Landing descend rate [ms^-1]",

These should have short parameter names eg:

1. Target Number
2. Position Offset
3. Descent Rate
cglusky commented 5 years ago

ah. well, if not available then i guess you are stuck with a look-up table.

SamuelDudley commented 5 years ago

Yes, I think we will have to do the work by hand on this occasion...