@synapticon/motion-master-client 6.0.0-alpha.81 → 6.0.0-alpha.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/generated/Api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AlStatusCode, BrakeState, Cia402Status, DcSyncStatus, DeviceDiagnostics, DeviceFile, DeviceParameter, EscRegister, EsiParseResult, FirmwareCompatibility, FirmwarePackageName, FoeErrorCode, GameLoopHealth, HardwareDescription, HrdRecording, IntegroVariant, IntegroVariantOption, MailboxErrorCode, Monitoring, ObjectDataTypeInfo, OperationModes, OutputStageResult, ParameterCacheEntry, PdoMapping, PdoMappingRequest, ProcedureListing, ProcedureRequest, ProcedureSnapshot, ProcessDataWatchdog, ProcessImageObject, SdoAbortCode, SlaveConfig, SlaveInformationInterface, UserCacheListing } from "./data-contracts.js";
|
|
1
|
+
import { AlStatusCode, AutoTuningError, AutoTuningRunRequest, AutoTuningRunResponse, AutoTuningStatus, BrakeState, Cia402Status, DcSyncStatus, DeviceDiagnostics, DeviceFile, DeviceParameter, EscRegister, EsiParseResult, FirmwareCompatibility, FirmwarePackageName, FoeErrorCode, GameLoopHealth, HardwareDescription, HrdRecording, IntegroVariant, IntegroVariantOption, MailboxErrorCode, Monitoring, ObjectDataTypeInfo, OperationModes, OutputStageResult, ParameterCacheEntry, PdoMapping, PdoMappingRequest, ProcedureListing, ProcedureRequest, ProcedureSnapshot, ProcessDataWatchdog, ProcessImageObject, SdoAbortCode, SlaveConfig, SlaveInformationInterface, UserCacheListing } from "./data-contracts.js";
|
|
2
2
|
import { HttpClient, RequestParams } from "./http-client.js";
|
|
3
3
|
export declare class Api<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
|
|
4
4
|
/**
|
|
@@ -374,6 +374,34 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
374
374
|
* @request GET:/api/log
|
|
375
375
|
*/
|
|
376
376
|
getLog: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<string, any>>;
|
|
377
|
+
/**
|
|
378
|
+
* @description Reports what Motion Master knows about the auto-tuning process. The tuning calculations run in a separate executable, which Motion Master starts at startup and reaches over loopback. That executable is downloaded by the install scripts rather than shipped in a release, so a machine may not have it — this endpoint is how a client tells the four cases apart: switched off in the configuration, not installed, installed but would not start, or running. The values are a startup snapshot. `started` says the process answered when Motion Master waited for it, not that it is alive now. Nothing polls it: a call is the honest test, and `POST /api/auto-tuning/run` makes one.
|
|
379
|
+
*
|
|
380
|
+
* @name GetAutoTuning
|
|
381
|
+
* @summary Auto-tuning process status
|
|
382
|
+
* @request GET:/api/auto-tuning
|
|
383
|
+
*/
|
|
384
|
+
getAutoTuning: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<AutoTuningStatus, any>>;
|
|
385
|
+
/**
|
|
386
|
+
* @description Forwards the request to the auto-tuning process and returns its reply unchanged. The body is a JSON object with `run`, naming the function, and `data`, holding that function's inputs — the same shape the auto-tuning program takes on its own API. **A rejected input is reported with 200 and an `error` property**, not with a 4xx. The auto-tuning program keeps 4xx and 5xx for a malformed request, an unknown function name, and a routine that threw, so a client tests for `error` in the body rather than relying on the status alone. Motion Master passes both through untouched; only 400, 502 and 503 below are its own. Measurement data travels in the body. `identify_plant_model` takes the chirp measurements as `data.csv` text, and the bode data comes back inline as `bode`, so no file is written and nothing needs a shared filesystem view. The schemas here are a copy of the auto-tuning program's own, taken from version 3.1.1, and they exist so that the generated clients are typed. That program's current description is served verbatim at `GET /api/auto-tuning/swagger.yml`, which is the authority if the two ever disagree.
|
|
387
|
+
*
|
|
388
|
+
* @name RunAutoTuning
|
|
389
|
+
* @summary Run an auto-tuning function
|
|
390
|
+
* @request POST:/api/auto-tuning/run
|
|
391
|
+
*/
|
|
392
|
+
runAutoTuning: (data: AutoTuningRunRequest, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<AutoTuningRunResponse, AutoTuningError | {
|
|
393
|
+
error: string;
|
|
394
|
+
}>>;
|
|
395
|
+
/**
|
|
396
|
+
* @description Serves the OpenAPI document the auto-tuning process carries, fetched from it on each request. The schemas under `/api/auto-tuning/run` above are a copy of these, so this is where to look when a version of the program disagrees with them.
|
|
397
|
+
*
|
|
398
|
+
* @name GetAutoTuningSpec
|
|
399
|
+
* @summary The auto-tuning program's own API description
|
|
400
|
+
* @request GET:/api/auto-tuning/swagger.yml
|
|
401
|
+
*/
|
|
402
|
+
getAutoTuningSpec: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<string, {
|
|
403
|
+
error: string;
|
|
404
|
+
}>>;
|
|
377
405
|
/**
|
|
378
406
|
* @description Returns the static catalogue of EtherCAT AL Status Codes defined in ETG.1000.6 §6.4.1. These codes appear in the alStatusCode field of the device state response when an error is present and identify the cause of the state transition failure.
|
|
379
407
|
*
|
|
@@ -467,7 +495,7 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
467
495
|
}[];
|
|
468
496
|
}[], any>>;
|
|
469
497
|
/**
|
|
470
|
-
* @description The register map of the Integro's internal (Kübler) encoder — the reference table for POST /api/devices/{slavePosition}/procedures/kuebler-register-communication, and documentation in its own right. Static: it describes the encoder type, not any connected device, so it needs no bus and no scan. Transcribed from the vendor's own draft table. Each entry carries the width, the access type, whether the encoder
|
|
498
|
+
* @description The register map of the Integro's internal (Kübler) encoder — the reference table for POST /api/devices/{slavePosition}/procedures/kuebler-register-communication, and documentation in its own right. Static: it describes the encoder type, not any connected device, so it needs no bus and no scan. Transcribed from the vendor's own draft table, then corrected against what the encoder really does: the draft calls four registers not implemented that the encoder calibration sequence reads or writes, and leaves out four more. Each entry carries the width, the access type, whether the encoder implements it, and the vendor's bit definitions verbatim, which for a bit-field register is the only place its meaning is recorded. A register the draft does not document says so in `definition`, because a reader has nowhere else to look. `format` says how to read the assembled value, because signedness is not uniform and one register is not a single number at all: `unsigned`, `signed`, `bitField` (the number means nothing on its own), or `signedHalves` — two signed 16-bit values packed into 32 bits, which register 0x3C is the only case of. `readableInOneCommand` says whether one command can carry the register, since the command's length byte caps at 4 bytes. Every register fits today, so it is true for all of them.
|
|
471
499
|
*
|
|
472
500
|
* @name GetKueblerRegisters
|
|
473
501
|
* @summary The Integro internal encoder's register map
|
|
@@ -1000,6 +1028,23 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
1000
1028
|
*/
|
|
1001
1029
|
error: string;
|
|
1002
1030
|
}>>;
|
|
1031
|
+
/**
|
|
1032
|
+
* @description Deletes `filename` from the flash of the device at `slavePosition`. **Vendor-specific despite reading like a filesystem operation.** FoE has no delete, so SOMANET firmware acts on a pseudo-file instead: reading the name `fs-remove=<filename>` removes that file. This endpoint exists so no client has to know that, and a device that is not a SOMANET drive is refused rather than probed. **A file that was not there answers 200.** The caller asked for the file to be gone, and it is. Every other FoE failure is a 500 naming the reason. The file is gone from flash immediately. Deleting `config.csv` discards the stored parameter values, so the drive falls back to its defaults on the next power cycle.
|
|
1033
|
+
*
|
|
1034
|
+
* @name DeleteDeviceFile
|
|
1035
|
+
* @summary Delete a file from a device
|
|
1036
|
+
* @request DELETE:/api/devices/{slavePosition}/files/{filename}
|
|
1037
|
+
*/
|
|
1038
|
+
deleteDeviceFile: (slavePosition: number, filename: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
|
|
1039
|
+
/** @example true */
|
|
1040
|
+
ok?: boolean;
|
|
1041
|
+
}, void | {
|
|
1042
|
+
/**
|
|
1043
|
+
* Human-readable error message from the driver
|
|
1044
|
+
* @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
|
|
1045
|
+
*/
|
|
1046
|
+
error: string;
|
|
1047
|
+
}>>;
|
|
1003
1048
|
/**
|
|
1004
1049
|
* @description Reads the raw SII EEPROM image of the device at `slavePosition` through the ESC's EEPROM-control registers and returns either the parsed structure or the raw bytes, selected by the `Accept` request header. With `Accept: application/json` (or `*\/*`, or no `Accept` header) the parsed `SlaveInformationInterface` is returned — the 128-byte fixed header plus the decoded category section (strings, general info, FMMU/Sync-Manager and PDO defaults, distributed-clock settings). With `Accept: application/octet-stream` the raw EEPROM image is returned unparsed, suitable for a hex dump or archival. EEPROM access is a control-plane operation and is most reliable while the device is in INIT or PRE-OP. String-index fields in the parsed structure (e.g. `general.nameIdx`) are 1-based references into `category.strings`.
|
|
1005
1050
|
*
|
package/dist/generated/Api.js
CHANGED
|
@@ -167,6 +167,46 @@ export class Api extends HttpClient {
|
|
|
167
167
|
method: "GET",
|
|
168
168
|
...params,
|
|
169
169
|
});
|
|
170
|
+
/**
|
|
171
|
+
* @description Reports what Motion Master knows about the auto-tuning process. The tuning calculations run in a separate executable, which Motion Master starts at startup and reaches over loopback. That executable is downloaded by the install scripts rather than shipped in a release, so a machine may not have it — this endpoint is how a client tells the four cases apart: switched off in the configuration, not installed, installed but would not start, or running. The values are a startup snapshot. `started` says the process answered when Motion Master waited for it, not that it is alive now. Nothing polls it: a call is the honest test, and `POST /api/auto-tuning/run` makes one.
|
|
172
|
+
*
|
|
173
|
+
* @name GetAutoTuning
|
|
174
|
+
* @summary Auto-tuning process status
|
|
175
|
+
* @request GET:/api/auto-tuning
|
|
176
|
+
*/
|
|
177
|
+
getAutoTuning = (params = {}) => this.request({
|
|
178
|
+
path: `/api/auto-tuning`,
|
|
179
|
+
method: "GET",
|
|
180
|
+
format: "json",
|
|
181
|
+
...params,
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* @description Forwards the request to the auto-tuning process and returns its reply unchanged. The body is a JSON object with `run`, naming the function, and `data`, holding that function's inputs — the same shape the auto-tuning program takes on its own API. **A rejected input is reported with 200 and an `error` property**, not with a 4xx. The auto-tuning program keeps 4xx and 5xx for a malformed request, an unknown function name, and a routine that threw, so a client tests for `error` in the body rather than relying on the status alone. Motion Master passes both through untouched; only 400, 502 and 503 below are its own. Measurement data travels in the body. `identify_plant_model` takes the chirp measurements as `data.csv` text, and the bode data comes back inline as `bode`, so no file is written and nothing needs a shared filesystem view. The schemas here are a copy of the auto-tuning program's own, taken from version 3.1.1, and they exist so that the generated clients are typed. That program's current description is served verbatim at `GET /api/auto-tuning/swagger.yml`, which is the authority if the two ever disagree.
|
|
185
|
+
*
|
|
186
|
+
* @name RunAutoTuning
|
|
187
|
+
* @summary Run an auto-tuning function
|
|
188
|
+
* @request POST:/api/auto-tuning/run
|
|
189
|
+
*/
|
|
190
|
+
runAutoTuning = (data, params = {}) => this.request({
|
|
191
|
+
path: `/api/auto-tuning/run`,
|
|
192
|
+
method: "POST",
|
|
193
|
+
body: data,
|
|
194
|
+
type: ContentType.Json,
|
|
195
|
+
format: "json",
|
|
196
|
+
...params,
|
|
197
|
+
});
|
|
198
|
+
/**
|
|
199
|
+
* @description Serves the OpenAPI document the auto-tuning process carries, fetched from it on each request. The schemas under `/api/auto-tuning/run` above are a copy of these, so this is where to look when a version of the program disagrees with them.
|
|
200
|
+
*
|
|
201
|
+
* @name GetAutoTuningSpec
|
|
202
|
+
* @summary The auto-tuning program's own API description
|
|
203
|
+
* @request GET:/api/auto-tuning/swagger.yml
|
|
204
|
+
*/
|
|
205
|
+
getAutoTuningSpec = (params = {}) => this.request({
|
|
206
|
+
path: `/api/auto-tuning/swagger.yml`,
|
|
207
|
+
method: "GET",
|
|
208
|
+
...params,
|
|
209
|
+
});
|
|
170
210
|
/**
|
|
171
211
|
* @description Returns the static catalogue of EtherCAT AL Status Codes defined in ETG.1000.6 §6.4.1. These codes appear in the alStatusCode field of the device state response when an error is present and identify the cause of the state transition failure.
|
|
172
212
|
*
|
|
@@ -233,7 +273,7 @@ export class Api extends HttpClient {
|
|
|
233
273
|
...params,
|
|
234
274
|
});
|
|
235
275
|
/**
|
|
236
|
-
* @description The register map of the Integro's internal (Kübler) encoder — the reference table for POST /api/devices/{slavePosition}/procedures/kuebler-register-communication, and documentation in its own right. Static: it describes the encoder type, not any connected device, so it needs no bus and no scan. Transcribed from the vendor's own draft table. Each entry carries the width, the access type, whether the encoder
|
|
276
|
+
* @description The register map of the Integro's internal (Kübler) encoder — the reference table for POST /api/devices/{slavePosition}/procedures/kuebler-register-communication, and documentation in its own right. Static: it describes the encoder type, not any connected device, so it needs no bus and no scan. Transcribed from the vendor's own draft table, then corrected against what the encoder really does: the draft calls four registers not implemented that the encoder calibration sequence reads or writes, and leaves out four more. Each entry carries the width, the access type, whether the encoder implements it, and the vendor's bit definitions verbatim, which for a bit-field register is the only place its meaning is recorded. A register the draft does not document says so in `definition`, because a reader has nowhere else to look. `format` says how to read the assembled value, because signedness is not uniform and one register is not a single number at all: `unsigned`, `signed`, `bitField` (the number means nothing on its own), or `signedHalves` — two signed 16-bit values packed into 32 bits, which register 0x3C is the only case of. `readableInOneCommand` says whether one command can carry the register, since the command's length byte caps at 4 bytes. Every register fits today, so it is true for all of them.
|
|
237
277
|
*
|
|
238
278
|
* @name GetKueblerRegisters
|
|
239
279
|
* @summary The Integro internal encoder's register map
|
|
@@ -725,6 +765,19 @@ export class Api extends HttpClient {
|
|
|
725
765
|
format: "json",
|
|
726
766
|
...params,
|
|
727
767
|
});
|
|
768
|
+
/**
|
|
769
|
+
* @description Deletes `filename` from the flash of the device at `slavePosition`. **Vendor-specific despite reading like a filesystem operation.** FoE has no delete, so SOMANET firmware acts on a pseudo-file instead: reading the name `fs-remove=<filename>` removes that file. This endpoint exists so no client has to know that, and a device that is not a SOMANET drive is refused rather than probed. **A file that was not there answers 200.** The caller asked for the file to be gone, and it is. Every other FoE failure is a 500 naming the reason. The file is gone from flash immediately. Deleting `config.csv` discards the stored parameter values, so the drive falls back to its defaults on the next power cycle.
|
|
770
|
+
*
|
|
771
|
+
* @name DeleteDeviceFile
|
|
772
|
+
* @summary Delete a file from a device
|
|
773
|
+
* @request DELETE:/api/devices/{slavePosition}/files/{filename}
|
|
774
|
+
*/
|
|
775
|
+
deleteDeviceFile = (slavePosition, filename, params = {}) => this.request({
|
|
776
|
+
path: `/api/devices/${slavePosition}/files/${filename}`,
|
|
777
|
+
method: "DELETE",
|
|
778
|
+
format: "json",
|
|
779
|
+
...params,
|
|
780
|
+
});
|
|
728
781
|
/**
|
|
729
782
|
* @description Reads the raw SII EEPROM image of the device at `slavePosition` through the ESC's EEPROM-control registers and returns either the parsed structure or the raw bytes, selected by the `Accept` request header. With `Accept: application/json` (or `*\/*`, or no `Accept` header) the parsed `SlaveInformationInterface` is returned — the 128-byte fixed header plus the decoded category section (strings, general info, FMMU/Sync-Manager and PDO defaults, distributed-clock settings). With `Accept: application/octet-stream` the raw EEPROM image is returned unparsed, suitable for a hex dump or archival. EEPROM access is a control-plane operation and is most reliable while the device is in INIT or PRE-OP. String-index fields in the parsed structure (e.g. `general.nameIdx`) are 1-based references into `category.strings`.
|
|
730
783
|
*
|
|
@@ -418,7 +418,7 @@ export interface ProgressStep {
|
|
|
418
418
|
/** @example "succeeded" */
|
|
419
419
|
status: "idle" | "running" | "succeeded" | "failed";
|
|
420
420
|
/**
|
|
421
|
-
* What the step produced, if anything — shape is per procedure. Absent when the step produced nothing. For `os-command` it is an object with `status`, `data`,
|
|
421
|
+
* What the step produced, if anything — shape is per procedure. Absent when the step produced nothing. For `os-command` it is an object with `status`, `data`, `errorCode` when the drive sent one, and `fsBuffer` when the request asked to read bulk data. For `read-object-dictionary` it is an object with `byteCount` and `values`, one entry per object with its `index`, `subindex` and `value`.
|
|
422
422
|
* @example {"status":1,"data":[1,2,3,4,5,6]}
|
|
423
423
|
*/
|
|
424
424
|
value?: any;
|
|
@@ -897,6 +897,14 @@ export interface ProcedureRequest {
|
|
|
897
897
|
* @default 10
|
|
898
898
|
*/
|
|
899
899
|
pollIntervalMs?: number;
|
|
900
|
+
/**
|
|
901
|
+
* `os-command` only: whether the command moves bulk data through the drive's fs-buffer, and which way. Most commands move none. The transfer runs while the command runs, because the drive holds the command in progress until all the data has moved, and it needs firmware 5.2 or newer. Setting a direction for a command that moves no bulk data leaves the server waiting for a transfer the drive will never start.
|
|
902
|
+
* @default "none"
|
|
903
|
+
* @example "read"
|
|
904
|
+
*/
|
|
905
|
+
fsBuffer?: "none" | "read" | "write";
|
|
906
|
+
/** `os-command` only, and required when `fsBuffer` is `write`: the bytes to send, base64-encoded into this JSON string. Rejected for the other two directions rather than ignored, so a request that names one and forgets the other is told rather than running a command that moves nothing. (Deliberately not `format: byte`, for the reason spelled out on `packageContent`.) */
|
|
907
|
+
fsBufferData?: string;
|
|
900
908
|
/**
|
|
901
909
|
* `encoder-register-communication` and `ic-mu-calibration-mode`: which of the drive's encoders to address. Encoder 1 is the encoder configured in 0x2110 and encoder 2 the one configured in 0x2112, so the ordinal picks a configuration object rather than a kind of encoder.
|
|
902
910
|
* @default 1
|
|
@@ -1724,4 +1732,275 @@ export interface EsiParseResult {
|
|
|
1724
1732
|
/** Recoverable problems in the document itself — a skipped malformed object, an unparsable value. A file with warnings still parses. Per-device assembly problems are reported on the device instead. */
|
|
1725
1733
|
warnings?: string[];
|
|
1726
1734
|
}
|
|
1735
|
+
/** What Motion Master knows about the auto-tuning process, as a startup snapshot. */
|
|
1736
|
+
export interface AutoTuningStatus {
|
|
1737
|
+
/**
|
|
1738
|
+
* The `autoTuning.enabled` setting from the configuration file.
|
|
1739
|
+
* @example true
|
|
1740
|
+
*/
|
|
1741
|
+
enabled: boolean;
|
|
1742
|
+
/**
|
|
1743
|
+
* The executable Motion Master looked for, as an absolute path.
|
|
1744
|
+
* @example "/opt/motion-master/auto-tuning"
|
|
1745
|
+
*/
|
|
1746
|
+
binaryPath: string;
|
|
1747
|
+
/**
|
|
1748
|
+
* Whether a file exists at that path.
|
|
1749
|
+
* @example true
|
|
1750
|
+
*/
|
|
1751
|
+
installed: boolean;
|
|
1752
|
+
/**
|
|
1753
|
+
* Whether the process started and answered its health endpoint. Not a liveness check: nothing polls the process after startup.
|
|
1754
|
+
* @example true
|
|
1755
|
+
*/
|
|
1756
|
+
started: boolean;
|
|
1757
|
+
/**
|
|
1758
|
+
* The version the process reported, empty unless it started. A build older than that program's version reporting starts and reports nothing, which is why an empty string here does not mean it failed.
|
|
1759
|
+
* @example "3.1.1"
|
|
1760
|
+
*/
|
|
1761
|
+
version: string;
|
|
1762
|
+
/**
|
|
1763
|
+
* The loopback port the process was told to serve on.
|
|
1764
|
+
* @example 63528
|
|
1765
|
+
*/
|
|
1766
|
+
port: number;
|
|
1767
|
+
/**
|
|
1768
|
+
* Why it is not running. Empty when it is.
|
|
1769
|
+
* @example ""
|
|
1770
|
+
*/
|
|
1771
|
+
error: string;
|
|
1772
|
+
}
|
|
1773
|
+
/** The auto-tuning program's error shape. Returned with 200 when a function rejected its inputs, and with 404 or 500 for an unknown function or an unhandled exception. */
|
|
1774
|
+
export interface AutoTuningError {
|
|
1775
|
+
error: {
|
|
1776
|
+
/** @example "A linear model can't be fit in the recorded data." */
|
|
1777
|
+
message: string;
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Transfer function coefficients, highest order first.
|
|
1782
|
+
* @example {"numerator":[1],"denominator":[0.00015,0.000206]}
|
|
1783
|
+
*/
|
|
1784
|
+
export interface PlantModel {
|
|
1785
|
+
numerator: number[];
|
|
1786
|
+
denominator: number[];
|
|
1787
|
+
}
|
|
1788
|
+
/** One controller's gains. */
|
|
1789
|
+
export interface Pid {
|
|
1790
|
+
kp?: number;
|
|
1791
|
+
ki?: number;
|
|
1792
|
+
kd?: number;
|
|
1793
|
+
}
|
|
1794
|
+
/** Controller gains. A function that tunes only the velocity loop leaves the position gains at zero. */
|
|
1795
|
+
export interface Gains {
|
|
1796
|
+
/** One controller's gains. */
|
|
1797
|
+
position?: Pid;
|
|
1798
|
+
/** One controller's gains. */
|
|
1799
|
+
velocity?: Pid;
|
|
1800
|
+
}
|
|
1801
|
+
/**
|
|
1802
|
+
* Bode diagram data, keyed by column name, every array the same length. This comes back in the response body instead of a written CSV, which is why no auto-tuning call needs a shared filesystem. A non-finite value is null.
|
|
1803
|
+
* @example {"Frequency_Hz":[0.5,1],"Plant_Mag_dB":[65.77570877159437,59.79191013147556],"Plant_Phase_deg":[-66.38766900151838,-76.55997369096534]}
|
|
1804
|
+
*/
|
|
1805
|
+
export type Bode = Record<string, (number | null)[]>;
|
|
1806
|
+
/** Drive configuration, as read from the drive. */
|
|
1807
|
+
export interface DriveConfig {
|
|
1808
|
+
vel_lp_type?: number;
|
|
1809
|
+
vel_lp_fc?: number;
|
|
1810
|
+
pos_lp_type?: number;
|
|
1811
|
+
pos_lp_fc?: number;
|
|
1812
|
+
notch_en?: number;
|
|
1813
|
+
notch_fw?: number;
|
|
1814
|
+
notch_fc?: number;
|
|
1815
|
+
notch_dp?: number;
|
|
1816
|
+
vel_ff_gain?: number;
|
|
1817
|
+
vel_ff_fc?: number;
|
|
1818
|
+
/** Winding inductance. */
|
|
1819
|
+
L?: number;
|
|
1820
|
+
/** Winding resistance. */
|
|
1821
|
+
R?: number;
|
|
1822
|
+
/** DC link voltage. */
|
|
1823
|
+
vdc?: number;
|
|
1824
|
+
current_ratio?: number;
|
|
1825
|
+
tc_kp?: number;
|
|
1826
|
+
tc_ki?: number;
|
|
1827
|
+
switch_F?: number;
|
|
1828
|
+
tc_st?: number;
|
|
1829
|
+
tc_damping?: number;
|
|
1830
|
+
software_version?: string;
|
|
1831
|
+
rated_torque?: number;
|
|
1832
|
+
max_vel_noise?: number;
|
|
1833
|
+
}
|
|
1834
|
+
/** The `data` schema depends on the value of `run`. Each variant pairs one `run` value with the inputs that function reads. `run: exit` is deliberately absent: it shuts the process down, and this endpoint refuses it with 400. */
|
|
1835
|
+
export type AutoTuningRunRequest = AutoTuneVelocityController | AutoTunePositionController | FullAutoTuneVelocityController | FullAutoTunePositionController | AutoTuneNotch | AutoTuneFeedbackFilters | ComputePositionControllerGains | IdentifyPlantModel | GeneratePlantBode;
|
|
1836
|
+
export interface AutoTuneVelocityController {
|
|
1837
|
+
run: "auto_tune_velocity_controller";
|
|
1838
|
+
data: {
|
|
1839
|
+
/** Transfer function coefficients, highest order first. */
|
|
1840
|
+
plant_model: PlantModel;
|
|
1841
|
+
/** Damping ratio. */
|
|
1842
|
+
zeta: number;
|
|
1843
|
+
/** Demanded bandwidth in Hz. */
|
|
1844
|
+
demanded_bw: number;
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
export interface AutoTunePositionController {
|
|
1848
|
+
run: "auto_tune_position_controller";
|
|
1849
|
+
data: {
|
|
1850
|
+
/** Transfer function coefficients, highest order first. */
|
|
1851
|
+
plant_model: PlantModel;
|
|
1852
|
+
/** @example "PI-P" */
|
|
1853
|
+
controller_type: string;
|
|
1854
|
+
zeta: number;
|
|
1855
|
+
/** Demanded settling time in seconds. */
|
|
1856
|
+
demanded_st: number;
|
|
1857
|
+
/** Optional. Absent means the standard tuning rule. */
|
|
1858
|
+
highFrictionGain?: number;
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
export interface FullAutoTuneVelocityController {
|
|
1862
|
+
run: "full_auto_tune_velocity_controller";
|
|
1863
|
+
data: {
|
|
1864
|
+
/** Transfer function coefficients, highest order first. */
|
|
1865
|
+
plant_model: PlantModel;
|
|
1866
|
+
/** Drive configuration, as read from the drive. */
|
|
1867
|
+
drive_config: DriveConfig;
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
export interface FullAutoTunePositionController {
|
|
1871
|
+
run: "full_auto_tune_position_controller";
|
|
1872
|
+
data: {
|
|
1873
|
+
/** Transfer function coefficients, highest order first. */
|
|
1874
|
+
plant_model: PlantModel;
|
|
1875
|
+
/** @example "PI-P" */
|
|
1876
|
+
controller_type: string;
|
|
1877
|
+
/** Drive configuration, as read from the drive. */
|
|
1878
|
+
drive_config: DriveConfig;
|
|
1879
|
+
highFriction: 0 | 1;
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
export interface AutoTuneNotch {
|
|
1883
|
+
run: "auto_tune_notch";
|
|
1884
|
+
data: {
|
|
1885
|
+
/** Transfer function coefficients, highest order first. */
|
|
1886
|
+
plant_model: PlantModel;
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
export interface AutoTuneFeedbackFilters {
|
|
1890
|
+
run: "auto_tune_feedback_filters";
|
|
1891
|
+
data: {
|
|
1892
|
+
sigma_v: number;
|
|
1893
|
+
sigma_p: number;
|
|
1894
|
+
resVel: number;
|
|
1895
|
+
resPos: number;
|
|
1896
|
+
gearRatio: number;
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
export interface ComputePositionControllerGains {
|
|
1900
|
+
run: "compute_position_controller_gains";
|
|
1901
|
+
data: {
|
|
1902
|
+
pk: number;
|
|
1903
|
+
pt: number;
|
|
1904
|
+
omega: number;
|
|
1905
|
+
alpha: number;
|
|
1906
|
+
zeta: number;
|
|
1907
|
+
/** @example "PI-P" */
|
|
1908
|
+
controller_type: string;
|
|
1909
|
+
};
|
|
1910
|
+
}
|
|
1911
|
+
/** Identifies a plant model from chirp measurements. The measurements are uploaded in `data.csv`; `data.filepath` names a file on the auto-tuning process's own machine instead, and is a fallback that Motion Master has no use for. */
|
|
1912
|
+
export interface IdentifyPlantModel {
|
|
1913
|
+
run: "identify_plant_model" | "identify_plant_model_inline";
|
|
1914
|
+
data: {
|
|
1915
|
+
/** Contents of the measurement CSV. Three columns, no header: time, torque in Nm, velocity in rad/s, sampled at 1000 Hz. */
|
|
1916
|
+
csv?: string;
|
|
1917
|
+
/** Path to that CSV instead of its contents. */
|
|
1918
|
+
filepath?: string;
|
|
1919
|
+
/** Chirp start frequency in Hz. */
|
|
1920
|
+
f0: number;
|
|
1921
|
+
/** Chirp end frequency in Hz. */
|
|
1922
|
+
f1: number;
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
/** Computes the bode data of a plant model and returns it inline. */
|
|
1926
|
+
export interface GeneratePlantBode {
|
|
1927
|
+
run: "generate_plant_bode_file" | "generate_plant_bode";
|
|
1928
|
+
data: {
|
|
1929
|
+
/** Transfer function coefficients, highest order first. */
|
|
1930
|
+
plant_model: PlantModel;
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
/** Which variant comes back depends on the request's `run`. Every result carries `duration`, the function's execution time in seconds. A function that rejected its inputs answers with `AutoTuningError` and status 200. */
|
|
1934
|
+
export type AutoTuningRunResponse = GainsResult | FullVelocityResult | FullPositionResult | NotchResult | FeedbackFiltersResult | IdentifyPlantModelResult | BodeResult | AutoTuningError;
|
|
1935
|
+
export interface GainsResult {
|
|
1936
|
+
/** Controller gains. A function that tunes only the velocity loop leaves the position gains at zero. */
|
|
1937
|
+
gains?: Gains;
|
|
1938
|
+
duration?: number;
|
|
1939
|
+
}
|
|
1940
|
+
export interface FullVelocityResult {
|
|
1941
|
+
/** Controller gains. A function that tunes only the velocity loop leaves the position gains at zero. */
|
|
1942
|
+
gains?: Gains;
|
|
1943
|
+
demanded_bw?: number;
|
|
1944
|
+
demanded_zeta?: number;
|
|
1945
|
+
/** Stability margins and closed-loop metrics. */
|
|
1946
|
+
state?: {
|
|
1947
|
+
gm?: number;
|
|
1948
|
+
pm?: number;
|
|
1949
|
+
msens?: number;
|
|
1950
|
+
act_bw?: number;
|
|
1951
|
+
vel_cl?: number;
|
|
1952
|
+
noise_resp?: number;
|
|
1953
|
+
max_KS?: number;
|
|
1954
|
+
};
|
|
1955
|
+
duration?: number;
|
|
1956
|
+
}
|
|
1957
|
+
export interface FullPositionResult {
|
|
1958
|
+
/** Controller gains. A function that tunes only the velocity loop leaves the position gains at zero. */
|
|
1959
|
+
gains?: Gains;
|
|
1960
|
+
demanded_st?: number;
|
|
1961
|
+
demanded_zeta?: number;
|
|
1962
|
+
highFrictionGain?: number;
|
|
1963
|
+
/** Stability margins and closed-loop metrics, position and velocity loop. */
|
|
1964
|
+
state?: {
|
|
1965
|
+
gm_p?: number;
|
|
1966
|
+
pm_p?: number;
|
|
1967
|
+
msens_p?: number;
|
|
1968
|
+
gm_v?: number;
|
|
1969
|
+
pm_v?: number;
|
|
1970
|
+
msens_v?: number;
|
|
1971
|
+
noise_resp?: number;
|
|
1972
|
+
max_KS?: number;
|
|
1973
|
+
bw_p?: number;
|
|
1974
|
+
bw_v?: number;
|
|
1975
|
+
act_st?: number;
|
|
1976
|
+
pos_cl?: number;
|
|
1977
|
+
};
|
|
1978
|
+
duration?: number;
|
|
1979
|
+
}
|
|
1980
|
+
export interface NotchResult {
|
|
1981
|
+
notch_en?: boolean;
|
|
1982
|
+
notch_fc?: number | null;
|
|
1983
|
+
notch_fw?: number | null;
|
|
1984
|
+
notch_dp?: number | null;
|
|
1985
|
+
duration?: number;
|
|
1986
|
+
}
|
|
1987
|
+
export interface FeedbackFiltersResult {
|
|
1988
|
+
/** Velocity feedback filter cut-off in Hz. */
|
|
1989
|
+
fcv?: number;
|
|
1990
|
+
/** Position feedback filter cut-off in Hz. */
|
|
1991
|
+
fcp?: number;
|
|
1992
|
+
duration?: number;
|
|
1993
|
+
}
|
|
1994
|
+
export interface IdentifyPlantModelResult {
|
|
1995
|
+
numerators?: number[];
|
|
1996
|
+
denominators?: number[];
|
|
1997
|
+
/** Bode diagram data, keyed by column name, every array the same length. This comes back in the response body instead of a written CSV, which is why no auto-tuning call needs a shared filesystem. A non-finite value is null. */
|
|
1998
|
+
bode?: Bode;
|
|
1999
|
+
duration?: number;
|
|
2000
|
+
}
|
|
2001
|
+
export interface BodeResult {
|
|
2002
|
+
/** Bode diagram data, keyed by column name, every array the same length. This comes back in the response body instead of a written CSV, which is why no auto-tuning call needs a shared filesystem. A non-finite value is null. */
|
|
2003
|
+
bode?: Bode;
|
|
2004
|
+
duration?: number;
|
|
2005
|
+
}
|
|
1727
2006
|
export {};
|
|
@@ -19,6 +19,7 @@ type MonitoringListener = (rows: MonitoringBatch) => void;
|
|
|
19
19
|
type NotificationListener = (data: unknown) => void;
|
|
20
20
|
type ProgressListener = (data: unknown) => void;
|
|
21
21
|
type StateListener = (state: ReadyState) => void;
|
|
22
|
+
export declare const NOTIFICATION_TOPIC = "notifications";
|
|
22
23
|
export interface WebSocketLike {
|
|
23
24
|
readyState: number;
|
|
24
25
|
send(data: string): void;
|
|
@@ -3,12 +3,20 @@
|
|
|
3
3
|
// progress, and client->server topic subscribe/unsubscribe. It owns reconnection, multiplexes
|
|
4
4
|
// per-topic subscriptions over the one socket (ref-counted: subscribe on the first listener,
|
|
5
5
|
// unsubscribe on the last, re-subscribe everything on reconnect), and routes inbound frames by
|
|
6
|
-
// type.
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// type. Nothing arrives until something is subscribed: `subscribe(topic, cb)` for one monitoring's
|
|
7
|
+
// batches, `onNotification(cb)` for every server notification — the latter is one shared topic, so
|
|
8
|
+
// a single subscription covers events added in a later server version. It is isomorphic: the
|
|
9
|
+
// browser global `WebSocket` is used by default, and any compatible implementation (e.g. the Node
|
|
10
|
+
// `ws` package) can be injected — there is no hard dependency on either, so the package stays
|
|
11
|
+
// usable in both environments.
|
|
9
12
|
/// The numeric `readyState` value a WebSocket reports when it is open. Hard-coded (rather than read
|
|
10
13
|
/// off a global) so the client never depends on a particular `WebSocket` implementation's statics.
|
|
11
14
|
const WS_OPEN = 1;
|
|
15
|
+
/// The one topic every server notification is published to. One topic rather than one per event, so
|
|
16
|
+
/// a client subscribes once and keeps receiving events added in a later server version — uWebSockets
|
|
17
|
+
/// matches topic names exactly, with no wildcard, so there is no way to ask for "all of them".
|
|
18
|
+
/// Events are told apart by `data.event`, which is kebab-case.
|
|
19
|
+
export const NOTIFICATION_TOPIC = 'notifications';
|
|
12
20
|
export class WebSocketConnection {
|
|
13
21
|
url;
|
|
14
22
|
WebSocketImpl;
|
|
@@ -69,6 +77,9 @@ export class WebSocketConnection {
|
|
|
69
77
|
for (const topic of this.topicListeners.keys()) {
|
|
70
78
|
this.send({ subscribe: topic });
|
|
71
79
|
}
|
|
80
|
+
if (this.notificationListeners.size > 0) {
|
|
81
|
+
this.send({ subscribe: NOTIFICATION_TOPIC });
|
|
82
|
+
}
|
|
72
83
|
};
|
|
73
84
|
socket.onmessage = (event) => this.route(event.data);
|
|
74
85
|
socket.onclose = () => this.handleDisconnect();
|
|
@@ -117,13 +128,21 @@ export class WebSocketConnection {
|
|
|
117
128
|
}
|
|
118
129
|
};
|
|
119
130
|
}
|
|
120
|
-
/// Registers a listener for server notifications (e.g. `{ event: '
|
|
121
|
-
///
|
|
131
|
+
/// Registers a listener for server notifications (e.g. `{ event: 'short-working-counter' }`). Every
|
|
132
|
+
/// notification arrives on one topic, so the first listener subscribes and the last to leave
|
|
133
|
+
/// unsubscribes — the same ref-counting `subscribe` uses. Connects lazily. Returns a removal
|
|
134
|
+
/// function.
|
|
122
135
|
onNotification(listener) {
|
|
136
|
+
if (this.notificationListeners.size === 0) {
|
|
137
|
+
this.send({ subscribe: NOTIFICATION_TOPIC });
|
|
138
|
+
}
|
|
123
139
|
this.notificationListeners.add(listener);
|
|
124
140
|
this.connect();
|
|
125
141
|
return () => {
|
|
126
142
|
this.notificationListeners.delete(listener);
|
|
143
|
+
if (this.notificationListeners.size === 0) {
|
|
144
|
+
this.send({ unsubscribe: NOTIFICATION_TOPIC });
|
|
145
|
+
}
|
|
127
146
|
};
|
|
128
147
|
}
|
|
129
148
|
/// Registers a listener for procedure progress messages (reserved; fires once the backend ships
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapticon/motion-master-client",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.83",
|
|
4
4
|
"description": "Isomorphic TypeScript client for Motion Master: the generated HTTP API client, the WebSocket connection, and helpers.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|