motion-master-client 0.0.323 → 0.0.325
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/package.json +1 -1
- package/src/api.js +30 -0
- package/src/api.js.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/limited-range-system-identification.d.ts +80 -0
- package/src/lib/limited-range-system-identification.js +302 -0
- package/src/lib/limited-range-system-identification.js.map +1 -0
- package/src/lib/motion-master-req-res-client.d.ts +39 -1
- package/src/lib/motion-master-req-res-client.js +67 -3
- package/src/lib/motion-master-req-res-client.js.map +1 -1
- package/src/lib/smm-od-v2.json +4 -4
- package/src/lib/smm.js +5 -0
- package/src/lib/smm.js.map +1 -1
- package/src/lib/util.d.ts +30 -0
- package/src/lib/util.js +31 -1
- package/src/lib/util.js.map +1 -1
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LimitedRangeSystemIdentification = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const rxjs_1 = require("rxjs");
|
|
6
|
+
const os_command_1 = require("./os-command");
|
|
7
|
+
const cia402_1 = require("./cia402");
|
|
8
|
+
const util_1 = require("./util");
|
|
9
|
+
const device_1 = require("./device");
|
|
10
|
+
/**
|
|
11
|
+
* Formats a number as a hexadecimal string, prefixed with `0x`.
|
|
12
|
+
*
|
|
13
|
+
* @param value - The numeric value to format.
|
|
14
|
+
* @returns The hexadecimal string representation of the value.
|
|
15
|
+
*/
|
|
16
|
+
function hex(value) {
|
|
17
|
+
return `0x${value === null || value === void 0 ? void 0 : value.toString(16).toUpperCase()}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Performs a limited-range system identification procedure on a device.
|
|
21
|
+
*
|
|
22
|
+
* This class safely executes the system identification process while preserving
|
|
23
|
+
* the device's original configuration (PID parameters, encoder settings, position
|
|
24
|
+
* feedback filter). It emits notifications about progress and status updates, which
|
|
25
|
+
* can be displayed in a UI or logged for debugging.
|
|
26
|
+
*/
|
|
27
|
+
class LimitedRangeSystemIdentification {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a new instance of the limited-range system identification routine.
|
|
30
|
+
*
|
|
31
|
+
* @param client - The Motion Master client used for communication with the device.
|
|
32
|
+
* @param deviceRef - A reference to the target device.
|
|
33
|
+
* @param options - Configuration options for the procedure.
|
|
34
|
+
*/
|
|
35
|
+
constructor(client, deviceRef, options = {
|
|
36
|
+
hrdStreamingDuration: 4000,
|
|
37
|
+
modesOfOperation: cia402_1.ModesOfOperation.CYCLIC_SYNC_POSITION_MODE,
|
|
38
|
+
rangeLimitEff: 10000,
|
|
39
|
+
rangeLimitMin: 1000,
|
|
40
|
+
signalType: os_command_1.SystemIdentificationOsCommandSignalType.LOGARITHMIC_WITH_AMPLITUDE_MODULATION,
|
|
41
|
+
startFrequency: 1000,
|
|
42
|
+
startProcedure: os_command_1.SystemIdentificationOsCommandStartProcedure.WAIT_FOR_HRD_STREAMING_TO_START,
|
|
43
|
+
targetAmplitude: 300,
|
|
44
|
+
targetFrequency: 100000,
|
|
45
|
+
transitionTime: 3000,
|
|
46
|
+
}) {
|
|
47
|
+
this.client = client;
|
|
48
|
+
this.deviceRef = deviceRef;
|
|
49
|
+
this.options = options;
|
|
50
|
+
/**
|
|
51
|
+
* Emits status and progress messages during the procedure.
|
|
52
|
+
* Subscribers can display these messages in a UI or log them.
|
|
53
|
+
*/
|
|
54
|
+
this.notifications$ = new rxjs_1.Subject();
|
|
55
|
+
/**
|
|
56
|
+
* Indicates whether the system identification procedure is currently running.
|
|
57
|
+
*/
|
|
58
|
+
this.isRunning = false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Starts the limited-range system identification procedure.
|
|
62
|
+
*
|
|
63
|
+
* This method:
|
|
64
|
+
* - Ensures the device is in a safe state.
|
|
65
|
+
* - Computes and sets initial PID values.
|
|
66
|
+
* - Starts data monitoring for position feedback.
|
|
67
|
+
* - Runs the chirp signal on the device.
|
|
68
|
+
* - Computes the plant model without the chirp signal.
|
|
69
|
+
* - Restores all device settings to their original values.
|
|
70
|
+
*
|
|
71
|
+
* Emits notifications to `notifications$` for each major step and error.
|
|
72
|
+
*
|
|
73
|
+
* @throws Will throw an error if any of the device requests fail.
|
|
74
|
+
*/
|
|
75
|
+
start() {
|
|
76
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
// Small delay to ensure subscribers to notifications$ are ready
|
|
78
|
+
yield (0, util_1.resolveAfter)(1);
|
|
79
|
+
// Prevent concurrent executions of the procedure
|
|
80
|
+
if (this.isRunning) {
|
|
81
|
+
this.notifications$.next('Limited Range System Identification is already running.');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Mark the procedure as running
|
|
85
|
+
this.isRunning = true;
|
|
86
|
+
// Validate and adjust HRD streaming duration if necessary
|
|
87
|
+
if (this.options.hrdStreamingDuration < this.options.transitionTime) {
|
|
88
|
+
this.notifications$.next(`Warning: hrdStreamingDuration (${this.options.hrdStreamingDuration} ms) is shorter than transitionTime (${this.options.transitionTime} ms). Increasing hrdStreamingDuration by 1 second to ensure proper timing.`);
|
|
89
|
+
this.options.hrdStreamingDuration = this.options.transitionTime + 1000; // 1-second buffer
|
|
90
|
+
}
|
|
91
|
+
// Ensure the required Modes of Operation is set
|
|
92
|
+
if (this.options.modesOfOperation !== cia402_1.ModesOfOperation.CYCLIC_SYNC_POSITION_MODE) {
|
|
93
|
+
this.notifications$.next(`Warning: modesOfOperation is set to ${this.options.modesOfOperation}, but CYCLIC_SYNC_POSITION_MODE (8) is required for this procedure. Applying the required mode automatically.`);
|
|
94
|
+
this.options.modesOfOperation = cia402_1.ModesOfOperation.CYCLIC_SYNC_POSITION_MODE;
|
|
95
|
+
}
|
|
96
|
+
// Ensure the required Start Procedure is set
|
|
97
|
+
if (this.options.startProcedure !== os_command_1.SystemIdentificationOsCommandStartProcedure.WAIT_FOR_HRD_STREAMING_TO_START) {
|
|
98
|
+
this.notifications$.next(`Warning: startProcedure is currently ${this.options.startProcedure}, but WAIT_FOR_HRD_STREAMING_TO_START (2) is required. Setting the correct start procedure automatically.`);
|
|
99
|
+
this.options.startProcedure = os_command_1.SystemIdentificationOsCommandStartProcedure.WAIT_FOR_HRD_STREAMING_TO_START;
|
|
100
|
+
}
|
|
101
|
+
// Variables to hold original configurations for restoration later
|
|
102
|
+
let encCom;
|
|
103
|
+
let encPos;
|
|
104
|
+
const dataMonitoring = this.client.createDataMonitoring([[this.deviceRef, 0x6064, 0x00]], 50000); // 50 ms interval
|
|
105
|
+
let positionFeedbackFilterType;
|
|
106
|
+
let pKp;
|
|
107
|
+
let pKi;
|
|
108
|
+
let pKd;
|
|
109
|
+
let pCtrlStrategy;
|
|
110
|
+
try {
|
|
111
|
+
// Ensure the drive is in the "Switch On Disabled" state before any motion commands
|
|
112
|
+
this.notifications$.next('Transitioning to "Switch On Disabled" state...');
|
|
113
|
+
yield this.client.request.transitionToCia402State(this.deviceRef, cia402_1.Cia402State.SWITCH_ON_DISABLED);
|
|
114
|
+
this.notifications$.next('"Switch On Disabled" state reached.');
|
|
115
|
+
// Compute the feed constant required for motion control
|
|
116
|
+
this.notifications$.next('Computing feed constant...');
|
|
117
|
+
const feedConstant = yield (0, rxjs_1.lastValueFrom)(this.client.request.computeFeedConstant(this.deviceRef));
|
|
118
|
+
this.notifications$.next(`Feed constant computed: ${feedConstant}`);
|
|
119
|
+
// Disable the position feedback filter
|
|
120
|
+
this.notifications$.next('Disabling the position feedback filter...');
|
|
121
|
+
positionFeedbackFilterType = yield this.client.request.upload(this.deviceRef, 0x2022, 0x01);
|
|
122
|
+
yield this.client.request.download(this.deviceRef, 0x2022, 0x01, 0);
|
|
123
|
+
this.notifications$.next('Position feedback filter disabled.');
|
|
124
|
+
// Retrieve encoder ordinal values for commutation (ENC_COM) and position (ENC_POS) configurations
|
|
125
|
+
this.notifications$.next('Retrieving encoder configurations...');
|
|
126
|
+
encCom = yield this.client.request.upload(this.deviceRef, 0x2010, 0x0c);
|
|
127
|
+
encPos = yield this.client.request.upload(this.deviceRef, 0x2012, 0x09);
|
|
128
|
+
this.notifications$.next(`Encoder configurations retrieved: ENC_COM = ${encCom}, ENC_POS = ${encPos}`);
|
|
129
|
+
// If ENC_COM and ENC_POS do not match, update ENC_POS to match ENC_COM
|
|
130
|
+
if (encCom !== encPos) {
|
|
131
|
+
this.notifications$.next('Encoder configurations do not match. Updating ENC_POS to match ENC_COM...');
|
|
132
|
+
yield this.client.request.download(this.deviceRef, 0x2012, 0x09, encCom);
|
|
133
|
+
this.notifications$.next('ENC_POS updated to match ENC_COM.');
|
|
134
|
+
}
|
|
135
|
+
// Retrieve the encoder resolution based on the ENC_COM configuration
|
|
136
|
+
const encConfigObjIdx = encCom === 1 ? 0x2110 : 0x2112;
|
|
137
|
+
this.notifications$.next(`Getting the encoder resolution from ${hex(encConfigObjIdx)}...`);
|
|
138
|
+
const resolution = yield this.client.request.upload(this.deviceRef, encConfigObjIdx, 0x03);
|
|
139
|
+
this.notifications$.next(`Encoder resolution: ${resolution}`);
|
|
140
|
+
// Calculate adjusted limit range min based on feed constant and encoder resolution
|
|
141
|
+
this.notifications$.next('Calculating limit range based on feed constant and resolution...');
|
|
142
|
+
const rangeLimitEff = this.options.rangeLimitEff;
|
|
143
|
+
// feed constant is not disabled and greater than resolution
|
|
144
|
+
const ratio = feedConstant !== 0xffffffff && feedConstant > resolution ? feedConstant / resolution : 1;
|
|
145
|
+
const rangeLimitMin = Math.round(this.options.rangeLimitMin * ratio);
|
|
146
|
+
this.notifications$.next(`Adjusted range limit: min=${rangeLimitMin}, eff=${rangeLimitEff}`);
|
|
147
|
+
// Retrieve the PID controller parameters
|
|
148
|
+
this.notifications$.next('Retrieving the PID values...');
|
|
149
|
+
[pKp, pKi, pKd, pCtrlStrategy] = (yield this.client.request.uploadMany([
|
|
150
|
+
[this.deviceRef, 0x2012, 0x01],
|
|
151
|
+
[this.deviceRef, 0x2012, 0x02],
|
|
152
|
+
[this.deviceRef, 0x2012, 0x03],
|
|
153
|
+
[this.deviceRef, 0x2002, 0x00],
|
|
154
|
+
]));
|
|
155
|
+
this.notifications$.next(`PID values retrieved: Kp=${pKp}, Ki=${pKi}, Kd=${pKd}, CtrlStrategy=${pCtrlStrategy}`);
|
|
156
|
+
// Retrieve the maximum torque value from the drive
|
|
157
|
+
this.notifications$.next('Retrieving the maximum torque value...');
|
|
158
|
+
const maxTorque = yield this.client.request.upload(this.deviceRef, 0x6072, 0x00);
|
|
159
|
+
this.notifications$.next(`Maximum torque value retrieved: ${maxTorque}`);
|
|
160
|
+
// Compute the initial kp value and xi squared based on the retrieved parameters
|
|
161
|
+
this.notifications$.next('Computing the initial kp value and xi squared...');
|
|
162
|
+
let kpInit;
|
|
163
|
+
let xiSquared;
|
|
164
|
+
if (feedConstant === 0xffffffff) {
|
|
165
|
+
xiSquared = Math.min(maxTorque, 1000 * Math.sqrt(rangeLimitEff / rangeLimitMin)) * rangeLimitEff;
|
|
166
|
+
kpInit = xiSquared / Math.pow(rangeLimitEff, 2);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
xiSquared =
|
|
170
|
+
((Math.min(maxTorque, 1000 * Math.sqrt(rangeLimitEff / rangeLimitMin)) * rangeLimitEff) / feedConstant) *
|
|
171
|
+
resolution;
|
|
172
|
+
kpInit = xiSquared / Math.pow((rangeLimitEff / feedConstant) * resolution, 2);
|
|
173
|
+
}
|
|
174
|
+
this.notifications$.next(`Initial kp value: ${kpInit}, xi squared: ${xiSquared}`);
|
|
175
|
+
// Set the initial PID controller parameters for the procedure
|
|
176
|
+
this.notifications$.next('Setting initial PID values...');
|
|
177
|
+
yield this.client.request.downloadMany([
|
|
178
|
+
[this.deviceRef, 0x2012, 1, kpInit],
|
|
179
|
+
[this.deviceRef, 0x2012, 2, 0],
|
|
180
|
+
[this.deviceRef, 0x2012, 3, 0],
|
|
181
|
+
[this.deviceRef, 0x2002, 0, 1],
|
|
182
|
+
]);
|
|
183
|
+
this.notifications$.next('Initial PID values set.');
|
|
184
|
+
// Force an on-demand parameters update to apply all settings
|
|
185
|
+
this.notifications$.next('Forcing on-demand parameters update...');
|
|
186
|
+
yield this.client.request.forceOnDemandParametersUpdate(this.deviceRef);
|
|
187
|
+
this.notifications$.next('On-demand parameters update forced.');
|
|
188
|
+
// Start data monitoring for position actual value (0x6064:00) and update Kp based on position error
|
|
189
|
+
this.notifications$.next('Starting data monitoring for position actual value...');
|
|
190
|
+
const posRef = yield this.client.request.upload(this.deviceRef, 0x6064, 0x00);
|
|
191
|
+
dataMonitoring
|
|
192
|
+
.start()
|
|
193
|
+
.pipe(
|
|
194
|
+
// Convert each emitted actual position into a download request to update the position loop Kp,
|
|
195
|
+
// ignoring new emissions until the previous request completes
|
|
196
|
+
(0, rxjs_1.exhaustMap)((data) => {
|
|
197
|
+
const posAct = data[0];
|
|
198
|
+
const e = posRef - posAct;
|
|
199
|
+
let kp;
|
|
200
|
+
if (feedConstant === 0xffffffff) {
|
|
201
|
+
kp = xiSquared / Math.pow(Math.max(rangeLimitEff - Math.abs(e), 1), 2);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
kp = xiSquared / Math.pow((Math.max(rangeLimitEff - Math.abs(e), 1) / feedConstant) * resolution, 2);
|
|
205
|
+
}
|
|
206
|
+
return (0, rxjs_1.from)(this.client.request.download(this.deviceRef, 0x2012, 0x01, kp));
|
|
207
|
+
}))
|
|
208
|
+
.subscribe();
|
|
209
|
+
this.notifications$.next('Data monitoring started.');
|
|
210
|
+
// Read the current position and set it as the target position to prevent sudden movement
|
|
211
|
+
this.notifications$.next('Setting current position as target position...');
|
|
212
|
+
const positionActualValue = yield this.client.request.upload(this.deviceRef, 0x6064, 0x00);
|
|
213
|
+
yield this.client.request.download(this.deviceRef, 0x607a, 0x00, positionActualValue);
|
|
214
|
+
this.notifications$.next(`Target position set to ${positionActualValue}.`);
|
|
215
|
+
// Run the chirp signal on the device
|
|
216
|
+
this.notifications$.next('Running the chirp signal...');
|
|
217
|
+
yield (0, rxjs_1.lastValueFrom)(this.client.request.runChirpSignal(this.deviceRef, this.options));
|
|
218
|
+
this.notifications$.next('Chirp signal procedure completed.');
|
|
219
|
+
// Stop data monitoring
|
|
220
|
+
this.notifications$.next('Stopping data monitoring...');
|
|
221
|
+
dataMonitoring.stop();
|
|
222
|
+
this.notifications$.next('Data monitoring stopped.');
|
|
223
|
+
// Start the system identification procedure without the chirp signal in order to only compute the plant model
|
|
224
|
+
this.notifications$.next('Starting system identification procedure on Motion Master to compute plant model...');
|
|
225
|
+
const deviceRefObj = (0, device_1.makeDeviceRefObj)(this.deviceRef);
|
|
226
|
+
const props = Object.assign(Object.assign({}, deviceRefObj), { skipChirpSignal: true, nextGenSysId: true, durationSeconds: this.options.transitionTime / 1000, endFrequency: this.options.targetFrequency / 1000, startFrequency: this.options.startFrequency / 1000, torqueAmplitude: this.options.targetAmplitude });
|
|
227
|
+
yield (0, rxjs_1.lastValueFrom)(this.client.request.startSystemIdentification(props, 10000));
|
|
228
|
+
this.notifications$.next('Computing plant model completed.');
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
this.notifications$.next(`Error during procedure: ${error instanceof Error ? error.message : error}`);
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
// Mark the procedure as not running
|
|
236
|
+
this.isRunning = false;
|
|
237
|
+
// Stop data monitoring
|
|
238
|
+
this.notifications$.next('Stopping data monitoring...');
|
|
239
|
+
dataMonitoring.stop();
|
|
240
|
+
this.notifications$.next('Data monitoring stopped.');
|
|
241
|
+
// Ensure the drive is in the "Switch On Disabled" after the procedure
|
|
242
|
+
this.notifications$.next('Transitioning to "Switch On Disabled" state...');
|
|
243
|
+
try {
|
|
244
|
+
yield this.client.request.transitionToCia402State(this.deviceRef, cia402_1.Cia402State.SWITCH_ON_DISABLED);
|
|
245
|
+
this.notifications$.next('"Switch On Disabled" state reached.');
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
this.notifications$.next(`Failed to transition to "Switch On Disabled": ${err instanceof Error ? err.message : err}`);
|
|
249
|
+
}
|
|
250
|
+
// Restore original ENC_POS configuration if it was changed
|
|
251
|
+
if (encCom !== undefined && encPos !== undefined && encCom !== encPos) {
|
|
252
|
+
this.notifications$.next(`Restoring original ENC_POS configuration ${encPos}...`);
|
|
253
|
+
try {
|
|
254
|
+
yield this.client.request.download(this.deviceRef, 0x2012, 0x09, encPos);
|
|
255
|
+
this.notifications$.next('ENC_POS configuration restored.');
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.notifications$.next(`Failed to restore ENC_POS: ${err instanceof Error ? err.message : err}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Restore the position feedback filter if it was changed
|
|
262
|
+
if (positionFeedbackFilterType !== undefined && positionFeedbackFilterType !== 0) {
|
|
263
|
+
this.notifications$.next('Restoring the position feedback filter...');
|
|
264
|
+
try {
|
|
265
|
+
yield this.client.request.download(this.deviceRef, 0x2022, 0x01, positionFeedbackFilterType);
|
|
266
|
+
this.notifications$.next('Position feedback filter restored.');
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
this.notifications$.next(`Failed to restore position feedback filter: ${err instanceof Error ? err.message : err}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Restore the original PID controller parameters
|
|
273
|
+
if (pKp !== undefined && pKi !== undefined && pKd !== undefined && pCtrlStrategy !== undefined) {
|
|
274
|
+
this.notifications$.next('Restoring original PID values...');
|
|
275
|
+
try {
|
|
276
|
+
yield this.client.request.downloadMany([
|
|
277
|
+
[this.deviceRef, 0x2012, 0x01, pKp],
|
|
278
|
+
[this.deviceRef, 0x2012, 0x02, pKi],
|
|
279
|
+
[this.deviceRef, 0x2012, 0x03, pKd],
|
|
280
|
+
[this.deviceRef, 0x2002, 0x00, pCtrlStrategy],
|
|
281
|
+
]);
|
|
282
|
+
this.notifications$.next('Original PID values restored.');
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
this.notifications$.next(`Failed to restore PID values: ${err instanceof Error ? err.message : err}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Force an on-demand parameters update to apply all restored settings
|
|
289
|
+
this.notifications$.next('Forcing on-demand parameters update...');
|
|
290
|
+
try {
|
|
291
|
+
yield this.client.request.forceOnDemandParametersUpdate(this.deviceRef);
|
|
292
|
+
this.notifications$.next('On-demand parameters update forced.');
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
this.notifications$.next(`Failed to force on-demand parameters update: ${err instanceof Error ? err.message : err}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
exports.LimitedRangeSystemIdentification = LimitedRangeSystemIdentification;
|
|
302
|
+
//# sourceMappingURL=limited-range-system-identification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limited-range-system-identification.js","sourceRoot":"","sources":["../../../../../libs/motion-master-client/src/lib/limited-range-system-identification.ts"],"names":[],"mappings":"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"}
|
|
@@ -1258,9 +1258,29 @@ export declare class MotionMasterReqResClient {
|
|
|
1258
1258
|
*/
|
|
1259
1259
|
factoryReset(deviceRef: DeviceRef, filesToKeep?: string[], installEmptyFirmware?: boolean, reloadFirmware?: boolean): Observable<RequestStatusMessage>;
|
|
1260
1260
|
/**
|
|
1261
|
-
* Computes the Feed Constant
|
|
1261
|
+
* Computes the Feed Constant for a given device.
|
|
1262
|
+
*
|
|
1263
|
+
* The Feed Constant is calculated as the quotient of:
|
|
1264
|
+
* - `0x6092:01`: Feed
|
|
1265
|
+
* - `0x6092:02`: Shaft Revolutions
|
|
1266
|
+
*
|
|
1267
|
+
* @param deviceRef - Reference to the device for which the Feed Constant is computed.
|
|
1268
|
+
* @param requestTimeout - Optional timeout in milliseconds for the parameter request (default: 5000).
|
|
1269
|
+
* @returns An Observable that emits the computed Feed Constant as a number.
|
|
1262
1270
|
*/
|
|
1263
1271
|
computeFeedConstant(deviceRef: DeviceRef, requestTimeout?: number): Observable<number>;
|
|
1272
|
+
/**
|
|
1273
|
+
* Computes the Gear Ratio for a given device.
|
|
1274
|
+
*
|
|
1275
|
+
* The Gear Ratio is calculated as the quotient of:
|
|
1276
|
+
* - Gear Ratio Numerator (`0x6091:01` – Motor Revolutions)
|
|
1277
|
+
* - Gear Ratio Denominator (`0x6091:02` – Shaft Revolutions)
|
|
1278
|
+
*
|
|
1279
|
+
* @param deviceRef - Reference to the device for which the Gear Ratio is computed.
|
|
1280
|
+
* @param requestTimeout - Optional timeout in milliseconds for the parameter request (default: 5000).
|
|
1281
|
+
* @returns An Observable that emits the computed Gear Ratio as a number.
|
|
1282
|
+
*/
|
|
1283
|
+
computeGearRatio(deviceRef: DeviceRef, requestTimeout?: number): Observable<number>;
|
|
1264
1284
|
/**
|
|
1265
1285
|
* Save the modified parameter values to the config.csv file so that they are used the next time the device is power cycled.
|
|
1266
1286
|
* The configuration is saved using the 0x1010: Store parameters object.
|
|
@@ -2099,4 +2119,22 @@ export declare class MotionMasterReqResClient {
|
|
|
2099
2119
|
* will also be executed.
|
|
2100
2120
|
*/
|
|
2101
2121
|
runChirpSignal(deviceRef: DeviceRef, options: ChirpSignalOptions): Observable<number[][]>;
|
|
2122
|
+
/**
|
|
2123
|
+
* Reads the motor and shaft revolutions from a device and calculates the gear ratio.
|
|
2124
|
+
*
|
|
2125
|
+
* The gear ratio is defined as the number of motor revolutions per one shaft revolution:
|
|
2126
|
+
*
|
|
2127
|
+
* gearRatio = motorRev / shaftRev
|
|
2128
|
+
*
|
|
2129
|
+
* If either motorRev or shaftRev is zero or negative, the function returns a default value of 1.
|
|
2130
|
+
*
|
|
2131
|
+
* @param deviceRef - Reference to the device from which to read the values.
|
|
2132
|
+
* @returns A Promise that resolves to the gear ratio (positive number). Returns 1 if the readings are invalid.
|
|
2133
|
+
*
|
|
2134
|
+
* @remarks
|
|
2135
|
+
* - Both motorRev and shaftRev are read via `upload()` from the device object dictionary at index 0x6091.
|
|
2136
|
+
* - Ensure that `upload()` returns numeric values and not raw buffers.
|
|
2137
|
+
* - This function assumes positive values; a negative value may indicate an error or reversed rotation.
|
|
2138
|
+
*/
|
|
2139
|
+
getGearRatio(deviceRef: DeviceRef): Promise<number>;
|
|
2102
2140
|
}
|
|
@@ -1863,6 +1863,7 @@ class MotionMasterReqResClient {
|
|
|
1863
1863
|
if (content) {
|
|
1864
1864
|
try {
|
|
1865
1865
|
const buffer = buffer_1.Buffer.from(content);
|
|
1866
|
+
// @ts-ignore
|
|
1866
1867
|
const text = (0, util_1.decodeTextContent)(buffer);
|
|
1867
1868
|
return JSON.parse(text);
|
|
1868
1869
|
}
|
|
@@ -2521,7 +2522,15 @@ class MotionMasterReqResClient {
|
|
|
2521
2522
|
}));
|
|
2522
2523
|
}
|
|
2523
2524
|
/**
|
|
2524
|
-
* Computes the Feed Constant
|
|
2525
|
+
* Computes the Feed Constant for a given device.
|
|
2526
|
+
*
|
|
2527
|
+
* The Feed Constant is calculated as the quotient of:
|
|
2528
|
+
* - `0x6092:01`: Feed
|
|
2529
|
+
* - `0x6092:02`: Shaft Revolutions
|
|
2530
|
+
*
|
|
2531
|
+
* @param deviceRef - Reference to the device for which the Feed Constant is computed.
|
|
2532
|
+
* @param requestTimeout - Optional timeout in milliseconds for the parameter request (default: 5000).
|
|
2533
|
+
* @returns An Observable that emits the computed Feed Constant as a number.
|
|
2525
2534
|
*/
|
|
2526
2535
|
computeFeedConstant(deviceRef, requestTimeout = 5000) {
|
|
2527
2536
|
return this.getParameterValues([
|
|
@@ -2529,6 +2538,23 @@ class MotionMasterReqResClient {
|
|
|
2529
2538
|
[deviceRef, 0x6092, 2], // Shaft revolutions
|
|
2530
2539
|
], false, requestTimeout).pipe((0, operators_1.map)((values) => values[0] / values[1]));
|
|
2531
2540
|
}
|
|
2541
|
+
/**
|
|
2542
|
+
* Computes the Gear Ratio for a given device.
|
|
2543
|
+
*
|
|
2544
|
+
* The Gear Ratio is calculated as the quotient of:
|
|
2545
|
+
* - Gear Ratio Numerator (`0x6091:01` – Motor Revolutions)
|
|
2546
|
+
* - Gear Ratio Denominator (`0x6091:02` – Shaft Revolutions)
|
|
2547
|
+
*
|
|
2548
|
+
* @param deviceRef - Reference to the device for which the Gear Ratio is computed.
|
|
2549
|
+
* @param requestTimeout - Optional timeout in milliseconds for the parameter request (default: 5000).
|
|
2550
|
+
* @returns An Observable that emits the computed Gear Ratio as a number.
|
|
2551
|
+
*/
|
|
2552
|
+
computeGearRatio(deviceRef, requestTimeout = 5000) {
|
|
2553
|
+
return this.getParameterValues([
|
|
2554
|
+
[deviceRef, 0x6091, 1],
|
|
2555
|
+
[deviceRef, 0x6091, 2], // Gear Ratio Denominator (`0x6091:02` – Shaft Revolutions)
|
|
2556
|
+
], false, requestTimeout).pipe((0, operators_1.map)((values) => values[0] / values[1]));
|
|
2557
|
+
}
|
|
2532
2558
|
/**
|
|
2533
2559
|
* Save the modified parameter values to the config.csv file so that they are used the next time the device is power cycled.
|
|
2534
2560
|
* The configuration is saved using the 0x1010: Store parameters object.
|
|
@@ -2981,6 +3007,7 @@ class MotionMasterReqResClient {
|
|
|
2981
3007
|
loginToSmmForParameterDownload(deviceRef, username, password, commandTimeout = 5000, responsePollingInterval = 500) {
|
|
2982
3008
|
const command = (0, os_command_1.createSmmAcyclicHandlerOsCommand)(os_command_1.SmmAcyclicHandlerSubcommandId.PARAMETER_DOWNLOAD_LOGIN);
|
|
2983
3009
|
const content = (0, smm_1.packSmmCredentials)(username, password);
|
|
3010
|
+
// @ts-ignore
|
|
2984
3011
|
return this.runOsCommandAndWriteFsBuffer(deviceRef, command, content, commandTimeout, responsePollingInterval).pipe((0, operators_1.last)(), (0, operators_1.map)((response) => {
|
|
2985
3012
|
if (response.request !== 'succeeded') {
|
|
2986
3013
|
throw new Error('Login to SMM for parameter download failed.');
|
|
@@ -3008,6 +3035,7 @@ class MotionMasterReqResClient {
|
|
|
3008
3035
|
loginToSmmForSoftwareUpdate(deviceRef, username, password, commandTimeout = 10000, responsePollingInterval = 500) {
|
|
3009
3036
|
const command = (0, os_command_1.createSmmAcyclicHandlerOsCommand)(os_command_1.SmmAcyclicHandlerSubcommandId.SOFTWARE_UPDATE_LOGIN);
|
|
3010
3037
|
const content = (0, smm_1.packSmmCredentials)(username, password);
|
|
3038
|
+
// @ts-ignore
|
|
3011
3039
|
return this.runOsCommandAndWriteFsBuffer(deviceRef, command, content, commandTimeout, responsePollingInterval).pipe((0, operators_1.last)(), (0, operators_1.map)((response) => {
|
|
3012
3040
|
if (response.request !== 'succeeded') {
|
|
3013
3041
|
throw new Error('Login to SMM for software update failed.');
|
|
@@ -3072,6 +3100,7 @@ class MotionMasterReqResClient {
|
|
|
3072
3100
|
changeSmmPassword(deviceRef, oldPassword, newPassword, commandTimeout = 10000, responsePollingInterval = 500) {
|
|
3073
3101
|
const command = (0, os_command_1.createSmmAcyclicHandlerOsCommand)(os_command_1.SmmAcyclicHandlerSubcommandId.CHANGE_PASSWORD);
|
|
3074
3102
|
const content = (0, smm_1.packSmmChangePassword)(newPassword, oldPassword);
|
|
3103
|
+
// @ts-ignore
|
|
3075
3104
|
return this.runOsCommandAndWriteFsBuffer(deviceRef, command, content, commandTimeout, responsePollingInterval).pipe((0, operators_1.last)(), (0, operators_1.mergeMap)(() => this.triggerSmmRestart(deviceRef)));
|
|
3076
3105
|
}
|
|
3077
3106
|
/**
|
|
@@ -3194,7 +3223,9 @@ class MotionMasterReqResClient {
|
|
|
3194
3223
|
const packedCrc = (0, smm_1.packSmmSoftwareUpdateCrc)(crc);
|
|
3195
3224
|
const finalizeSoftwareUpdateCommand = (0, os_command_1.createSmmAcyclicHandlerOsCommand)(os_command_1.SmmAcyclicHandlerSubcommandId.FINALIZE_SOFTWARE_UPDATE);
|
|
3196
3225
|
// Step 6: Send the CRC to validate data integrity.
|
|
3197
|
-
observables.push((0, rxjs_1.defer)(() =>
|
|
3226
|
+
observables.push((0, rxjs_1.defer)(() =>
|
|
3227
|
+
// @ts-ignore
|
|
3228
|
+
this.runOsCommandAndWriteFsBuffer(deviceRef, finalizeSoftwareUpdateCommand, packedCrc).pipe((0, operators_1.last)(), (0, operators_1.map)((response) => {
|
|
3198
3229
|
if (response.request !== 'succeeded') {
|
|
3199
3230
|
throw new Error('Finalizing SMM software update failed.');
|
|
3200
3231
|
}
|
|
@@ -3226,7 +3257,9 @@ class MotionMasterReqResClient {
|
|
|
3226
3257
|
return (parameterStructureVersion ? (0, rxjs_1.of)(parameterStructureVersion) : this.resolveSmmParameterStructureVersion(deviceRef)).pipe((0, operators_1.mergeMap)((version) => {
|
|
3227
3258
|
const command = (0, os_command_1.createSmmAcyclicHandlerOsCommand)(os_command_1.SmmAcyclicHandlerSubcommandId.TRANSMIT_PARAMETERS);
|
|
3228
3259
|
const { buffer: content } = (0, smm_1.packSmmParameterValues)(values, version);
|
|
3229
|
-
return this.runOsCommandAndWriteFsBuffer(deviceRef, command,
|
|
3260
|
+
return this.runOsCommandAndWriteFsBuffer(deviceRef, command,
|
|
3261
|
+
// @ts-ignore
|
|
3262
|
+
content, commandTimeout, responsePollingInterval).pipe((0, operators_1.last)(), (0, operators_1.map)((response) => {
|
|
3230
3263
|
if (response.request !== 'succeeded') {
|
|
3231
3264
|
throw new Error('Transmitting SMM parameters failed.');
|
|
3232
3265
|
}
|
|
@@ -3727,6 +3760,7 @@ class MotionMasterReqResClient {
|
|
|
3727
3760
|
}));
|
|
3728
3761
|
}));
|
|
3729
3762
|
}
|
|
3763
|
+
// TODO: Move to another file
|
|
3730
3764
|
getMaxValuePercentageColor(percentage) {
|
|
3731
3765
|
if (percentage >= 50 && percentage <= 100) {
|
|
3732
3766
|
return '#6ba853';
|
|
@@ -3742,6 +3776,7 @@ class MotionMasterReqResClient {
|
|
|
3742
3776
|
}
|
|
3743
3777
|
return '';
|
|
3744
3778
|
}
|
|
3779
|
+
// TODO: Move to another file
|
|
3745
3780
|
getMaxValuePercentageLabel(percentage) {
|
|
3746
3781
|
if (percentage >= 50 && percentage <= 100) {
|
|
3747
3782
|
return 'Calibration was successful. Encoder system is robust to mechanical displacements and temperature expansions.';
|
|
@@ -4131,6 +4166,35 @@ class MotionMasterReqResClient {
|
|
|
4131
4166
|
}
|
|
4132
4167
|
}));
|
|
4133
4168
|
}
|
|
4169
|
+
/**
|
|
4170
|
+
* Reads the motor and shaft revolutions from a device and calculates the gear ratio.
|
|
4171
|
+
*
|
|
4172
|
+
* The gear ratio is defined as the number of motor revolutions per one shaft revolution:
|
|
4173
|
+
*
|
|
4174
|
+
* gearRatio = motorRev / shaftRev
|
|
4175
|
+
*
|
|
4176
|
+
* If either motorRev or shaftRev is zero or negative, the function returns a default value of 1.
|
|
4177
|
+
*
|
|
4178
|
+
* @param deviceRef - Reference to the device from which to read the values.
|
|
4179
|
+
* @returns A Promise that resolves to the gear ratio (positive number). Returns 1 if the readings are invalid.
|
|
4180
|
+
*
|
|
4181
|
+
* @remarks
|
|
4182
|
+
* - Both motorRev and shaftRev are read via `upload()` from the device object dictionary at index 0x6091.
|
|
4183
|
+
* - Ensure that `upload()` returns numeric values and not raw buffers.
|
|
4184
|
+
* - This function assumes positive values; a negative value may indicate an error or reversed rotation.
|
|
4185
|
+
*/
|
|
4186
|
+
getGearRatio(deviceRef) {
|
|
4187
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
4188
|
+
const motorRev = yield this.upload(deviceRef, 0x6091, 1);
|
|
4189
|
+
const shaftRev = yield this.upload(deviceRef, 0x6091, 2);
|
|
4190
|
+
if (motorRev > 0 && shaftRev > 0) {
|
|
4191
|
+
return motorRev / shaftRev;
|
|
4192
|
+
}
|
|
4193
|
+
else {
|
|
4194
|
+
return 1;
|
|
4195
|
+
}
|
|
4196
|
+
});
|
|
4197
|
+
}
|
|
4134
4198
|
}
|
|
4135
4199
|
exports.MotionMasterReqResClient = MotionMasterReqResClient;
|
|
4136
4200
|
/**
|