Open panaaj opened 3 years ago
This is really commendable work!
I think we should also include what deltas are sent. For example if I am running several UIs, like multiple instances of Freeboard, I want to keep them in sync. A practical use case would be setting the course down below in the use navigation station and the settings reflected at the helm.
Do we want to keep somehow track of who set the course? For example the user, or a course computer advancing the route as the vessel makes way along the route (in the latter case it would be useful to know who originally set the route to follow).
Is it useful to have the irrelevant fields as ´null` or should they be just undefined / not there at all?
How about advance/go back one waypoint?
What about the sequence
I am not sure if we have really used hrefs anywhere in anger yet. As the SK http paths are mounted at /signalk/v1/api should there be a mechanism to indicate that the path in href is relative to that, or should there be something in the begining of the path, denoting that this is the case and the path does not start at the http server's root? Or should the hrefs be relative?
I think we should also include what deltas are sent. For example if I am running several UIs, like multiple instances of Freeboard, I want to keep them in sync. A practical use case would be setting the course down below in the use navigation station and the settings reflected at the helm.
Agreed.
I will add something to the README.md document in apis/course
(which can be used as the documentation for this API).
Do we want to keep somehow track of who set the course? For example the user, or a course computer advancing the route as the vessel makes way along the route (in the latter case it would be useful to know who originally set the route to follow).
Have added a source
attribute to hold a value representing who made the change.
Is it useful to have the irrelevant fields as ´null` or should they be just undefined / not there at all?
The convention to date seems to have been:
api
endpoint / no delta emitted via stream
.null
value when a previous value has been deleted / removed or path has a provider but no value is available.This convention seems to work quite well currently.
How about advance/go back one waypoint?
Was covered in course/activeRoute/nextPoint
API by the request being able to contain either:
increment
attribute the value of which can be 1 (increment) or -1 (decrement) pointIndex
attribute which sets the specific point in the routeHave separated this out to two APIs:
course/activeRoute/nextPoint
for previous / nextcourse/activeRoute/setPoint
for setting a specific point in the routeBoth of these APIs will consider the value of the reverse
attribute value provided when the route was activated.
What about the sequence
- activate route with waypoint 0
- steer the boat so that it is near, but not really at waypoint 0
- forward the course, so that the active waypoint is 1 now previousPoint should be waypoint0, shouldn't it? And XTE calculated between vessel position and the line between points 0 and 1.
My understanding is that XTE works on source
and destination
position.... so if the vessel source
position was only proximal to the destination location prior to advancing to the next point....... would using the route point position as the source
instead of the vessel position negatively impact the XTE calculation significantly?
What does this mean for autopilot operation, etc?
I am not sure if we have really used hrefs anywhere in anger yet. As the SK http paths are mounted at /signalk/v1/api should there be a mechanism to indicate that the path in href is relative to that, or should there be something in the begining of the path, denoting that this is the case and the path does not start at the http server's root? Or should the hrefs be relative?
From the relevant part of the specification the implication is that it's relative to signalk/v1/api
... I'm OK with that based on the work done with Freeboard and resources so far.
Extract from navigation.course.activeRoute.href
"href": {
"description": "A reference (URL) to the presently active route, in resources.",
"example": "/resources/routes/urn:mrn:signalk:uuid:3dd34dcc-36bf-4d61-ba80-233799b25672",
"type": "string"
}
https://www.manualsdir.com/manuals/199085/raymarine-chartplotter.html?page=48&original=1
Relevant features:
Re: XTE: forget my example of being near or far from the waypoint. If we are navigating a route imho XTE would be the perpendicular distance between current position and the route leg, defined by two waypoints of the route, that we (or the autopilot) has set to be nextPoint and previousPoint. Does not really matter what our position is - XTE can be calculated even when we are behind previousPosition.
The only exception would be "restart XTE" case.
Added restart
api endpoint and updated description of previousPoint
to align.
Added arrivalCircle
endpoint to enable setting the radius to determine arrival at destination.
Also added arrivalCircle
attribute to destination
and activeRoute
endpoints.
Do we want to include specifying the notifications for entering arrival circle and passing waypoint perpendicular, or is that going into autopilot functionality?
I don't love the "PUT" or "POST". I think these should all be PUT, or at least pick one.
Do we want to include specifying the notifications for entering arrival circle and passing waypoint perpendicular, or is that going into autopilot functionality?
I think that it's worth specifiying at least the path of the notification that would be raised.
e.g. notifications.navigation.course.arrivalCircleEntered
I don't love the "PUT" or "POST". I think these should all be PUT, or at least pick one.
I'm OK with just PUT.
Updated OpenAPI definition to remove POST operatrions. Updated the README.md to reflect these changes as well as general formatting and readability.
This is more in the realm of implementation, but the frequency at which deltas are sent and whether the course values are persisted, so they survive a server restart, all contribute to expected behaviour. Are these worth including?
I am adding a bunch of comments, see what you make of them.
I am starting to think that it would be useful to create the server implementation and a UI to exercise this API before merging this. While this sounds pretty straightforward the devils in the details and they are hard to get right just working in the abstract.
I have been mocking this up by extending the freeboard-sk-helper
plugin and a modified sk-resources-fs
plugin to allow route details to be retrieved. I can confirm the proposed operation.
As far as embedding the course API into the server it will first require the resource path handling functionality to enable the courseAPI to retrieve route details.
I have working skeleton of the resources
path handling as described in server issues #1351 .
If it is the correct protocol I can push this branch to signalk-server
repository.
If it is the correct protocol I can push this branch to signalk-server repository.
Please do. I had already trouble looking for PR 1351 and then realised it was an issue, not a PR.
Collaboration is easier when working off the same repo: a bit less work with checking out work locally and at least trivial corrections like typos need not go via comments. Can also collaborate on stuff where we are not stepping on each other's toes.
Feature: Course API
Description:
Define an API for Signal K client applications that provides methods to set a destination or navigate a route.
These methods manage the setting of values in the relevant Signal K paths under both
navigation.courseGreatCircle
andnavigation.courseRhumbline
to enable a course computer to generate additional navigation information (XTE, DTG, etc) as well as facilitate display on a chart plotter.The API will facilitate operations such as:
/resources/waypoints
as a destination/resources/routes
Motivation:
Currently Signal K makes available paths to store navigation data but it is largely left up to implementors of client applications to determine how they are used.
This is can cause interoperability issues and inconsistency in application (e.g. calculations in
signalk-derived-data
plugin will use a mixture of pathsnavigation.courseGreatCircle
andnavigation.courseRhumbline
) so depending on an individual implementation results may vary.Defining and implementing an API will provide reliability in how the values in these paths are populated ensuring confidence in the source data used in course calculations.
By clearly defining and managing the use of specific
course
paths within the Signal K schema, this will ensure consistency in the values they contain and engender confidence in their use.Maintaining quality data in these paths enables the reliable operation of other navigation equipment such as:
by providing a trusted source of data for use in calculating navigation information for steering a course.
The paths within the Signal K schema pertaining to other navigation operations will be maintained by the relevant equipment or Signal K API.
1. Signal K Paths in Scope:
Note: All paths outlined below are relative to
/signalk/v1/api/vessels/self
.The Signal K specification contains a
navigation.course
schema definition which is applied to both thenavigation/courseGreatCircle
andnavigation/courseRhumbline
paths.The following properties under both these paths are in scope for management by this API:
This API will provide endpoints under the path
navigation/course
in order to set a course as well as query the current course information.2.API Operation:
While the intended use of the
in scope
Signal K paths are defined in the specification, the actual use of these paths in practise determines the success of an implementation.2.1 Use of
previousPoint
.To facilitate course calculations such as XTE where the source position is required, the
previousPoint.position
attribute will be set (at the time the destination is set) as follows:When a position (lat, lon) is supplied as a destination: Set the value of
previousPoint.position
to the location of the vessel.When a reference to a waypoint resource is supplied as a destination: Set the value of
previousPoint.position
to the location of the vessel.When a reference to a route resource is is supplied:
If the supplied route
pointIndex
is0
(point at start of the route) then set the value ofpreviousPoint.position
to the location of the vessel.If the supplied route
pointIndex
is not0
then set the value ofpreviousPoint.position
to that of the preceding point in the route.When a "Course Restart" is requested: Set the value of
previousPoint.position
to the location of the vessel.When a destination or active route is "Cancelled": then set the value of
previousPoint.position
tonull
.3.API Methods:
The following endpoints under the path
navigation/course
make up the Course API.3.1 Set a position (lat, lon) as a destination
Use case: Provide "navigate to here" operation.
Action:
PUT
Path:
<self>/navigation/course/destination
Request body:
where:
position
: The destination lat, lon (as per Signal K schema)type
(optional): A string describing the destination (as per Signal K schema).arrivalCircle
(optional): Radius of circle centered at destination indicating arrival.This will result in the following Signal K path values being set:
3.2 Set a Waypoint as a destination
Use case: Provide "navigate to selected waypoint resource" operation.
Action:
PUT
Path:
<self>/navigation/course/destination
Request body:
where:
href
: The path to the target waypoint in/resources/waypoints/
.arrivalCircle
(optional): Radius of circle centered at destination indicating arrival.This will result in the following Signal K path values being set:
3.3 Clear / Cancel a destination or Activated Route.
Use case: Provide "stop navigating to destination" or "deactivate as route" operation.
Action:
DELETE
Path:
<self>/navigation/course/destination
or<self>/navigation/course/activeRoute
Request body: empty
This will result in the following Signal K path values being set:
3.4 Activate a Route to follow.
Use case: Provide "activate / follow a route" operation.
Action:
PUT
Path:
<self>/navigation/course/activeRoute
Request body:
where:
href
: The path to the target route in/resources/routes/
.pointIndex
(optional): Zero based index of the point within the route to use as the initial destination (defaults to 0 if not supplied or if value is larger than index of last point in the route).reverse
(optional): Iftrue
performs operations on route points in reverse order (defaults to false).arrivalCircle
(optional): Radius of circle centered at destination indicating arrival.This will result in the following Signal K path values being set:
3.5 Select point in the active Route as destination.
Use case: Provide "go to point in route" operation.
Action:
PUT
Path:
<self>/navigation/course/activeRoute/pointIndex
Request body:
where:
value
: Zero based index of the point within the route to use as the initial destination (if value is larger than index of last point in the route then destination is not changed).This will result in the following Signal K path values being set:
3.6 Increment / decrement point in the active Route as destination.
Use case: Provide "previous / next point" operation.
Action:
PUT
Path:
<self>/navigation/course/activeRoute/nextPoint
Request body:
where:
value
: Is either1
(next point) or-1
(previous point).This will result in the following Signal K path values being set:
3.7 Restart course calculations.
Use case: Provide "restart XTE" operation.
Action:
PUT
Path:
<self>/navigation/course/activeRoute/restart
Request body: empty
3.8 Set arrival circle.
Use case: Provide ability to set the radius of a circle centered at destination indicating arrival.
Action:
PUT
Path:
<self>/navigation/course/arrivalCircle
Request body:
where:
value
: Is the radius of the circle in meters.This will result in the following Signal K path values being set:
3.9 Query current course details.
Use case: Provide "get current course", "get course details" operation.
Action:
GET
Path:
<self>/navigation/course
Response: JSON formatted object containing the current course details as per the following example:
4. Signal K Stream Deltas
The implementation of the Course API requires that the relevant delta messages are sent for the in-scope Signal K paths when:
The absence of a delta for a specific Signal K path indicates that the path has never had a value assigned to it.
Where a delta value is
null
, this indicates that a previous value is no longer valid (i.e. there is a provider for this path but there is no current value available).Delta messages for in-scope paths are as follows: