Skip to content

Commit

Permalink
Dodge operations
Browse files Browse the repository at this point in the history
  • Loading branch information
panaaj committed Nov 25, 2024
1 parent e65ae99 commit b5912ff
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 359 deletions.
275 changes: 133 additions & 142 deletions docs/src/develop/plugins/autopilot_provider_plugins.md

Large diffs are not rendered by default.

115 changes: 68 additions & 47 deletions docs/src/develop/rest-api/autopilot_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,26 @@

## Overview

The Autopilot API defines the `autopilots` path under the `steering` schema group _(e.g. `/signalk/v2/api/vessels/self/steering/autopilots`)_ for representing information from one or more autopilot devices.
The Autopilot API defines the `autopilots` path under `self` _(e.g. `/signalk/v2/api/vessels/self/autopilots`)_ for representing information from one or more autopilot devices.

The Autopilot API provides a mechanism for applications to issue requests to autopilot devices to perform common operations. Additionally, when multiple autopilot devices are present, each autopilot device is individually addressable.

_Note: Autopilot provider plugins are required to enable the API operation and provide communication with autopilot devices. See [Autopilot Provider Plugins](../plugins/autopilot_provider_plugins.md) for details._


## Common Operations

The following operations are supported:
- Setting the operating mode
- Engaging / Disengaging the pilot
- Setting / adjusting the course
- Dodging port / starboard
- Tacking / Gybing


## The _Default_ Autopilot

To ensure a consistent API calling profile and to simplify client operations, the Autopilot API will assign a _default_ autopilot device which is accessible using the path `./steering/autopilots/_default`.
To ensure a consistent API calling profile and to simplify client operations, the Autopilot API will assign a _default_ autopilot device which is accessible using the path `/signalk/v2/api/vessels/self/autopilots/_default`.

- When only one autopilot is present, it will be automatically assigned as the _default_.

Expand All @@ -23,11 +34,11 @@ To ensure a consistent API calling profile and to simplify client operations, th

### Getting the Default Autopilot Identifier

To get the id of the _default_ autopilot, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots/_providers/_default`.
To get the id of the _default_ autopilot, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/autopilots/_providers/_default`.

_Example:_
```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/_providers/_default"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/_providers/_default"
```

_Response:_
Expand All @@ -39,24 +50,24 @@ _Response:_

### Setting an Autopilot as the Default

To set / change the _default_ autopilot, submit an HTTP `POST` request to `/signalk/v2/api/vessels/self/steering/autopilots/_providers/_default/{id}` where `{id}` is the identifier of the autopilot to use as the _default_.
To set / change the _default_ autopilot, submit an HTTP `POST` request to `/signalk/v2/api/vessels/self/autopilots/_providers/_default/{id}` where `{id}` is the identifier of the autopilot to use as the _default_.

_Example:_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/_providers/_default/raymarine-id"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/_providers/_default/raymarine-id"
```

The autopilot with the supplied id will now be the target of requests made to `./steering/autopilots/_default/*`.
The autopilot with the supplied id will now be the target of requests made to `/signalk/v2/api/vessels/self/autopilots/_default/*`.


## Listing the available Autopilots

To retrieve a list of installed autopilot devices, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots`.
To retrieve a list of installed autopilot devices, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/autopilots`.

The response will be an object containing all the registered autopilot devices, keyed by their identifier, detailing the `provider` it is registered by and whether it is assigned as the _default_.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots"
HTTP GET "/signalk/v2/api/vessels/self/autopilots"
```
_Example: List of registered autopilots showing that `pypilot-id` is assigned as the default._

Expand Down Expand Up @@ -146,29 +157,29 @@ If an autopilot device is not connected or unreachable, the provider for that au
## Autopilot Operations

All API operations are invoked by issuing requests to:
1. `/signalk/v2/api/vessels/self/steering/autopilots/_default/*`
1. `/signalk/v2/api/vessels/self/autopilots/_default/*`

Targets the default autopilot device.

OR

2. `/signalk/v2/api/vessels/self/steering/autopilots/{id}/*`
2. `/signalk/v2/api/vessels/self/autopilots/{id}/*`

Target the autopilot with the supplied `{id}`

_Example:_
```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/_default/state"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/_default/state"

HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/pypilot-id/mode"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/pypilot-id/mode"
```

### Retrieving Autopilot Status

To retrieve the current autopilot configuration as well as a list of available options for `state` and `mode` selections, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/steering/autopilots/{id}`.
To retrieve the current autopilot configuration as well as a list of available options for `state` and `mode` selections, submit an HTTP `GET` request to `/signalk/v2/api/vessels/self/autopilots/{id}`.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/{id}"
```
_Response:_

Expand All @@ -195,18 +206,18 @@ Where:

### Setting the Autopilot State

Autopilot state can be set by submitting an HTTP `PUT` request to the `state` endpoint containing a value from the list of available states.
Autopilot state can be set by submitting an HTTP `PUT` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/state` endpoint containing a value from the list of available states.

```typescript
HTTP PUT "/signalk/v2/api/vessels/self/steering/autopilots/{id}/state" {"value": "disabled"}
HTTP PUT "/signalk/v2/api/vessels/self/autopilots/{id}/state" {"value": "disabled"}
```

### Getting the Autopilot State

The current autopilot state can be retrieved by submitting an HTTP `GET` request to the `state` endpoint.
The current autopilot state can be retrieved by submitting an HTTP `GET` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/state` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/state"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/{id}/state"
```

_Response:_
Expand All @@ -219,18 +230,18 @@ _Response:_

### Setting the Autopilot Mode

Autopilot mode can be set by submitting an HTTP `PUT` request to the `mode` endpoint containing a value from the list of available modes.
Autopilot mode can be set by submitting an HTTP `PUT` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/mode` endpoint containing a value from the list of available modes.

```typescript
HTTP PUT "/signalk/v2/api/vessels/self/steering/autopilots/{id}/mode" {"value": "gps"}
HTTP PUT "/signalk/v2/api/vessels/self/autopilots/{id}/mode" {"value": "gps"}
```

### Getting the Autopilot Mode

The current autopilot mode can be retrieved by submitting an HTTP `GET` request to the `mode` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/mode"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/{id}/mode"
```

_Response:_
Expand All @@ -243,26 +254,26 @@ _Response:_

### Setting the Target value

Autopilot target value can be set by submitting an HTTP `PUT` request to the `target` endpoint containing the desired value in radians.
Autopilot target value can be set by submitting an HTTP `PUT` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/target` endpoint containing the desired value in degrees.

_Note: The value supplied should be a number within the valid range for the selected `mode`._

```typescript
HTTP PUT "signalk/v2/api/vessels/self/steering/autopilots/{id}/target" {"value": 1.1412}
HTTP PUT "signalk/v2/api/vessels/self/autopilots/{id}/target" {"value": 129}
```

The target value can be adjusted a +/- value by submitting an HTTP `PUT` request to the `target/adjust` endpoint with the value to add to the current `target` value in radians.
The target value can be adjusted a +/- value by submitting an HTTP `PUT` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/target/adjust` endpoint with the value to add to the current `target` value in degrees.

```typescript
HTTP PUT "signalk/v2/api/vessels/self/steering/autopilots/{id}/target/adjust" {"value": -0.1412}
HTTP PUT "signalk/v2/api/vessels/self/autopilots/{id}/target/adjust" {"value": -2}
```

### Getting the current Target value

The current autopilot target value _(in radians)_ can be retrieved by submitting an HTTP `GET` request to the `target` endpoint.
The current autopilot target value _(in degrees)_ can be retrieved by submitting an HTTP `GET` request to the `target` endpoint.

```typescript
HTTP GET "/signalk/v2/api/vessels/self/steering/autopilots/{id}/target"
HTTP GET "/signalk/v2/api/vessels/self/autopilots/{id}/target"
```

_Response:_
Expand All @@ -277,66 +288,76 @@ _Response:_

#### Engaging the autopilot

An autopilot can be engaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be engaged more generically by submitting an HTTP `POST` request to the `engage` endpoint.
An autopilot can be engaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be engaged more generically by submitting an HTTP `POST` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/engage` endpoint.

```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/engage"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/engage"
```

_Note: The resultant `state` into which the autopilot is placed will be determined by the **provider plugin** and the autopilot device it is communicating with._

#### Disengaging the autopilot

An autopilot can be disengaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be disengaged more generically by submitting an HTTP `POST` request to the `disengage` endpoint.
An autopilot can be disengaged by [setting it to a speciifc `state`](#setting-the-state) but it can also be disengaged more generically by submitting an HTTP `POST` request to the `/signalk/v2/api/vessels/self/autopilots/{id}/disengage` endpoint.

```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/disengage"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/disengage"
```

_Note: The resultant `state` into which the autopilot is placed will be determined by the **provider plugin** and the autopilot device it is communicating with._

### Perform a Tack

To send a command to the autopilot to perform a tack in the required direction, submit an HTTP `POST` request to `/tack/{direction}` where _direction_ is either `port` or `starboard`.
To send a command to the autopilot to perform a tack in the required direction, submit an HTTP `POST` request to `./autopilots/{id}/tack/{direction}` where _direction_ is either `port` or `starboard`.

_Example: Tack to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/tack/port"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/tack/port"
```

_Example: Tack to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/tack/starboard"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/tack/starboard"
```


### Perform a Gybe

To send a command to the autopilot to perform a gybe in the required direction, submit an HTTP `POST` request to `/gybe/{direction}` where _direction_ is either `port` or `starboard`.
To send a command to the autopilot to perform a gybe in the required direction, submit an HTTP `POST` request to `/signalk/v2/api/vessels/self/autopilots/{id}/gybe/{direction}` where _direction_ is either `port` or `starboard`.

_Example: Gybe to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/gybe/port"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/gybe/port"
```

_Example: Gybe to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/gybe/starboard"
HTTP POST "/signalk/v2/api/vessels/self/autopilots/{id}/gybe/starboard"
```



### Dodging / overriding
### Dodging Obstacles

To send a command to the autopilot to manually override the rudder position two (2) degrees in the requested direction in order to avoid an obstacle,
submit an HTTP `POST` request to `/dodge/{direction}` where _direction_ is either `port` or `starboard`.
To address the various methods that the `dodge` function could be invoked on pilot devices, the API provides the following endpoints to provide the widest coverage possible:

_Example: Dodge to Port_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/dodge/port"

**To enter dodge mode at the current course**
```javascript
POST /signalk/v2/api/vessels/self/autopilots/{id}/dodge
```

_Example: Gybe to Starboard_
```typescript
HTTP POST "/signalk/v2/api/vessels/self/steering/autopilots/{id}/dodge/starboard"
**To enter dodge mode and change course by 5 degrees starboard**
```javascript
PUT /signalk/v2/api/vessels/self/autopilots/{id}/dodge {"value": 5}
```

**To enter dodge mode and change course by 5 degrees port**
```javascript
PUT /signalk/v2/api/vessels/self/autopilots/{id}/dodge {"value": -5}
```

**To cancel dodge mode**
```javascript
DELETE /signalk/v2/api/vessels/self/autopilots/{id}/dodge
```
2 changes: 1 addition & 1 deletion docs/src/develop/rest-api/open_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ APIs are available via `/signalk/v2/api/<endpoint>`
|--- |--- |--- |
| [Course](./course_api.md) | Set a course, follow a route, advance to next point, etc. | `vessels/self/navigation/course` |
| [Resources](./resources_api.md) | Create, view, update and delete waypoints, routes, etc. | `resources` |
| [`Autopilot`](./autopilot_api.md) | Provide the ability to send common commands to an autopilot via a provider plugin. | `vessels/self/autopilot` |

---

Expand All @@ -23,7 +24,6 @@ APIs are available via `/signalk/v2/api/<endpoint>`
| Proposed API | Description | Endpoint |
|--- |--- |--- |
| _[`Notifications`](notifications_api.md)_ | Provide the ability to raise, update and clear notifications from multiple sources. _[View PR](https://github.com/SignalK/signalk-server/pull/1560)_| `notifications` |
| _[`Autopilot`](./autopilot_api.md)_ | Provide the ability to send common commands to an autopilot via a provider plugin. _[View PR](https://github.com/SignalK/signalk-server/pull/1596)_ | `vessels/self/steering/autopilot` |
| _[`Anchor`](./anchor_api.md)_ | Provide endpoints to perform operations and facilitate an anchor alarm. | `vessels/self/navigation/anchor` |

---
23 changes: 5 additions & 18 deletions packages/server-api/src/autopilotapi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Notification, Value } from './deltas'
import { Value } from './deltas'

export type AutopilotUpdateAttrib =
| 'mode'
Expand Down Expand Up @@ -48,22 +48,15 @@ export interface AutopilotApi {
apUpdate(
pluginId: string,
deviceId: string,
attrib: AutopilotUpdateAttrib,
value: Value
): void
apAlarm(
pluginId: string,
deviceId: string,
alarmName: AutopilotAlarm,
value: Notification
apInfo: {[path:string]: Value}
): void
}

/** @see {isAutopilotProvider} ts-auto-guard:type-guard */
export interface AutopilotProvider {
getData(deviceId: string): Promise<AutopilotInfo>
getState(deviceId: string): Promise<string>
setState(state: string, deviceId: string): Promise<boolean>
setState(state: string, deviceId: string): Promise<void>
getMode(deviceId: string): Promise<string>
setMode(mode: string, deviceId: string): Promise<void>
getTarget(deviceId: string): Promise<number>
Expand All @@ -73,7 +66,7 @@ export interface AutopilotProvider {
disengage(deviceId: string): Promise<void>
tack(direction: TackGybeDirection, deviceId: string): Promise<void>
gybe(direction: TackGybeDirection, deviceId: string): Promise<void>
dodge(direction: TackGybeDirection, deviceId: string): Promise<void>
dodge(value: number | null, deviceId: string): Promise<void>
}

export interface AutopilotStateDef {
Expand Down Expand Up @@ -101,12 +94,6 @@ export interface AutopilotProviderRegistry {
): void
autopilotUpdate(
deviceId: string,
attrib: AutopilotUpdateAttrib,
value: Value
): void
autopilotAlarm(
deviceId: string,
alarmName: AutopilotAlarm,
value: Notification
apInfo: {[path:string]: Value}
): void
}
Loading

0 comments on commit b5912ff

Please sign in to comment.