tpmkms_4wp 9.5.1-beta.9 → 9.6.0-beta.0
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/common/animals.instance.json +130 -0
- package/common/animals.js +3 -5
- package/common/asking.js +12 -4
- package/common/avatar.test.json +1001 -860
- package/common/can.instance.json +2182 -5
- package/common/can.js +102 -39
- package/common/can.test.json +51307 -0
- package/common/colors.instance.json +142 -30
- package/common/colors.js +3 -6
- package/common/comparable.instance.json +31 -1
- package/common/comparable.js +3 -6
- package/common/concept.js +25 -27
- package/common/concept.test.json +142 -120
- package/common/conjunction.test.json +32 -42
- package/common/crew.instance.json +400 -126
- package/common/crew.js +3 -6
- package/common/dateTimeSelectors.instance.json +2 -2
- package/common/dateTimeSelectors.js +6 -9
- package/common/dateTimeSelectors.test.json +76935 -35739
- package/common/dates.instance.json +50 -84
- package/common/dates.js +3 -6
- package/common/dates.test.json +284 -287
- package/common/dialogues.js +33 -115
- package/common/dialogues.test.json +1248 -1152
- package/common/dimension.instance.json +21498 -566
- package/common/dimension.js +147 -52
- package/common/dimension.test.json +10979 -4625
- package/common/drone.instance.json +24709 -0
- package/common/drone.js +662 -0
- package/common/drone.test.json +30522 -0
- package/common/drone_v1.instance.json +24703 -0
- package/common/drone_v1.js +596 -0
- package/common/drone_v1.test.json +115538 -0
- package/common/edible.instance.json +365 -65
- package/common/edible.js +3 -5
- package/common/emotions.instance.json +57 -70
- package/common/emotions.js +3 -6
- package/common/errors.js +3 -3
- package/common/fastfood.instance.json +1270 -244
- package/common/fastfood.js +10 -12
- package/common/fastfood.test.json +6970 -6829
- package/common/formulas.instance.json +10 -0
- package/common/formulas.js +2 -1
- package/common/gdefaults.js +58 -13
- package/common/help.js +9 -9
- package/common/help.test.json +65 -11
- package/common/helpers/dialogues.js +9 -1
- package/common/helpers/properties.js +37 -18
- package/common/helpers.js +32 -2
- package/common/hierarchy.js +10 -8
- package/common/kirk.instance.json +10 -0
- package/common/kirk.js +4 -6
- package/common/kirk.test.json +600 -424
- package/common/latin.instance.json +10 -10
- package/common/latin.js +8 -10
- package/common/length.instance.json +34659 -3157
- package/common/length.js +11 -6
- package/common/length.test.json +54357 -2557
- package/common/math.instance.json +11 -1
- package/common/math.js +2 -1
- package/common/menus.instance.json +74 -7
- package/common/menus.js +3 -12
- package/common/meta.js +4 -5
- package/common/nameable.js +29 -15
- package/common/nameable.test.json +436 -0
- package/common/numbers.js +1 -1
- package/common/ordering.instance.json +24 -2
- package/common/ordering.js +3 -5
- package/common/ordering.test.json +104 -174
- package/common/people.instance.json +140 -315
- package/common/people.js +3 -5
- package/common/pipboy.instance.json +171 -57
- package/common/pipboy.js +2 -1
- package/common/pokemon.instance.json +135 -5
- package/common/pokemon.js +3 -5
- package/common/pressure.instance.json +3990 -1981
- package/common/pressure.js +3 -5
- package/common/pressure.test.json +433 -477
- package/common/properties.instance.json +15 -16
- package/common/properties.js +10 -9
- package/common/properties.test.json +9565 -6951
- package/common/rates.instance.json +59 -0
- package/common/rates.js +95 -0
- package/common/rates.test.json +27702 -0
- package/common/reminders.js +5 -8
- package/common/reminders.test.json +64635 -25787
- package/common/reports.instance.json +22 -2
- package/common/reports.js +3 -5
- package/common/scorekeeper.js +3 -6
- package/common/spock.instance.json +10 -0
- package/common/spock.js +4 -7
- package/common/spock.test.json +606 -430
- package/common/stm.js +37 -20
- package/common/temperature.instance.json +3162 -1153
- package/common/temperature.js +3 -5
- package/common/temperature.test.json +433 -477
- package/common/time.instance.json +24852 -0
- package/common/time.js +136 -139
- package/common/time.test.json +31876 -3757
- package/common/ui.instance.json +12 -5
- package/common/ui.js +4 -13
- package/common/weight.instance.json +10500 -4098
- package/common/weight.js +3 -5
- package/common/weight.test.json +2601 -2263
- package/common/words.instance.json +9 -0
- package/common/words.js +50 -0
- package/common/words.test.json +2 -0
- package/common/wp.instance.json +470 -58
- package/common/wp.js +6 -4
- package/common/wp.test.json +7385 -6906
- package/main.js +6 -2
- package/package.json +21 -6
- package/common/listener.js +0 -50
- package/common/listener.test.json +0 -142
package/common/drone.js
ADDED
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
const { knowledgeModule, where } = require('./runtime').theprogrammablemind
|
|
2
|
+
const { defaultContextCheck, getValue, setValue } = require('./helpers')
|
|
3
|
+
const drone_tests = require('./drone.test.json')
|
|
4
|
+
const instance = require('./drone.instance.json')
|
|
5
|
+
const hierarchy = require('./hierarchy')
|
|
6
|
+
const ordinals = require('./ordinals')
|
|
7
|
+
const nameable = require('./nameable')
|
|
8
|
+
const rates = require('./rates')
|
|
9
|
+
const help = require('./help')
|
|
10
|
+
const { degreesToRadians, radiansToDegrees, cartesianToPolar } = require('./helpers/drone')
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
todo
|
|
14
|
+
|
|
15
|
+
VOSK
|
|
16
|
+
|
|
17
|
+
https://alphacephei.com/vosk/
|
|
18
|
+
|
|
19
|
+
FreeNode Tank
|
|
20
|
+
|
|
21
|
+
https://docs.freenove.com/projects/fnk0077/en/latest/fnk0077/codes/tutorial/3_Module_test_%28necessary%29.html
|
|
22
|
+
https://www.amazon.ca/Freenove-Raspberry-Tracking-Avoidance-Ultrasonic/dp/B0BNDQFRP1/ref=sr_1_1_sspa?crid=1JT788RT84O8C&dib=eyJ2IjoiMSJ9.1W6XTWnHwPcqZTD8iRfmF7hHwiVycHjB02NHKEcqGfQSUKyJfN0OLyaaoCcypQug_C9CGah-7wLgfAtJRs_JKiwDsqYXqFfvvoU5ETBk_Le-S9Qt4kwh92r0w19bzA5my7aQpT52ssw8-f8Xpzjbqm1uFsLh82jF4V7P8xMKobjVHHILXalReEPuJz2OlF6y_ihwtUuVLDjMkuvNPoK-M7YLntLqKQy229XKjtDSUV4J0YT1L8uLVWHZ-ySs_MmG_w-oyZ9QFIe0a9hJEMuiu_BcaDmxFkwMeGBro2uczAU.NlqF_FH_6PvflZKozPylFlIyKuwx7mAB-jAggC1aPFk&dib_tag=se&keywords=Freenove+Tank+Robot+Kit&qid=1766258114&sprefix=freenove+drone+robot+kit%2Caps%2C130&sr=8-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
send commands to arduino from another computer:
|
|
26
|
+
|
|
27
|
+
https://www.npmjs.com/package/johnny-five
|
|
28
|
+
|
|
29
|
+
KEYESTUDIO Mini Tank Robot V2 Smart Car Kit for Arduino
|
|
30
|
+
|
|
31
|
+
https://www.amazon.ca/KEYESTUDIO-Infrared-Ultrasonic-Obstacle-Avoidance/dp/B07X4W7SZ5/ref=sr_1_10?crid=2A71NHZNTAION&dib=eyJ2IjoiMSJ9.W-I4I_tfyGdGt2UrNlNrlFeKnfIwppniNSX5FJndx77Ht944f9RylJD9me0PiqV5V_b185b17BsrPdKxmYYHnJ-Odb7hbdVzKs019mag1nCL-Wqe4aR0IYrEOzJkKTnR4YbXGYwriLd26OBYjhNvgaCFyE5uwsYkAK-qJXI2Xiui19oLiLYrmJvBz0bCHe4s7U6OdmaumYhhfxpVErk1E1zAwxE8kdq_YD7ZCMRjKS9Tr6cbayIh9GKDwMLuW-LCdzOW2eQx-dTB7yXV53rpV34IBAcCE1IgmwwNIIW7E6Y.fdaAuj4qvXq-67f5ktOq7Coo8lggrMiB_TFFtluqDtI&dib_tag=se&keywords=Adafruit+Mini+Round+Robot+Chassis+Kit&qid=1766256581&sprefix=adafruit+mini+round+robot+chassis+kit+%2Caps%2C123&sr=8-10
|
|
32
|
+
https://github.com/ericmend/mini-drone/blob/master/README.md
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
vosk
|
|
38
|
+
|
|
39
|
+
https://github.com/sunfounder/picar-x/tree/v2.0/gpt_examples
|
|
40
|
+
https://github.com/sunfounder/picar-x/tree/v2.0/example
|
|
41
|
+
VOSK: https://docs.sunfounder.com/projects/picar-x-v20/en/latest/ai_interaction/python_voice_control.html
|
|
42
|
+
|
|
43
|
+
DONE why is 3 meters not marker: length its marker dimension
|
|
44
|
+
DONE how to handle time in the testing
|
|
45
|
+
repeat that/what/say again/say that again
|
|
46
|
+
make it say the howToCalibrate right from the start. maybe have some prime it call?!?!?!
|
|
47
|
+
convert from length to a some kind of standard number
|
|
48
|
+
shut up/dont talk/be quiet -> stop saying responses
|
|
49
|
+
|
|
50
|
+
use it to measure distances -> go forward. stop. how far was that
|
|
51
|
+
|
|
52
|
+
call this point a
|
|
53
|
+
move 5 feet
|
|
54
|
+
call this point b
|
|
55
|
+
moving between a and b is called patrol 1
|
|
56
|
+
do patrol 1 every 3 minutes
|
|
57
|
+
|
|
58
|
+
what is patrol 1
|
|
59
|
+
|
|
60
|
+
calibrate distance
|
|
61
|
+
stop
|
|
62
|
+
|
|
63
|
+
go forward slowly
|
|
64
|
+
stop
|
|
65
|
+
that was 2 feet
|
|
66
|
+
|
|
67
|
+
do a circle 2 feet in diameter every 2 minutes
|
|
68
|
+
|
|
69
|
+
this is jeff
|
|
70
|
+
say hi
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
say your names
|
|
74
|
+
car 1 do patrol one
|
|
75
|
+
car 1 and 2 go to point a
|
|
76
|
+
|
|
77
|
+
who car 1
|
|
78
|
+
|
|
79
|
+
just say the speed
|
|
80
|
+
|
|
81
|
+
go forward 2 meters
|
|
82
|
+
|
|
83
|
+
pan camera left slowly
|
|
84
|
+
do the cylon every 30 seconds
|
|
85
|
+
|
|
86
|
+
patrol one is forward 10 feet left 2 feet right 3 feet and back to the start
|
|
87
|
+
go forward 10 feet then go back to the start
|
|
88
|
+
|
|
89
|
+
go to the last point
|
|
90
|
+
go back 2 positions
|
|
91
|
+
|
|
92
|
+
call the first point start
|
|
93
|
+
call the second point fred
|
|
94
|
+
call the last point june
|
|
95
|
+
call the next point albert
|
|
96
|
+
|
|
97
|
+
pause for 4 seconds
|
|
98
|
+
|
|
99
|
+
this way is north
|
|
100
|
+
turn west
|
|
101
|
+
go three meters
|
|
102
|
+
turn south
|
|
103
|
+
go 1 foot
|
|
104
|
+
|
|
105
|
+
forward for 4 seconds
|
|
106
|
+
|
|
107
|
+
you are facing north. patrol between here and 100 feet to the west
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
function expectDirection(args) {
|
|
111
|
+
args.config.addSemantic({
|
|
112
|
+
match: ({context, isA}) => isA(context.marker, 'direction'),
|
|
113
|
+
apply: ({objects, context}) => {
|
|
114
|
+
objects.runCommand = true
|
|
115
|
+
objects.current.direction = context.marker
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function expectDistanceForMove(args) {
|
|
121
|
+
// TODO save id for recalibration
|
|
122
|
+
args.config.addSemantic({
|
|
123
|
+
match: ({context, isA}) => isA(context.marker, 'quantity') && !isA(context.unit.marker, 'unitPerUnit'),
|
|
124
|
+
apply: async ({context, objects, fragments, e}) => {
|
|
125
|
+
const instantiation = await fragments("quantity in meters", { quantity: context })
|
|
126
|
+
const result = await e(instantiation)
|
|
127
|
+
objects.runCommand = true
|
|
128
|
+
objects.current.distance = result.evalue.amount.evalue.evalue
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
^
|
|
135
|
+
y
|
|
136
|
+
|
|
|
137
|
+
90
|
|
138
|
+
|
|
|
139
|
+
-180/180 <--^--> 0 -- x ->
|
|
140
|
+
|
|
|
141
|
+
-90
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
class OverrideCheck {
|
|
145
|
+
constructor(base, checks) {
|
|
146
|
+
this.base = base
|
|
147
|
+
this.checks = checks
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
check(obj) {
|
|
151
|
+
for (const check of this.checks) {
|
|
152
|
+
if (obj[check] == this.base.prototype[check]) {
|
|
153
|
+
throw new Error(`For ${obj.constructor.name} you need to override ${check}`)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
L = track separation width (distance between the centers of the two tracks, measured side-to-side, in meters or whatever unit you like)
|
|
161
|
+
|
|
162
|
+
v = ground speed of each track (in m/s) — assume same magnitude but opposite directionsleft track forward at +v
|
|
163
|
+
right track backward at -v (or vice versa for the other direction)
|
|
164
|
+
|
|
165
|
+
θ = desired turn angle in radians (convert degrees to radians with θ_rad = θ_deg × π / 180)
|
|
166
|
+
|
|
167
|
+
The angular velocity ω (how fast the tank rotates, in rad/s) is:
|
|
168
|
+
|
|
169
|
+
ω = 2v / L
|
|
170
|
+
|
|
171
|
+
The time t needed to turn by angle θ is:
|
|
172
|
+
|
|
173
|
+
t = θ / ω = (θ × L) / (2v)
|
|
174
|
+
*/
|
|
175
|
+
class API {
|
|
176
|
+
constructor() {
|
|
177
|
+
this.overrideCheck = new OverrideCheck(API, ['forwardDrone', 'backwardDrone', 'rotateDrone', 'sonicDrone', 'tiltAngleDrone', 'panAngleDrone', 'stopDrone', 'saveCalibration'])
|
|
178
|
+
this.overriden = this.constructor !== API
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
initialize({ objects }) {
|
|
182
|
+
if (this.overriden) {
|
|
183
|
+
this.overrideCheck.check(this)
|
|
184
|
+
}
|
|
185
|
+
this._objects = objects
|
|
186
|
+
this._objects.defaultTime = { hour: 9, minute: 0, second: 0, millisecond: 0 }
|
|
187
|
+
this._objects.ordinal = 0
|
|
188
|
+
delete this.testDate
|
|
189
|
+
|
|
190
|
+
objects.calibration = {
|
|
191
|
+
speed: undefined, // meters per second
|
|
192
|
+
widthOfTankInMM: 188,
|
|
193
|
+
widthOfTreadInMM: 44,
|
|
194
|
+
}
|
|
195
|
+
objects.current = {
|
|
196
|
+
angleInRadians: 0
|
|
197
|
+
// direction: undefined, // direction to go if going
|
|
198
|
+
// power: undefined, // power
|
|
199
|
+
// ordinal // ordinal of the current point or the current point that the recent movement started at
|
|
200
|
+
}
|
|
201
|
+
objects.history = []
|
|
202
|
+
objects.calibration.isCalibrated = false
|
|
203
|
+
objects.sonicTest = 5
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
isCalibrated() {
|
|
207
|
+
return this._objects.calibration.isCalibrated
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
nextOrdinal() {
|
|
211
|
+
return this._objects.ordinal += 1
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
currentPoint() {
|
|
215
|
+
if (!this._objects.current.endTime) {
|
|
216
|
+
return null // in motion
|
|
217
|
+
}
|
|
218
|
+
const ordinal = this._objects.current.ordinal
|
|
219
|
+
const lastPoint = this.args.mentions({ context: { marker: 'point' }, condition: (context) => context.ordinal == ordinal })
|
|
220
|
+
|
|
221
|
+
const durationInSeconds = (this._objects.current.endTime - this._objects.current.startTime) / 1000
|
|
222
|
+
const speedInMetersPerSecond = (this._objects.current.power / this._objects.calibration.power) * this._objects.calibration.speedForward
|
|
223
|
+
const direction = this._objects.current.direction
|
|
224
|
+
const distanceInMeters = speedInMetersPerSecond * durationInSeconds * (direction == 'forward' ? 1 : -1)
|
|
225
|
+
const angleInRadians = this._objects.current.angleInRadians
|
|
226
|
+
const yPrime = lastPoint.point.y + distanceInMeters * Math.sin(angleInRadians)
|
|
227
|
+
const xPrime = lastPoint.point.x + distanceInMeters * Math.cos(angleInRadians)
|
|
228
|
+
return { x: xPrime, y: yPrime }
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
markCurrentPoint() {
|
|
232
|
+
const ordinal = this.nextOrdinal()
|
|
233
|
+
const point = this.currentPoint()
|
|
234
|
+
this.args.mentioned({ marker: 'point', ordinal, point })
|
|
235
|
+
this._objects.current.ordinal = ordinal
|
|
236
|
+
this._objects.current.endTime = null
|
|
237
|
+
this._objects.current.startTime = null
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async sendCommand() {
|
|
241
|
+
const stopAtDistance = async (direction, distanceMeters) => {
|
|
242
|
+
const speed_meters_per_second = direction == 'forward' ? this._objects.calibration.speedForward : this._objects.calibration.speedBackward
|
|
243
|
+
const duration_seconds = distanceMeters / speed_meters_per_second
|
|
244
|
+
await this.pause(duration_seconds, { batched: true })
|
|
245
|
+
await this.stop()
|
|
246
|
+
this.markCurrentPoint()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (this._objects.current.destination) {
|
|
250
|
+
const currentPoint = this.args.mentions({ context: { marker: 'point' } })
|
|
251
|
+
const polar = cartesianToPolar(currentPoint.point, this._objects.current.destination.point)
|
|
252
|
+
const destinationAngleInDegrees = radiansToDegrees(polar.angle)
|
|
253
|
+
let angleDelta = destinationAngleInRadians - this._objects.current.angleInRadians
|
|
254
|
+
if (angleDelta > 180) {
|
|
255
|
+
angleDelta -= 360
|
|
256
|
+
} else if (angleDelta < -180) {
|
|
257
|
+
angleDelta += 360
|
|
258
|
+
}
|
|
259
|
+
await this.rotate(angleDelta)
|
|
260
|
+
await this.forward(this._objects.current.power)
|
|
261
|
+
await stopAtDistance(polar.radius)
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const command = { power: this._objects.current.power, ...this._objects.current }
|
|
266
|
+
switch (command.direction) {
|
|
267
|
+
case 'forward':
|
|
268
|
+
await this.forward(command.power, { batched: command.distance })
|
|
269
|
+
break
|
|
270
|
+
case 'backward':
|
|
271
|
+
await this.backward(command.power, { batched: command.distance })
|
|
272
|
+
break
|
|
273
|
+
case 'right':
|
|
274
|
+
await this.rotate(-Math.PI/2)
|
|
275
|
+
break
|
|
276
|
+
case 'left':
|
|
277
|
+
await this.rotate(Math.PI/2)
|
|
278
|
+
break
|
|
279
|
+
case 'around':
|
|
280
|
+
await this.rotate(180)
|
|
281
|
+
break
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (command.distance) {
|
|
285
|
+
const distanceMeters = command.distance
|
|
286
|
+
await stopAtDistance(command.direction, distanceMeters)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
loadCalibration(calibration) {
|
|
291
|
+
Object.assign(this._objects.calibration, calibration)
|
|
292
|
+
this._objects.current.power = this._objects.calibration.minPower
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// override this to save the calibration to not have to run it over and over again and be annoing.
|
|
296
|
+
async saveCalibration(calibration) {
|
|
297
|
+
this._objects.history.push({ marker: 'history', saveCalibration: true })
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async forward(power, options) {
|
|
301
|
+
const time = await this.forwardDrone(power, options)
|
|
302
|
+
this._objects.current.startTime = time
|
|
303
|
+
this._objects.current.endTime = null
|
|
304
|
+
return time
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async backward(power, options) {
|
|
308
|
+
const time = await this.backwardDrone(power, options)
|
|
309
|
+
this._objects.current.startTime = time
|
|
310
|
+
this._objects.current.endTime = null
|
|
311
|
+
return time
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async sonic() {
|
|
315
|
+
return await this.sonicDrone()
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// TODO allow saying turn while its moving and make that one moves so you can go back wiggly?
|
|
319
|
+
async rotate(angleInRadians) {
|
|
320
|
+
await this.rotateDrone(angleInRadians)
|
|
321
|
+
this._objects.current.angleInRadians = (this._objects.current.angleInRadians + angleInRadians) % Math.PI
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async tiltAngle(angle) {
|
|
325
|
+
await tiltAngleDrone(angle)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async panAngle(angle) {
|
|
329
|
+
await panAngleDrone(angle)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async stop(options) {
|
|
333
|
+
const time = await this.stopDrone(options)
|
|
334
|
+
this._objects.current.endTime = time
|
|
335
|
+
return time
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async pause(durationInSeconds, options) {
|
|
339
|
+
await this.pauseDrone(durationInSeconds, options)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// subclass and override the remaining to call the drone
|
|
343
|
+
|
|
344
|
+
// this is for testing
|
|
345
|
+
async pauseDrone(durationInSeconds, options) {
|
|
346
|
+
this._objects.history.push({ marker: 'history', pause: durationInSeconds, ...options })
|
|
347
|
+
this.testDate = new Date(this.testDate.getTime() + (durationInSeconds-1)*1000)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
now() {
|
|
351
|
+
if (this.args.isProcess || this.args.isTest) {
|
|
352
|
+
if (!this.testDate) {
|
|
353
|
+
this.testDate = new Date(2025, 5, 29, 14, 52, 0)
|
|
354
|
+
}
|
|
355
|
+
this.testDate = new Date(this.testDate.getTime() + 1000)
|
|
356
|
+
return this.testDate
|
|
357
|
+
} else {
|
|
358
|
+
return new Date()
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// CMD_MOTOR#1000#1000#
|
|
363
|
+
async forwardDrone(power, options) {
|
|
364
|
+
const time = this.now()
|
|
365
|
+
this._objects.sonicTest -= 1
|
|
366
|
+
this._objects.history.push({ marker: 'history', direction: 'forward', power, time, ...options })
|
|
367
|
+
return time
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async backwardDrone(power, options) {
|
|
371
|
+
const time = this.now()
|
|
372
|
+
this._objects.sonicTest += 1
|
|
373
|
+
this._objects.history.push({ marker: 'history', direction: 'backward', power, time, ...options })
|
|
374
|
+
return time
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// -angle is counterclockwise
|
|
378
|
+
// +angle is clockwise
|
|
379
|
+
|
|
380
|
+
async rotateDrone(angleInRadians) {
|
|
381
|
+
this._objects.history.push({ marker: 'history', turn: angleInRadians })
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// distance in cm
|
|
385
|
+
async sonicDrone() {
|
|
386
|
+
this._objects.history.push({ marker: 'history', sonic: this._objects.sonicTest })
|
|
387
|
+
return this._objects.sonicTest
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async tiltAngleDrone(angle) {
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
async panAngleDrone(angle) {
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
async stopDrone(options) {
|
|
397
|
+
const time = this.now()
|
|
398
|
+
this._objects.history.push({ marker: 'history', power: 0, time, ...options })
|
|
399
|
+
return time
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const howToCalibrate = "Put an object in front of the drone. When you are ready say calibrate."
|
|
404
|
+
|
|
405
|
+
function askForProperty({
|
|
406
|
+
ask,
|
|
407
|
+
propertyPath,
|
|
408
|
+
contextPath=[],
|
|
409
|
+
query,
|
|
410
|
+
matchr,
|
|
411
|
+
oneShot=false,
|
|
412
|
+
}) {
|
|
413
|
+
ask({
|
|
414
|
+
where: where(),
|
|
415
|
+
oneShot,
|
|
416
|
+
|
|
417
|
+
matchq: ({ api, context, objects }) => !getValue(propertyPath, objects) && context.marker == 'controlEnd',
|
|
418
|
+
applyq: async ({ say, objects }) => {
|
|
419
|
+
return query
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
matchr,
|
|
423
|
+
applyr: async ({objects, context}) => {
|
|
424
|
+
setValue(propertyPath, objects, getValue(contextPath, context))
|
|
425
|
+
},
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// expectProperty
|
|
430
|
+
/*
|
|
431
|
+
function expectDirection(args) {
|
|
432
|
+
args.config.addSemantic({
|
|
433
|
+
match: ({context, isA}) => isA(context.marker, 'direction'),
|
|
434
|
+
apply: ({objects, context}) => {
|
|
435
|
+
objects.runCommand = true
|
|
436
|
+
objects.current.direction = context.marker
|
|
437
|
+
}
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function expectDistanceForMove(args) {
|
|
442
|
+
// TODO save id for recalibration
|
|
443
|
+
args.config.addSemantic({
|
|
444
|
+
match: ({context, isA}) => isA(context.marker, 'quantity') && !isA(context.unit.marker, 'unitPerUnit'),
|
|
445
|
+
apply: async ({context, objects, fragments, e}) => {
|
|
446
|
+
const instantiation = await fragments("quantity in meters", { quantity: context })
|
|
447
|
+
const result = await e(instantiation)
|
|
448
|
+
objects.runCommand = true
|
|
449
|
+
objects.current.distance = result.evalue.amount.evalue.evalue
|
|
450
|
+
}
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
*/
|
|
454
|
+
|
|
455
|
+
const template = {
|
|
456
|
+
fragments: [
|
|
457
|
+
"quantity in meters",
|
|
458
|
+
"quantity in meters per second",
|
|
459
|
+
],
|
|
460
|
+
configs: [
|
|
461
|
+
"drone is a concept",
|
|
462
|
+
//TODO "forward left, right, backward are directions",
|
|
463
|
+
"around, forward, left, right, and backward are directions",
|
|
464
|
+
"speed and power are properties",
|
|
465
|
+
"point is a concept",
|
|
466
|
+
// TODO fix/add this "position means point",
|
|
467
|
+
"points are nameable orderable and memorable",
|
|
468
|
+
(args) => {
|
|
469
|
+
expectDirection(args)
|
|
470
|
+
expectDistanceForMove(args)
|
|
471
|
+
|
|
472
|
+
args.config.addSemantic({
|
|
473
|
+
match: ({context, isA}) => isA(context.marker, 'quantity') && isA(context.unit.marker, 'unitPerUnit'),
|
|
474
|
+
apply: async ({context, objects, api, fragments, e}) => {
|
|
475
|
+
// send a command to the drone
|
|
476
|
+
const instantiation = await fragments("quantity in meters per second", { quantity: context })
|
|
477
|
+
const result = await e(instantiation)
|
|
478
|
+
const desired_speed = result.evalue.amount.evalue.evalue
|
|
479
|
+
const desired_power = objects.current.power * (desired_speed / objects.calibration.speedForward)
|
|
480
|
+
objects.runCommand = true
|
|
481
|
+
objects.current.power = desired_power
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
args.config.addSemantic({
|
|
486
|
+
match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlStart',
|
|
487
|
+
apply: ({context, objects, api}) => {
|
|
488
|
+
objects.runCommand = false
|
|
489
|
+
}
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
args.config.addSemantic({
|
|
493
|
+
// match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && (context.marker == 'controlEnd' || context.marker == 'controlBetween'),
|
|
494
|
+
match: ({context, objects, isA}) => objects.current.direction && objects.calibration.isCalibrated && context.marker == 'controlEnd',
|
|
495
|
+
apply: async ({context, objects, api}) => {
|
|
496
|
+
// send a command to the drone
|
|
497
|
+
if (objects.runCommand) {
|
|
498
|
+
await api.sendCommand()
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
operators: [
|
|
505
|
+
"([calibrate])",
|
|
506
|
+
"([turn] (direction))",
|
|
507
|
+
"([pause] ([number]))",
|
|
508
|
+
"([stop] ([drone|])?)",
|
|
509
|
+
"([go])",
|
|
510
|
+
"([toPoint|to] (point))",
|
|
511
|
+
],
|
|
512
|
+
bridges: [
|
|
513
|
+
{
|
|
514
|
+
id: "toPoint",
|
|
515
|
+
isA: ['preposition'],
|
|
516
|
+
bridge: "{ ...next(operator), operator: operator, point: after[0], interpolate: [{ property: 'operator' }, { property: 'point' }] }",
|
|
517
|
+
semantic: async ({objects, api, e, context}) => {
|
|
518
|
+
if (api.isCalibrated()) {
|
|
519
|
+
objects.runCommand = true
|
|
520
|
+
const point = await e(context.point)
|
|
521
|
+
objects.current.destination = point.evalue
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
{ id: "go" },
|
|
526
|
+
{
|
|
527
|
+
id: 'turn',
|
|
528
|
+
isA: ['verb'],
|
|
529
|
+
bridge: "{ ...next(operator), direction: after[0], interpolate: [{ context: operator }, { property: 'direction' }] }",
|
|
530
|
+
semantic: ({context, objects, api}) => {
|
|
531
|
+
objects.runCommand = true
|
|
532
|
+
objects.current.direction = context.direction.marker
|
|
533
|
+
},
|
|
534
|
+
// check: { marker: 'turn', exported: true, extra: ['direction'] }
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
id: 'calibrate',
|
|
538
|
+
words: ['configure'],
|
|
539
|
+
isA: ['verb'],
|
|
540
|
+
bridge: "{ ...next(operator), interpolate: [{ context: operator }] }",
|
|
541
|
+
semantic: async ({context, objects, api, mentioned}) => {
|
|
542
|
+
let power = 20
|
|
543
|
+
const moveTimeInSeconds = 0.5
|
|
544
|
+
let distanceInCM = 0
|
|
545
|
+
let startBackward
|
|
546
|
+
for (; power < 30; ++power) {
|
|
547
|
+
const start = await api.sonic();
|
|
548
|
+
await api.forward(power, { batched: true })
|
|
549
|
+
await api.pause(moveTimeInSeconds, { batched: true })
|
|
550
|
+
await api.stop()
|
|
551
|
+
const end = await api.sonic();
|
|
552
|
+
if (end !== start) {
|
|
553
|
+
distanceInCM = start - end
|
|
554
|
+
startBackward = end
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const metersPerSecondForward = (distanceInCM/100)/moveTimeInSeconds
|
|
560
|
+
|
|
561
|
+
// reset
|
|
562
|
+
|
|
563
|
+
await api.backward(power, { batched: true })
|
|
564
|
+
await api.pause(moveTimeInSeconds, { batched: true })
|
|
565
|
+
await api.stop()
|
|
566
|
+
const endBackward = await api.sonic();
|
|
567
|
+
|
|
568
|
+
const metersPerSecondBackward = ((endBackward-startBackward)/100)/moveTimeInSeconds
|
|
569
|
+
|
|
570
|
+
// console.log(`Distance ${distance} cm`)
|
|
571
|
+
// console.log(`Time ${moveTime} ms`)
|
|
572
|
+
// console.log(`M/S ${metersPerSecond}`)
|
|
573
|
+
|
|
574
|
+
objects.calibration.minPower = power
|
|
575
|
+
objects.calibration.power = power
|
|
576
|
+
objects.current.power = power
|
|
577
|
+
objects.calibration.speedForward = metersPerSecondForward
|
|
578
|
+
objects.calibration.speedBackward = metersPerSecondBackward
|
|
579
|
+
objects.calibration.isCalibrated = true
|
|
580
|
+
|
|
581
|
+
const ordinal = api.nextOrdinal()
|
|
582
|
+
mentioned({ marker: 'point', ordinal, point: { x: 0, y: 0 }, description: "start" })
|
|
583
|
+
objects.current.ordinal = ordinal
|
|
584
|
+
|
|
585
|
+
api.saveCalibration(objects.calibration)
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: 'pause',
|
|
590
|
+
isA: ['verb'],
|
|
591
|
+
bridge: "{ ...operator, time: after[0], interpolate: [{ context: operator }, { property: 'time' }] }",
|
|
592
|
+
semantic: async ({context}) => {
|
|
593
|
+
// why doesn't nodejs add a sleep function. I always have to look up how to do this because its not fucking memorable.
|
|
594
|
+
// function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
595
|
+
// await sleep(context.time.value*1000)
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
id: 'stop',
|
|
600
|
+
isA: ['verb'],
|
|
601
|
+
optional: {
|
|
602
|
+
1: "{ marker: 'drone' }",
|
|
603
|
+
},
|
|
604
|
+
bridge: "{ ...next(operator), object: after[0], interpolate: [{ context: operator }, { property: 'object' }] }",
|
|
605
|
+
semantic: async ({mentioned, context, objects, api, say}) => {
|
|
606
|
+
if (!objects.calibration.startTime) {
|
|
607
|
+
return // ignore
|
|
608
|
+
}
|
|
609
|
+
if (objects.calibration.speedForward) {
|
|
610
|
+
await api.stop()
|
|
611
|
+
api.markCurrentPoint()
|
|
612
|
+
} else {
|
|
613
|
+
const stopTime = await api.stop()
|
|
614
|
+
objects.calibration.endTime = stopTime
|
|
615
|
+
objects.calibration.duration = (objects.calibration.endTime - objects.calibration.startTime)/1000
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
],
|
|
620
|
+
generators: [
|
|
621
|
+
{
|
|
622
|
+
match: ({context}) => context.marker == 'help' && !context.paraphrase && context.isResponse,
|
|
623
|
+
apply: () => ''
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
semantics: [
|
|
627
|
+
|
|
628
|
+
],
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
knowledgeModule( {
|
|
634
|
+
config: { name: 'drone' },
|
|
635
|
+
includes: [nameable, ordinals, hierarchy, rates, help],
|
|
636
|
+
api: () => new API(),
|
|
637
|
+
|
|
638
|
+
module,
|
|
639
|
+
description: 'controlling a drone',
|
|
640
|
+
test: {
|
|
641
|
+
name: './drone.test.json',
|
|
642
|
+
contents: drone_tests,
|
|
643
|
+
checks: {
|
|
644
|
+
context: [
|
|
645
|
+
defaultContextCheck({ marker: 'point', exported: true, extra: ['ordinal', { property: 'point', check: ['x', 'y'] }, 'description', { property: 'stm', check: ['id', 'names'] }] }),
|
|
646
|
+
defaultContextCheck({ marker: 'turn', exported: true, extra: ['direction'] }),
|
|
647
|
+
defaultContextCheck({ marker: 'history', exported: true, extra: ['pause', 'direction', 'power', 'turn', 'time', 'sonic', 'saveCalibration', 'batched'] }),
|
|
648
|
+
defaultContextCheck(),
|
|
649
|
+
],
|
|
650
|
+
objects: [
|
|
651
|
+
{ km: 'stm' },
|
|
652
|
+
{ path: ['isCalibrated'] },
|
|
653
|
+
{ path: ['calibration'] },
|
|
654
|
+
{ path: ['history'] },
|
|
655
|
+
{ path: ['current'] },
|
|
656
|
+
{ path: ['runCommand'] },
|
|
657
|
+
],
|
|
658
|
+
}
|
|
659
|
+
},
|
|
660
|
+
instance,
|
|
661
|
+
template,
|
|
662
|
+
})
|