ekms 9.6.0-beta.5 → 9.6.0-beta.6

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.
@@ -6,11 +6,10 @@
6
6
  "point is a concept",
7
7
  "points are nameable orderable and memorable",
8
8
  {
9
- "apply": "(args) => {\n expectDirection(args)\n expectDistanceForMove(args)\n\n args.config.addSemantic({\n match: ({context, isA}) => isA(context.marker, 'quantity') && isA(context.unit.marker, 'unitPerUnit'),\n apply: async ({context, objects, api, gr, fragments, e, say}) => {\n // send a command to the drone\n const instantiation = await fragments(\"quantity in meters per second\", { quantity: context })\n const result = await e(instantiation)\n const desired_speed = result.evalue.amount.evalue.evalue\n const desired_power = objects.current.power * (desired_speed / objects.calibration.speedForward)\n objects.runCommand = true\n objects.current.power = desired_power \n objects.current.speedUnitsOfUser = context.unit\n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlStart',\n apply: ({context, objects, api}) => {\n objects.runCommand = false \n }\n })\n\n args.config.addSemantic({\n // match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && (context.marker == 'controlEnd' || context.marker == 'controlBetween'),\n match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlEnd',\n apply: async ({context, objects, api}) => {\n // send a command to the drone\n if (objects.runCommand) {\n await api.sendCommand()\n }\n }\n })\n }"
9
+ "apply": "(args) => {\n expectDirection(args)\n expectDistanceForMove(args)\n\n args.config.addSemantic({\n match: ({context, isA}) => isA(context.marker, 'quantity') && isA(context.unit.marker, 'unitPerUnit'),\n apply: async ({context, objects, api, gr, fragments, e, say}) => {\n // send a command to the drone\n const instantiation = await fragments(\"quantity in meters per second\", { quantity: context })\n const result = await e(instantiation)\n const desired_speed = result.evalue.amount.evalue.evalue\n objects.runCommand = true\n objects.current.speed = desired_speed\n objects.current.speedUnitsOfUser = context.unit\n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlStart',\n apply: ({context, objects, api}) => {\n objects.runCommand = false \n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlEnd',\n apply: async ({context, objects, api}) => {\n // send a command to the drone\n if (objects.runCommand) {\n await api.sendCommand()\n }\n }\n })\n }"
10
10
  },
11
11
  {
12
12
  "operators": [
13
- "([calibrate])",
14
13
  "([back])",
15
14
  "([turn] (direction))",
16
15
  "([pause] ([number]))",
@@ -24,7 +23,7 @@
24
23
  "isA": [
25
24
  "noun"
26
25
  ],
27
- "semantic": "async ({objects, mentions, api, e, context}) => {\n if (api.isCalibrated()) {\n objects.runCommand = true\n const ordinal = objects.current.ordinal - 1\n const lastPoint = mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })\n objects.current.destination = lastPoint\n }\n }"
26
+ "semantic": "async ({objects, mentions, api, e, context}) => {\n objects.runCommand = true\n const ordinal = api.currentOrdinal() - 1\n const lastPoint = mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })\n objects.current.destination = lastPoint\n }"
28
27
  },
29
28
  {
30
29
  "id": "toPoint",
@@ -32,7 +31,7 @@
32
31
  "preposition"
33
32
  ],
34
33
  "bridge": "{ ...next(operator), operator: operator, point: after[0], interpolate: [{ property: 'operator' }, { property: 'point' }] }",
35
- "semantic": "async ({objects, api, e, context}) => {\n if (api.isCalibrated()) {\n objects.runCommand = true\n const point = await e(context.point)\n objects.current.destination = point.evalue\n }\n }"
34
+ "semantic": "async ({objects, api, e, context}) => {\n objects.runCommand = true\n const point = await e(context.point)\n objects.current.destination = point.evalue\n }"
36
35
  },
37
36
  {
38
37
  "id": "go"
@@ -45,17 +44,6 @@
45
44
  "bridge": "{ ...next(operator), direction: after[0], interpolate: [{ context: operator }, { property: 'direction' }] }",
46
45
  "semantic": "({context, objects, api}) => {\n objects.runCommand = true\n objects.current.direction = context.direction.marker\n }"
47
46
  },
48
- {
49
- "id": "calibrate",
50
- "words": [
51
- "configure"
52
- ],
53
- "isA": [
54
- "verb"
55
- ],
56
- "bridge": "{ ...next(operator), interpolate: [{ context: operator }] }",
57
- "semantic": "async ({context, objects, api, mentioned}) => {\n let power = 20\n const moveTimeInSeconds = 0.5\n let distanceInCM = 0\n let startBackward\n for (; power < 30; ++power) {\n const start = await api.sonic();\n await api.forward(power, { batched: true })\n await api.pause(moveTimeInSeconds, { batched: true })\n await api.stop()\n const end = await api.sonic();\n if (end !== start) {\n distanceInCM = start - end\n startBackward = end\n break;\n }\n }\n\n const metersPerSecondForward = (distanceInCM/100)/moveTimeInSeconds\n\n // reset\n\n await api.backward(power, { batched: true })\n await api.pause(moveTimeInSeconds, { batched: true })\n await api.stop()\n const endBackward = await api.sonic();\n\n const metersPerSecondBackward = ((endBackward-startBackward)/100)/moveTimeInSeconds\n \n // console.log(`Distance ${distance} cm`)\n // console.log(`Time ${moveTime} ms`)\n // console.log(`M/S ${metersPerSecond}`)\n\n objects.calibration.minPower = power\n objects.calibration.power = power\n objects.current.power = power\n objects.calibration.speedForward = metersPerSecondForward\n objects.calibration.speedBackward = metersPerSecondBackward\n objects.calibration.isCalibrated = true\n\n const ordinal = api.nextOrdinal()\n mentioned({ marker: 'point', ordinal, point: { x: 0, y: 0 }, description: \"start\" })\n objects.current.ordinal = ordinal\n\n api.saveCalibration(objects.calibration)\n }"
58
- },
59
47
  {
60
48
  "id": "pause",
61
49
  "isA": [
@@ -73,7 +61,7 @@
73
61
  "1": "{ marker: 'drone' }"
74
62
  },
75
63
  "bridge": "{ ...next(operator), object: after[0], interpolate: [{ context: operator }, { property: 'object' }] }",
76
- "semantic": "async ({mentioned, context, objects, api, say}) => {\n if (!objects.calibration.isCalibrated) {\n return // ignore\n }\n if (objects.calibration.speedForward) {\n await api.stop()\n api.markCurrentPoint()\n } else {\n const stopTime = await api.stop()\n objects.calibration.endTime = stopTime\n objects.calibration.duration = (objects.calibration.endTime - objects.calibration.startTime)/1000\n }\n }"
64
+ "semantic": "async ({mentioned, context, objects, api, say}) => {\n await api.stop()\n api.markCurrentPoint()\n }"
77
65
  }
78
66
  ],
79
67
  "generators": [
@@ -15683,12 +15671,11 @@
15683
15671
  }
15684
15672
  },
15685
15673
  {
15686
- "apply": "(args) => {\n expectDirection(args)\n expectDistanceForMove(args)\n\n args.config.addSemantic({\n match: ({context, isA}) => isA(context.marker, 'quantity') && isA(context.unit.marker, 'unitPerUnit'),\n apply: async ({context, objects, api, gr, fragments, e, say}) => {\n // send a command to the drone\n const instantiation = await fragments(\"quantity in meters per second\", { quantity: context })\n const result = await e(instantiation)\n const desired_speed = result.evalue.amount.evalue.evalue\n const desired_power = objects.current.power * (desired_speed / objects.calibration.speedForward)\n objects.runCommand = true\n objects.current.power = desired_power \n objects.current.speedUnitsOfUser = context.unit\n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlStart',\n apply: ({context, objects, api}) => {\n objects.runCommand = false \n }\n })\n\n args.config.addSemantic({\n // match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && (context.marker == 'controlEnd' || context.marker == 'controlBetween'),\n match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlEnd',\n apply: async ({context, objects, api}) => {\n // send a command to the drone\n if (objects.runCommand) {\n await api.sendCommand()\n }\n }\n })\n }"
15674
+ "apply": "(args) => {\n expectDirection(args)\n expectDistanceForMove(args)\n\n args.config.addSemantic({\n match: ({context, isA}) => isA(context.marker, 'quantity') && isA(context.unit.marker, 'unitPerUnit'),\n apply: async ({context, objects, api, gr, fragments, e, say}) => {\n // send a command to the drone\n const instantiation = await fragments(\"quantity in meters per second\", { quantity: context })\n const result = await e(instantiation)\n const desired_speed = result.evalue.amount.evalue.evalue\n objects.runCommand = true\n objects.current.speed = desired_speed\n objects.current.speedUnitsOfUser = context.unit\n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlStart',\n apply: ({context, objects, api}) => {\n objects.runCommand = false \n }\n })\n\n args.config.addSemantic({\n match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlEnd',\n apply: async ({context, objects, api}) => {\n // send a command to the drone\n if (objects.runCommand) {\n await api.sendCommand()\n }\n }\n })\n }"
15687
15675
  },
15688
15676
  {
15689
15677
  "extraConfig": true,
15690
15678
  "operators": [
15691
- "([calibrate])",
15692
15679
  "([back])",
15693
15680
  "([turn] (direction))",
15694
15681
  "([pause] ([number]))",
@@ -15720,16 +15707,6 @@
15720
15707
  ],
15721
15708
  "bridge": "{ ...next(operator), direction: after[0], interpolate: [{ context: operator }, { property: 'direction' }] }"
15722
15709
  },
15723
- {
15724
- "id": "calibrate",
15725
- "words": [
15726
- "configure"
15727
- ],
15728
- "isA": [
15729
- "verb"
15730
- ],
15731
- "bridge": "{ ...next(operator), interpolate: [{ context: operator }] }"
15732
- },
15733
15710
  {
15734
15711
  "id": "pause",
15735
15712
  "isA": [
@@ -15927,11 +15904,6 @@
15927
15904
  "verb",
15928
15905
  false
15929
15906
  ],
15930
- [
15931
- "calibrate",
15932
- "verb",
15933
- false
15934
- ],
15935
15907
  [
15936
15908
  "call",
15937
15909
  "verb",
@@ -18718,11 +18690,6 @@
18718
18690
  "verb",
18719
18691
  false
18720
18692
  ],
18721
- [
18722
- "calibrate",
18723
- "verb",
18724
- false
18725
- ],
18726
18693
  [
18727
18694
  "call",
18728
18695
  "verb",
@@ -21780,11 +21747,6 @@
21780
21747
  "verb",
21781
21748
  false
21782
21749
  ],
21783
- [
21784
- "calibrate",
21785
- "verb",
21786
- false
21787
- ],
21788
21750
  [
21789
21751
  "call",
21790
21752
  "verb",
@@ -24762,11 +24724,6 @@
24762
24724
  "verb",
24763
24725
  false
24764
24726
  ],
24765
- [
24766
- "calibrate",
24767
- "verb",
24768
- false
24769
- ],
24770
24727
  [
24771
24728
  "call",
24772
24729
  "verb",
package/common/drone.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { knowledgeModule, where } = require('./runtime').theprogrammablemind
2
- const { defaultContextCheck, getValue, setValue } = require('./helpers')
2
+ const { OverrideCheck, defaultContextCheck, getValue, setValue } = require('./helpers')
3
3
  const drone_tests = require('./drone.test.json')
4
4
  const instance = require('./drone.instance.json')
5
5
  const hierarchy = require('./hierarchy')
@@ -107,6 +107,8 @@ https://www.amazon.ca/Freenove-Raspberry-Tracking-Avoidance-Ultrasonic/dp/B0BNDQ
107
107
  you are facing north. patrol between here and 100 feet to the west
108
108
  this way is south
109
109
 
110
+ go forward for 1 second\nbackward 2 meters (implicit stop)
111
+
110
112
  go back
111
113
  */
112
114
 
@@ -121,14 +123,17 @@ function expectDirection(args) {
121
123
  }
122
124
 
123
125
  function expectDistanceForMove(args) {
124
- // TODO save id for recalibration
125
126
  args.config.addSemantic({
126
127
  match: ({context, isA}) => isA(context.marker, 'quantity') && !isA(context.unit.marker, 'unitPerUnit'),
127
- apply: async ({context, objects, fragments, e}) => {
128
+ apply: async ({context, objects, fragments, e, say, gp}) => {
128
129
  const instantiation = await fragments("quantity in meters", { quantity: context })
129
- const result = await e(instantiation)
130
- objects.runCommand = true
131
- objects.current.distance = result.evalue.amount.evalue.evalue
130
+ try {
131
+ const result = await e(instantiation)
132
+ objects.runCommand = true
133
+ objects.current.distance = result.evalue.amount.evalue.evalue
134
+ } catch (e) {
135
+ say(`Don't know how to interpret ${await gp(context)} in meters`)
136
+ }
132
137
  }
133
138
  })
134
139
  }
@@ -144,21 +149,6 @@ function expectDistanceForMove(args) {
144
149
  -90
145
150
  */
146
151
 
147
- class OverrideCheck {
148
- constructor(base, checks) {
149
- this.base = base
150
- this.checks = checks
151
- }
152
-
153
- check(obj) {
154
- for (const check of this.checks) {
155
- if (obj[check] == this.base.prototype[check]) {
156
- throw new Error(`For ${obj.constructor.name} you need to override ${check}`)
157
- }
158
- }
159
- }
160
- }
161
-
162
152
  /*
163
153
  L = track separation width (distance between the centers of the two tracks, measured side-to-side, in meters or whatever unit you like)
164
154
 
@@ -177,7 +167,7 @@ The time t needed to turn by angle θ is:
177
167
  */
178
168
  class API {
179
169
  constructor() {
180
- this.overrideCheck = new OverrideCheck(API, ['forwardDrone', 'backwardDrone', 'rotateDrone', 'sonicDrone', 'tiltAngleDrone', 'panAngleDrone', 'stopDrone', 'saveCalibration'])
170
+ this.overrideCheck = new OverrideCheck(API, ['forwardDrone', 'backwardDrone', 'rotateDrone', 'sonicDrone', 'tiltAngleDrone', 'panAngleDrone', 'stopDrone'])
181
171
  this.overriden = this.constructor !== API
182
172
  }
183
173
 
@@ -187,42 +177,39 @@ class API {
187
177
  }
188
178
  this._objects = objects
189
179
  this._objects.defaultTime = { hour: 9, minute: 0, second: 0, millisecond: 0 }
190
- this._objects.ordinal = 0
191
180
  delete this.testDate
192
181
 
193
- objects.calibration = {
194
- speed: undefined, // meters per second
195
- widthOfTankInMM: 188,
196
- widthOfTreadInMM: 44,
197
- }
198
182
  objects.current = {
199
- angleInRadians: 0
200
- // direction: undefined, // direction to go if going
201
- // power: undefined, // power
202
- // ordinal // ordinal of the current point or the current point that the recent movement started at
183
+ angleInRadians: 0,
184
+ speed: this.minimumSpeedDrone(),
185
+ ordinal: 0, // ordinal of the current point or the current point that the recent movement started at
203
186
  }
204
187
  objects.history = []
205
- objects.calibration.isCalibrated = false
206
188
  objects.sonicTest = 5
189
+
190
+ this.args.mentioned({ marker: 'point', ordinal: this.nextOrdinal(), point: { x: 0, y: 0 }, description: "start" })
207
191
  }
208
192
 
209
- isCalibrated() {
210
- return this._objects.calibration.isCalibrated
193
+ currentOrdinal() {
194
+ return this._objects.current.ordinal
211
195
  }
212
196
 
213
197
  nextOrdinal() {
214
- return this._objects.ordinal += 1
198
+ return this._objects.current.ordinal += 1
215
199
  }
216
200
 
217
201
  currentPoint() {
218
- if (!this._objects.current.endTime) {
202
+ if (!this._objects.current.startTime || !this._objects.current.endTime) {
219
203
  return null // in motion
220
204
  }
221
- const ordinal = this._objects.current.ordinal
205
+ const ordinal = this.currentOrdinal()
222
206
  const lastPoint = this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
207
+ if (!this._objects.current.startTime && !this._objects.current.endTime) {
208
+ return lastPoint // did not move
209
+ }
223
210
 
224
211
  const durationInSeconds = (this._objects.current.endTime - this._objects.current.startTime) / 1000
225
- const speedInMetersPerSecond = (this._objects.current.power / this._objects.calibration.power) * this._objects.calibration.speedForward
212
+ const speedInMetersPerSecond = this._objects.current.speed
226
213
  const direction = this._objects.current.direction
227
214
  const distanceInMeters = speedInMetersPerSecond * durationInSeconds * (direction == 'forward' ? 1 : -1)
228
215
  const angleInRadians = this._objects.current.angleInRadians
@@ -232,10 +219,12 @@ class API {
232
219
  }
233
220
 
234
221
  markCurrentPoint() {
235
- const ordinal = this.nextOrdinal()
236
222
  const point = this.currentPoint()
223
+ if (!point) {
224
+ return
225
+ }
226
+ const ordinal = this.nextOrdinal()
237
227
  this.args.mentioned({ marker: 'point', ordinal, point })
238
- this._objects.current.ordinal = ordinal
239
228
  this._objects.current.endTime = null
240
229
  this._objects.current.startTime = null
241
230
  }
@@ -245,32 +234,33 @@ class API {
245
234
  const { fragments, e, say, gr } = this.args
246
235
 
247
236
  // TODO account for forward vs backward speed
248
- if (objects.current.power < objects.calibration.minPower) {
237
+ const minimumSpeed = this.minimumSpeedDrone()
238
+ if (objects.current.speed < minimumSpeed) {
249
239
  const unitsOfUser = objects.current.speedUnitsOfUser
250
- const minimumValueInDroneUnits = await fragments("number meters per second", { number: { marker: 'integer', value: objects.calibration.speedForward } })
240
+ const minimumValueInDroneUnits = await fragments("number meters per second", { number: { marker: 'integer', value: minimumSpeed } })
251
241
  const valueInUsersUnits = await fragments("quantity in units", { quantity: minimumValueInDroneUnits, unit_length: unitsOfUser })
252
242
  const evaluated = await e(valueInUsersUnits)
253
243
  say(`The drone cannot go that slow. The minimum speed is ${await gr(evaluated.evalue)}`)
254
244
  objects.runCommand = false
255
- objects.current.power = objects.calibration.minPower // reset
245
+ objects.current.speed = minimumSpeed
256
246
  return
257
247
  }
258
248
 
259
249
  // TODO account for forward vs backward speed
260
- if (objects.current.power > 100) {
261
- const maximumSpeed = (100 / objects.calibration.power) * objects.calibration.speedForward
250
+ const maximumSpeed = this.maximumSpeedDrone()
251
+ if (objects.current.speed > maximumSpeed) {
262
252
  const unitsOfUser = objects.current.speedUnitsOfUser
263
253
  const maximumValueInDroneUnits = await fragments("number meters per second", { number: { marker: 'integer', value: maximumSpeed } })
264
254
  const valueInUsersUnits = await fragments("quantity in units", { quantity: maximumValueInDroneUnits, unit_length: unitsOfUser })
265
255
  const evaluated = await e(valueInUsersUnits)
266
256
  say(`The drone cannot go that fast. The maximum speed is ${await gr(evaluated.evalue)}`)
267
257
  objects.runCommand = false
268
- objects.current.power = objects.calibration.minPower // reset
258
+ objects.current.speed = minimumSpeed
269
259
  return
270
260
  }
271
261
 
272
262
  const stopAtDistance = async (direction, distanceMeters) => {
273
- const speed_meters_per_second = direction == 'forward' ? this._objects.calibration.speedForward : this._objects.calibration.speedBackward
263
+ const speed_meters_per_second = this._objects.current.speed
274
264
  const duration_seconds = distanceMeters / speed_meters_per_second
275
265
  await this.pause(duration_seconds, { batched: true })
276
266
  await this.stop()
@@ -278,26 +268,29 @@ class API {
278
268
  }
279
269
 
280
270
  if (this._objects.current.destination) {
281
- debugger
282
- const currentPoint = this.args.mentions({ context: { marker: 'point' } })
283
- const polar = cartesianToPolar(currentPoint.point, this._objects.current.destination.point)
284
- const destinationAngleInRadians = polar.angle
285
- let angleDelta = (destinationAngleInRadians - this._objects.current.angleInRadians)
286
- debugger
287
- await this.rotate(angleDelta)
288
- await this.forward(this._objects.current.power)
289
- await stopAtDistance("forward", polar.radius)
290
- this._objects.current.destination = undefined
271
+ const currentPoint = this.args.mentions({ context: { marker: 'point' } }).point
272
+ const destinationPoint = this._objects.current.destination.point
273
+ if (currentPoint.x == destinationPoint.x && currentPoint.y == destinationPoint.y) {
274
+ // already there
275
+ } else {
276
+ const polar = cartesianToPolar(currentPoint, destinationPoint)
277
+ const destinationAngleInRadians = polar.angle
278
+ const angleDelta = (destinationAngleInRadians - this._objects.current.angleInRadians)
279
+ await this.rotate(angleDelta)
280
+ await this.forward(this._objects.current.speed)
281
+ await stopAtDistance("forward", polar.radius)
282
+ this._objects.current.destination = undefined
283
+ }
291
284
  return
292
285
  }
293
286
 
294
- const command = { power: this._objects.current.power, ...this._objects.current }
287
+ const command = { speed: this._objects.current.speed, ...this._objects.current }
295
288
  switch (command.direction) {
296
289
  case 'forward':
297
- await this.forward(command.power, { batched: command.distance })
290
+ await this.forward(command.speed, { batched: command.distance })
298
291
  break
299
292
  case 'backward':
300
- await this.backward(command.power, { batched: command.distance })
293
+ await this.backward(command.speed, { batched: command.distance })
301
294
  break
302
295
  case 'right':
303
296
  await this.rotate(-Math.PI/4)
@@ -316,25 +309,17 @@ class API {
316
309
  }
317
310
  }
318
311
 
319
- loadCalibration(calibration) {
320
- Object.assign(this._objects.calibration, calibration)
321
- this._objects.current.power = this._objects.calibration.minPower
322
- }
323
-
324
- // override this to save the calibration to not have to run it over and over again and be annoing.
325
- async saveCalibration(calibration) {
326
- this._objects.history.push({ marker: 'history', saveCalibration: true })
327
- }
328
-
329
- async forward(power, options) {
330
- const time = await this.forwardDrone(power, options)
312
+ async forward(speed, options) {
313
+ await this.forwardDrone(speed, options)
314
+ const time = this.now()
331
315
  this._objects.current.startTime = time
332
316
  this._objects.current.endTime = null
333
317
  return time
334
318
  }
335
319
 
336
- async backward(power, options) {
337
- const time = await this.backwardDrone(power, options)
320
+ async backward(speed, options) {
321
+ await this.backwardDrone(speed, options)
322
+ const time = this.now()
338
323
  this._objects.current.startTime = time
339
324
  this._objects.current.endTime = null
340
325
  return time
@@ -359,8 +344,11 @@ class API {
359
344
  }
360
345
 
361
346
  async stop(options) {
362
- const time = await this.stopDrone(options)
363
- this._objects.current.endTime = time
347
+ await this.stopDrone(options)
348
+ const time = this.now()
349
+ if (this._objects.current.startTime) {
350
+ this._objects.current.endTime = time
351
+ }
364
352
  return time
365
353
  }
366
354
 
@@ -370,37 +358,46 @@ class API {
370
358
 
371
359
  // subclass and override the remaining to call the drone
372
360
 
373
- // this is for testing
374
361
  async pauseDrone(durationInSeconds, options) {
375
362
  this._objects.history.push({ marker: 'history', pause: durationInSeconds, ...options })
376
363
  this.testDate = new Date(this.testDate.getTime() + (durationInSeconds-1)*1000)
377
364
  }
378
365
 
379
- now() {
366
+ // meters per second
367
+ minimumSpeedDrone() {
368
+ return 0.25
369
+ }
370
+
371
+ // meters per second
372
+ maximumSpeedDrone() {
373
+ return 1.2
374
+ }
375
+
376
+ now(lookahead = false) {
380
377
  if (this.args.isProcess || this.args.isTest) {
381
378
  if (!this.testDate) {
382
379
  this.testDate = new Date(2025, 5, 29, 14, 52, 0)
383
380
  }
384
- this.testDate = new Date(this.testDate.getTime() + 1000)
385
- return this.testDate
381
+ if (lookahead) {
382
+ return new Date(this.testDate.getTime() + 1000)
383
+ } else {
384
+ this.testDate = new Date(this.testDate.getTime() + 1000)
385
+ return this.testDate
386
+ }
386
387
  } else {
387
388
  return new Date()
388
389
  }
389
390
  }
390
391
 
391
392
  // CMD_MOTOR#1000#1000#
392
- async forwardDrone(power, options) {
393
- const time = this.now()
393
+ async forwardDrone(speed, options) {
394
394
  this._objects.sonicTest -= 10 // make the speed about the same as the actual drone
395
- this._objects.history.push({ marker: 'history', direction: 'forward', power, time, ...options })
396
- return time
395
+ this._objects.history.push({ marker: 'history', direction: 'forward', speed, time: this.now(true), ...options })
397
396
  }
398
397
 
399
- async backwardDrone(power, options) {
400
- const time = this.now()
398
+ async backwardDrone(speed, options) {
401
399
  this._objects.sonicTest += 10 // make the speed about the same as the actual drone
402
- this._objects.history.push({ marker: 'history', direction: 'backward', power, time, ...options })
403
- return time
400
+ this._objects.history.push({ marker: 'history', direction: 'backward', speed, time: this.now(true), ...options })
404
401
  }
405
402
 
406
403
  // -angle is counterclockwise
@@ -423,9 +420,7 @@ class API {
423
420
  }
424
421
 
425
422
  async stopDrone(options) {
426
- const time = this.now()
427
- this._objects.history.push({ marker: 'history', power: 0, time, ...options })
428
- return time
423
+ this._objects.history.push({ marker: 'history', speed: 0, time: this.now(true), ...options })
429
424
  }
430
425
  }
431
426
 
@@ -507,23 +502,21 @@ const template = {
507
502
  const instantiation = await fragments("quantity in meters per second", { quantity: context })
508
503
  const result = await e(instantiation)
509
504
  const desired_speed = result.evalue.amount.evalue.evalue
510
- const desired_power = objects.current.power * (desired_speed / objects.calibration.speedForward)
511
505
  objects.runCommand = true
512
- objects.current.power = desired_power
506
+ objects.current.speed = desired_speed
513
507
  objects.current.speedUnitsOfUser = context.unit
514
508
  }
515
509
  })
516
510
 
517
511
  args.config.addSemantic({
518
- match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlStart',
512
+ match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlStart',
519
513
  apply: ({context, objects, api}) => {
520
514
  objects.runCommand = false
521
515
  }
522
516
  })
523
517
 
524
518
  args.config.addSemantic({
525
- // match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && (context.marker == 'controlEnd' || context.marker == 'controlBetween'),
526
- match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlEnd',
519
+ match: ({context, objects, isA}) => objects.current.direction && context.marker == 'controlEnd',
527
520
  apply: async ({context, objects, api}) => {
528
521
  // send a command to the drone
529
522
  if (objects.runCommand) {
@@ -534,7 +527,6 @@ const template = {
534
527
  },
535
528
  {
536
529
  operators: [
537
- "([calibrate])",
538
530
  "([back])",
539
531
  "([turn] (direction))",
540
532
  "([pause] ([number]))",
@@ -547,12 +539,10 @@ const template = {
547
539
  id: "back",
548
540
  isA: ['noun'],
549
541
  semantic: async ({objects, mentions, api, e, context}) => {
550
- if (api.isCalibrated()) {
551
- objects.runCommand = true
552
- const ordinal = objects.current.ordinal - 1
553
- const lastPoint = mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
554
- objects.current.destination = lastPoint
555
- }
542
+ objects.runCommand = true
543
+ const ordinal = api.currentOrdinal() - 1
544
+ const lastPoint = mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
545
+ objects.current.destination = lastPoint
556
546
  }
557
547
  },
558
548
  {
@@ -560,11 +550,9 @@ const template = {
560
550
  isA: ['preposition'],
561
551
  bridge: "{ ...next(operator), operator: operator, point: after[0], interpolate: [{ property: 'operator' }, { property: 'point' }] }",
562
552
  semantic: async ({objects, api, e, context}) => {
563
- if (api.isCalibrated()) {
564
- objects.runCommand = true
565
- const point = await e(context.point)
566
- objects.current.destination = point.evalue
567
- }
553
+ objects.runCommand = true
554
+ const point = await e(context.point)
555
+ objects.current.destination = point.evalue
568
556
  }
569
557
  },
570
558
  { id: "go" },
@@ -578,58 +566,6 @@ const template = {
578
566
  },
579
567
  // check: { marker: 'turn', exported: true, extra: ['direction'] }
580
568
  },
581
- {
582
- id: 'calibrate',
583
- words: ['configure'],
584
- isA: ['verb'],
585
- bridge: "{ ...next(operator), interpolate: [{ context: operator }] }",
586
- semantic: async ({context, objects, api, mentioned}) => {
587
- let power = 20
588
- const moveTimeInSeconds = 0.5
589
- let distanceInCM = 0
590
- let startBackward
591
- for (; power < 30; ++power) {
592
- const start = await api.sonic();
593
- await api.forward(power, { batched: true })
594
- await api.pause(moveTimeInSeconds, { batched: true })
595
- await api.stop()
596
- const end = await api.sonic();
597
- if (end !== start) {
598
- distanceInCM = start - end
599
- startBackward = end
600
- break;
601
- }
602
- }
603
-
604
- const metersPerSecondForward = (distanceInCM/100)/moveTimeInSeconds
605
-
606
- // reset
607
-
608
- await api.backward(power, { batched: true })
609
- await api.pause(moveTimeInSeconds, { batched: true })
610
- await api.stop()
611
- const endBackward = await api.sonic();
612
-
613
- const metersPerSecondBackward = ((endBackward-startBackward)/100)/moveTimeInSeconds
614
-
615
- // console.log(`Distance ${distance} cm`)
616
- // console.log(`Time ${moveTime} ms`)
617
- // console.log(`M/S ${metersPerSecond}`)
618
-
619
- objects.calibration.minPower = power
620
- objects.calibration.power = power
621
- objects.current.power = power
622
- objects.calibration.speedForward = metersPerSecondForward
623
- objects.calibration.speedBackward = metersPerSecondBackward
624
- objects.calibration.isCalibrated = true
625
-
626
- const ordinal = api.nextOrdinal()
627
- mentioned({ marker: 'point', ordinal, point: { x: 0, y: 0 }, description: "start" })
628
- objects.current.ordinal = ordinal
629
-
630
- api.saveCalibration(objects.calibration)
631
- }
632
- },
633
569
  {
634
570
  id: 'pause',
635
571
  isA: ['verb'],
@@ -648,17 +584,8 @@ const template = {
648
584
  },
649
585
  bridge: "{ ...next(operator), object: after[0], interpolate: [{ context: operator }, { property: 'object' }] }",
650
586
  semantic: async ({mentioned, context, objects, api, say}) => {
651
- if (!objects.calibration.isCalibrated) {
652
- return // ignore
653
- }
654
- if (objects.calibration.speedForward) {
655
- await api.stop()
656
- api.markCurrentPoint()
657
- } else {
658
- const stopTime = await api.stop()
659
- objects.calibration.endTime = stopTime
660
- objects.calibration.duration = (objects.calibration.endTime - objects.calibration.startTime)/1000
661
- }
587
+ await api.stop()
588
+ api.markCurrentPoint()
662
589
  }
663
590
  },
664
591
  ],
@@ -689,13 +616,11 @@ knowledgeModule( {
689
616
  context: [
690
617
  defaultContextCheck({ marker: 'point', exported: true, extra: ['ordinal', { property: 'point', check: ['x', 'y'] }, 'description', { property: 'stm', check: ['id', 'names'] }] }),
691
618
  defaultContextCheck({ marker: 'turn', exported: true, extra: ['direction'] }),
692
- defaultContextCheck({ marker: 'history', exported: true, extra: ['pause', 'direction', 'power', 'turn', 'time', 'sonic', 'saveCalibration', 'batched'] }),
619
+ defaultContextCheck({ marker: 'history', exported: true, extra: ['pause', 'direction', 'speed', 'turn', 'time', 'sonic', 'batched'] }),
693
620
  defaultContextCheck(),
694
621
  ],
695
622
  objects: [
696
623
  { km: 'stm' },
697
- { path: ['isCalibrated'] },
698
- { path: ['calibration'] },
699
624
  { path: ['history'] },
700
625
  { path: ['current'] },
701
626
  { path: ['runCommand'] },