Uses 911K of libraries. Click here for Pure Java version (9366L/50K).
1 | !7 |
2 | |
3 | cmodule RunVectorSDK > DynPrintLogAndEnabled { |
4 | switchable bool printImages; |
5 | switchable bool keepControl; |
6 | switchable double checkTouchedInterval = 30.0; // seconds. also for checking connection liveness |
7 | S toSay; |
8 | |
9 | transient Process process; |
10 | transient PrintStream out; |
11 | transient WithTimestamp<Bool> isBeingTouched; |
12 | |
13 | start-thread { |
14 | dm_registerAs_direct vectorSDK(); |
15 | dm_reloadOnFieldChange enabled(); |
16 | dm_onFieldChange keepControl(r { if (keepControl) requestControl(); else releaseControl(); }); |
17 | |
18 | doEvery(checkTouchedInterval, r { |
19 | checkBeingTouched(); |
20 | restartIfNoEvents(); |
21 | }); |
22 | |
23 | _startSDK(); |
24 | } |
25 | |
26 | void _startSDK q { |
27 | cleanMeUp_process(); |
28 | if (!enabled) ret; |
29 | //File script = userDir("vector-sdk/cam-stream-to-stdout.py"); |
30 | File script = userDir("vector-sdk/control-from-java-v2.py"); |
31 | assertFileExists(script); |
32 | makeExecutable(script); |
33 | |
34 | print("Calling " + script); |
35 | process = Runtime.getRuntime().exec(platformQuoteOpt(script)); |
36 | print("SDK process started"); |
37 | print("PID: " + getOpt(process, "pid")); |
38 | |
39 | drainErrorStreamToConsole(process, line -> enabled, lambda0 enter); |
40 | out = new PrintStream(process.getOutputStream()); |
41 | |
42 | isBeingTouched = WithTimestamp(null); |
43 | |
44 | dm_startThread("SDK Input", r { |
45 | DataInputStream in = new(process.getInputStream()); |
46 | S line; |
47 | while ((line = in.readLine()) != null) { |
48 | if (enabled) { |
49 | vmBus_send vectorSDK_gotLine(module(), line); |
50 | if (eqic(line, "Connected to vector")) { |
51 | vmBus_send vectorSDK_connected(module()); |
52 | if (keepControl) |
53 | requestControl(); |
54 | checkBeingTouched(); |
55 | } |
56 | if (printImages || !startsWith(line, "img:")) |
57 | print("Got line: " + takeFirst(100, line)); |
58 | if (eq(line, "Unknown error")) |
59 | _startSDK(); |
60 | if (startsWith(line, "touch:")) |
61 | isBeingTouched = WithTimestamp(match("true", afterColon(line))); |
62 | } |
63 | } |
64 | }); |
65 | } |
66 | |
67 | void cleanMeUp_process { |
68 | if (process != null) { |
69 | print("Stopping SDK process"); |
70 | process.destroy/*Forcibly*/(); |
71 | process = null; |
72 | print("Stopped SDK process, hopefully"); |
73 | } |
74 | } |
75 | |
76 | visual centerAndSouthWithMargin(super, |
77 | westAndCenterWithMargins( |
78 | dm_checkBox keepControl(), |
79 | dm_textFieldAndSubmit_q toSay(r { say(toSay) }, buttonText := "Say"))); |
80 | |
81 | // API |
82 | |
83 | void eval(S pythonCode) { |
84 | if (out == null || empty(pythonCode)) ret; |
85 | out.println(jsonEncode(pythonCode)); |
86 | out.flush(); |
87 | } |
88 | |
89 | void evalWithControl(S pythonCode) { |
90 | if (keepControl) |
91 | ret with eval(pythonCode); |
92 | print("evalWithControl: " + pythonCode); |
93 | eval("with anki_vector.Robot() as robot2:\n" + |
94 | indent(4, jreplace(pythonCode, "robot", "robot2"))); |
95 | } |
96 | |
97 | // returns true if (probably) successful |
98 | bool say(S s) { |
99 | if (out == null) false; |
100 | s = newLinesToSpaces_trim(s); |
101 | if (empty(s)) true; |
102 | print("Making Vector say: " + s); |
103 | // with release_control, there is "unknown error" after first utterance |
104 | /*eval(autoUnindent(linesLL( |
105 | "robot.conn.request_control(timeout=5.0)", |
106 | "robot.behavior.say_text(" + pythonQuote(s) + ")", |
107 | //"robot.conn.release_control()" |
108 | )));*/ |
109 | /*eval("with anki_vector.Robot() as robot2:\n" + |
110 | " robot2.behavior.say_text(" + pythonQuote(s) + ")");*/ |
111 | evalWithControl("robot.behavior.say_text(" + pythonQuote(s) + ")"); |
112 | true; |
113 | } |
114 | |
115 | void playWAV(File wav) { |
116 | print("Playing: " + wav); |
117 | if (!is16KMonoWAVFile(wav)) { |
118 | print("Converting to 16k"); |
119 | File wav2 = javaxCachesDir("vector.wav"); |
120 | deleteFile(wav2); |
121 | ffmpeg_toMonoAudio_16k(wav, wav2); |
122 | if (!fileExists(wav2)) fail("Conversion failed"); |
123 | wav = wav2; |
124 | } |
125 | int volume = 75; |
126 | evalWithControl("robot.audio.stream_wav_file(" + pythonQuote(f2s(wav)) + ", " + volume + ")"; |
127 | } |
128 | |
129 | void startCamStream { |
130 | eval("camFeedOn()"); |
131 | } |
132 | |
133 | void checkBeingTouched() { |
134 | eval([[print("touch: " + str(robot.touch.last_sensor_reading.is_being_touched))]]); |
135 | } |
136 | |
137 | // request control in main connection. currently not sure how to undo |
138 | void requestControl() { |
139 | eval("robot.conn.request_control()"); |
140 | } |
141 | |
142 | // Not working in tests? |
143 | void releaseControl() { |
144 | eval("robot.conn.release_control()"); |
145 | } |
146 | |
147 | void restartIfNoEvents() { |
148 | if (isBeingTouched != null && isBeingTouched.olderThanSeconds(checkTouchedInterval*2.0)) { |
149 | isBeingTouched = WithTimestamp(null); |
150 | _startSDK(); |
151 | } |
152 | } |
153 | } |
Began life as a copy of #1027258
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027266 |
Snippet name: | Run Vector SDK v2 [can eval any Python code] |
Eternal ID of this version: | #1027266/43 |
Text MD5: | 4bc95525898a7535ee94c0bbcd6190ad |
Transpilation MD5: | 8365e6508c1fadffebbe8fd305633a08 |
Author: | stefan |
Category: | javax / anki vector |
Type: | JavaX source code (Dynamic Module) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-04-05 02:01:55 |
Source code size: | 4731 bytes / 153 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 317 / 5606 |
Version history: | 42 change(s) |
Referenced in: | [show references] |