-
-
Notifications
You must be signed in to change notification settings - Fork 156
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
feature: V2 Autopilot API #1596
base: master
Are you sure you want to change the base?
Conversation
to facilitate plugins implement Signal K APIs.
@sbender9 would appreciate your feedback as to any forseen issues with the proposed API based on the current signalk-autopilot plugin functionality. |
@seandepagnier would appreciate your feedback with regards to the "Signal K aware" pilot scenario where the plugin requirements are more focussed on sending commands. Just as an FYI, Freeboard-SK implements a PoC PyPilot plugin that requires
I'm not sure if this is the preferred method, but was a convenient method for the PoC. |
I think this is a good start, but I see several issues here:
I remember you mentioning that you have a PoC of pypilot autopilot plugin - is it somewhere to be found? All in all I think it would be a good idea to work this out end to end: have a working or at least conceptually sound autopilot plugin wired together with this and maybe even a rudimentary standaloe web ui at the other end. In the past we have multiple cases where we worked from the specification that turned out to be more theoretical than practical. |
This API is implemented in Freeboard-SK today to interface with PyPilot. v2.3.0 branch is a more complete implementation.
They are mentioned in the context that autopilot operation is already supported by Signal K through the
Yes.. as per the text uses
Originally this API was based on the Resources API model that supports multiple providers. |
I am following this, and dont have much to add, except that, yes, I do have 2 pypilot installed on my boat. Generally one of them is off to save power, but it is essentially a backup pilot. Right now, if one pypilot has a wind sensor attached, the other pypilot can use it if both pypilots are connected to the same signalk server. It would be possible for example for each pilot to be wired to a wind sensor. Then if both pilots are on, whichever wind sensor is to windward could be used. There are other examples, but supporting multiple autopilots is a good idea, however be aware that multiple pypilots in the future may detect each other and communicate directly (outside of signalk) as well. |
With regards to operation with one or more autopilots I see the following scenarios:
Given the above scenarios, the breadth of devices and that the plugin is managing communication with the autopilot I see the following options:
I'm leaning towards option 1. send commands to all plugins and let them sort it out. |
I've been mulling this over, here are my thoughts: Looking at the API definition and the api routes it looks like the Autopilot api would not be overly complex in TypeScript - it would look like this
or am I missing something? Leaving routes implementation, validation and emitting deltas to each autopilot integration plugin sounds like a recipe for having as many different behaviors & intrepretations of how exactly the whole thing works as there are autopilot integration plugins. Why would we not got the "provider" way? Meaning have the server implement routes, validation, emitting deltas and access control and then delegate the operations to the actual AP plugin integration code? This would decouple the AP integration from the server, leaving configuring and routing autopilots to the server. As for the multiple autopilot case: I think the plugins will need to sort out is not a good enough strategy. Take for instance just the engange operation: the user most definitely must decide what autopilot the operation is about. In this case the REST resource structure would actually work pretty well: mount each autopilot's api at In general I think it is a good idea to sort the multiple instances case sooner rather than later, even if out there the single cases will far outnumber the multiple ones and it is kind of a sidetrack. Retrofitting support afterwards is much harder. We need also a way for an autopilot integration to send updates about changes coming from non-SK controlled autopilot devices: the user adjusting the target or mode via pushbuttons on the unit or for N2K devices over CAN, Sean's comment about autopilots changing state outside the SK APIs control etc. So the server api should provide a way for the ingeration to emit autopilot state updates (deltas?). As for multiple autopilot integrations of a single kind: the idea for adding support for instantiating a plugin multiple times, with multiple configurations has been there for quite a while. Maybe it's time for that? People have requested for example multiple separate configurations for sk-to-nmea0183. BTW I think APB and MWV are not really autopilot control: APB is 100% derived from the data in SK Course api and vessel position and heading and MWV is just wind sensor data. Did you put the pypilot code in Freeboard for convenience? Seems like an odd tangle, when it could as easily be an independent plugin. Or are you waiting for the capabilities API? |
Consider the common use case of two devices running opencpn or avnav, lets say a raspberry pi running signalk server and pypilot, and a laptop. If a route is activated in opencpn, normally it sends commands to steer the autopilot without needing signalk. However, only one instance of opencpn can do this at a time. There is some integration between opencpn instances, but if the idea is to make this universal, it must work with other plotters, like avnav and communicate with signalk. So for example, if you activated a route in opencpn, it would send the route via signalk, and other instances of other plotters would see this, create the route and activate it similarly. If the route is de-activated from any plotter it would deactivate from all of them, across plotters, and autopilots. The use case of multiple plotters and a single pilot is much more common. Typically multiple autopilots are for backup and only one is even powered on at a time. |
No disagreement from me! Sadly all interest in OpenCPN seems to be in integrating O instances, not universal APIs and communications (Headless use case, Route sharing). Now that O has the networking infrastructure for http and ws the foundation is there, but nobody seems to be building on it. Any ideas how to promote cross app cooperation appreciated. But that is mostly about course api (activating route, advancing to next waypoint etc), not the Autopilot api (engange/disengage, change mode) under discussion here. They are pretty tightly related, but separate: you can use a an autopilot without a plotter and a plotter without an autopilot. |
Another thing to consider is 'trajectories' This is a logical advancement in route following. What this means, is the autopilot actually tries to follow spline or beizer curve based on the route rather than route segments. It is something consider as there are a few more parameters, and the intended 'trajectory' should be rendered in the plotter. |
Add ability to select the primary provider.
@seandepagnier Is there a way to run pypilot in ”test” mode so that from the outside it looks like everything works as it should even though no actual mechanism is connected? Would be useful for testing Adrian’s pypilot integration end2end on the desktop. |
Convert the funky properties with function types to methods.
Less lookup code per route.
Again: my point is that we should not build assumptions like engaging autopilots always sets the target heading. You did not say that: if we assume your engaging autopilots almost always sets the target heading then the API should be flexible enough to support cases where the target is not automatically set.
I think we can list use cases, but it is foolish to assume that we can map all use cases. Some use cases may not even make sense (like having multiple active ap's), but arise from the messy real world (user errors, flaky comms, race conditions etc). Rereading my own comments I think we should be in pretty good shape re: multiple aps if the api supports
Moving forward towards solutions...I think we have several ways to solve these
I am wondering if it is time to break the SK v1 mechanism where delta paths map 1:1 to http paths. In practise we could use Sidenote: I don't think we want to reflect the internals of SK server in the API, so ap's in the API should have just a single identifier, not providerId.deviceId. We can internally derive the identifier from plugin id and instance id. But if for example pypilot would implement this natively the two parts would not make much sense. Oh I can come up with one more desirable API feature: steer developers dealing with the API to think about multiple APs and not just build "oh there's only ever going to be one" systems. btw thanks for insightful discussion! I feel we are making progress here. |
FYI resources API uses the approach of a query parameter to target the provider.
|
Yep. Maybe we could have picked a little bit more generic name for that parameter, but I think the abstraction there is correct and not too tied to current SK server. |
Whichever is more clean, but a way to specifically address a particular autopilot vs broadcast to all pilots. In the case of broadcasting the signalk server may need to be aware of which pilot is "active" and for this it might need a separate key to allow clients to inform the service which pilot to use so that broadcast requests without a particular target will only enable the primary autopilot. |
Allow plugin to register as the Default Provider. Delta source value contains provider id and device id Delta source value is `autopilotApi` for updates from defaultProvider. Target provider in API requests using query parameter.
Add device id to API paths Change API path to `steering/autopilots` to align with id in path.
Updated OpenAPI definitions Updated docs.
The following WIP plugins have been updated to align with this PR and can be used for testing and / or template. |
Version 2 Autopilot API:
Goals:
steering.autopilot
path with$source
= the autopilot device identifiersteering.autopilot.default
to notify clients when the default autopilot device is set / changedAPI will compliment these Signal K Server features to support autopilot operation:
Course API
: To set the destination and enable course data calculations to create a cohesive data set for navigation operations.signalk-to-nmea0183
plugin: Deliver the necessary NMEA sentences APB (for route control) and MWV (for wind steer) in the NMEA0183 data stream.Overview:
Features:
REST API
/signalk/v2/api/vessels/self/steering/autopilots
GET /signalk/v2/api/vessels/self/steering/autopilots
/signalk/v2/api/vessels/self/steering/autopilots/{device_id}/*
/signalk/v2/api/vessels/self/steering/autopilots/_default/*
POST /signalk/v2/api/vessels/self/steering/autopilots/_providers/_default/{device_id}
GET /signalk/v2/api/vessels/self/steering/autopilots/{device_id}
POST /signalk/v2/api/vessels/self/steering/autopilots/{device_id}/mode
POST /signalk/v2/api/vessels/self/steering/autopilots/{device_id}/target
DELTAS
vessels.self.steering.autopilot.*
with$source
set to thedevice_id
vessels.self.steering.autopilot.default
when default device is set / changedNotifications
Server / Provider Interface
Provider
Plugins (under development):
Related links:
Course API
Course API Definition
signalk-autopilot issue 1
Extending autopilot paths