Mercurial > cortex
comparison org/worm_learn.clj @ 415:af7945c27474
working on phi-space.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 19 Mar 2014 21:46:58 -0400 |
parents | 634795361af8 |
children | 9e52b6730fd0 |
comparison
equal
deleted
inserted
replaced
414:634795361af8 | 415:af7945c27474 |
---|---|
79 ;; These are scripts that direct the worm to move in two radically | 79 ;; These are scripts that direct the worm to move in two radically |
80 ;; different patterns -- a sinusoidal wiggling motion, and a curling | 80 ;; different patterns -- a sinusoidal wiggling motion, and a curling |
81 ;; motions that causes the worm to form a circle. | 81 ;; motions that causes the worm to form a circle. |
82 | 82 |
83 (def curl-script | 83 (def curl-script |
84 [[370 :d-flex 40] | 84 [[150 :d-flex 40] |
85 [600 :d-flex 0]]) | 85 [250 :d-flex 0]]) |
86 | 86 |
87 (def period 18) | 87 (def period 18) |
88 | 88 |
89 (def worm-muscle-labels | 89 (def worm-muscle-labels |
90 [:base-ex :base-flex | 90 [:base-ex :base-flex |
104 (def wiggle-script | 104 (def wiggle-script |
105 (mapcat gen-wiggle (repeat 4000 [:a-ex :a-flex]) | 105 (mapcat gen-wiggle (repeat 4000 [:a-ex :a-flex]) |
106 (range 100 1000000 (+ 3 (* period 2))))) | 106 (range 100 1000000 (+ 3 (* period 2))))) |
107 | 107 |
108 | 108 |
109 (defn shift-script [shift script] | |
110 (map (fn [[time label power]] [(+ time shift) label power]) | |
111 script)) | |
112 | |
113 (def do-all-the-things | |
114 (concat | |
115 curl-script | |
116 [[300 :d-ex 40] | |
117 [320 :d-ex 0]] | |
118 (shift-script 280 (take 16 wiggle-script)))) | |
119 | |
109 ;; Normally, we'd use unsupervised/supervised machine learning to pick | 120 ;; Normally, we'd use unsupervised/supervised machine learning to pick |
110 ;; out the defining features of the different actions available to the | 121 ;; out the defining features of the different actions available to the |
111 ;; worm. For this project, I am going to explicitely define functions | 122 ;; worm. For this project, I am going to explicitely define functions |
112 ;; that recognize curling and wiggling respectively. These functions | 123 ;; that recognize curling and wiggling respectively. These functions |
113 ;; are defined using all the information available from an embodied | 124 ;; are defined using all the information available from an embodied |
116 ;; invariance are complete non-issues here. This is the advantage of | 127 ;; invariance are complete non-issues here. This is the advantage of |
117 ;; body-centered action recognition and what I hope to show with this | 128 ;; body-centered action recognition and what I hope to show with this |
118 ;; thesis. | 129 ;; thesis. |
119 | 130 |
120 | 131 |
121 (defn straight? | 132 ;; curled? relies on proprioception, resting? relies on touch, |
122 "Is the worm straight?" | 133 ;; wiggling? relies on a fourier analysis of muscle contraction, and |
123 [experiences] | 134 ;; grand-circle? relies on touch and reuses curled? as a gaurd. |
124 (every? | |
125 (fn [[_ _ bend]] | |
126 (< (Math/sin bend) 0.05)) | |
127 (:proprioception (peek experiences)))) | |
128 | 135 |
129 (defn curled? | 136 (defn curled? |
130 "Is the worm curled up?" | 137 "Is the worm curled up?" |
131 [experiences] | 138 [experiences] |
132 (every? | 139 (every? |
133 (fn [[_ _ bend]] | 140 (fn [[_ _ bend]] |
134 (> (Math/sin bend) 0.64)) | 141 (> (Math/sin bend) 0.64)) |
135 (:proprioception (peek experiences)))) | 142 (:proprioception (peek experiences)))) |
136 | 143 |
137 (defn grand-circle? | |
138 "Does the worm form a majestic circle (one end touching the other)?" | |
139 [experiences] | |
140 (and (curled? experiences) | |
141 true)) ;; TODO: add code here. | |
142 | |
143 (defn vector:last-n [v n] | |
144 (let [c (count v)] | |
145 (if (< c n) v | |
146 (subvec v (- c n) c)))) | |
147 | |
148 (defn touch-average [[coords touch]] | 144 (defn touch-average [[coords touch]] |
149 (/ (average (map first touch)) (average (map second touch)))) | 145 (/ (average (map first touch)) (average (map second touch)))) |
150 | 146 |
151 (defn rect-region [[x0 y0] [x1 y1]] | 147 (defn rect-region [[x0 y0] [x1 y1]] |
152 (vec | 148 (vec |
153 (for [x (range x0 (inc x1)) | 149 (for [x (range x0 (inc x1)) |
154 y (range y0 (inc y1))] | 150 y (range y0 (inc y1))] |
155 [x y]))) | 151 [x y]))) |
156 | 152 |
157 (def worm-segment-touch-bottom (rect-region [8 15] [14 22])) | 153 (def worm-segment-bottom (rect-region [8 15] [14 22])) |
158 | 154 |
159 (defn contact | 155 (defn contact |
160 "Determine how much contact a particular worm segment has with | 156 "Determine how much contact a particular worm segment has with |
161 other objects. Returns a value between 0 and 1, where 1 is full | 157 other objects. Returns a value between 0 and 1, where 1 is full |
162 contact and 0 is no contact." | 158 contact and 0 is no contact." |
163 [[coords contact :as touch]] | 159 [touch-region [coords contact :as touch]] |
164 (-> (zipmap coords contact) | 160 (-> (zipmap coords contact) |
165 (select-keys worm-segment-touch-bottom) | 161 (select-keys touch-region) |
166 (vals) | 162 (vals) |
167 (#(map first %)) | 163 (#(map first %)) |
168 (average) | 164 (average) |
169 (* 10) | 165 (* 10) |
170 (- 1) | 166 (- 1) |
171 (Math/abs))) | 167 (Math/abs))) |
172 | 168 |
169 (defn resting? | |
170 "Is the worm straight?" | |
171 [experiences] | |
172 (every? | |
173 (fn [touch-data] | |
174 (< 0.9 (contact worm-segment-bottom touch-data))) | |
175 (:touch (peek experiences)))) | |
176 | |
177 (defn vector:last-n [v n] | |
178 (let [c (count v)] | |
179 (if (< c n) v | |
180 (subvec v (- c n) c)))) | |
181 | |
173 (defn fft [nums] | 182 (defn fft [nums] |
174 (map | 183 (map |
175 #(.getReal %) | 184 #(.getReal %) |
176 (.transform | 185 (.transform |
177 (FastFourierTransformer. DftNormalization/STANDARD) | 186 (FastFourierTransformer. DftNormalization/STANDARD) |
179 | 188 |
180 (def indexed (partial map-indexed vector)) | 189 (def indexed (partial map-indexed vector)) |
181 | 190 |
182 (defn max-indexed [s] | 191 (defn max-indexed [s] |
183 (first (sort-by (comp - second) (indexed s)))) | 192 (first (sort-by (comp - second) (indexed s)))) |
184 | |
185 | 193 |
186 (defn wiggling? | 194 (defn wiggling? |
187 "Is the worm wiggling?" | 195 "Is the worm wiggling?" |
188 [experiences] | 196 [experiences] |
189 (let [analysis-interval 0x40] | 197 (let [analysis-interval 0x40] |
194 (map :muscle (vector:last-n experiences analysis-interval)) | 202 (map :muscle (vector:last-n experiences analysis-interval)) |
195 base-activity | 203 base-activity |
196 (map #(- (% a-flex) (% a-ex)) muscle-activity)] | 204 (map #(- (% a-flex) (% a-ex)) muscle-activity)] |
197 (= 2 | 205 (= 2 |
198 (first | 206 (first |
199 (max-indexed (map #(Math/abs %) (take 20 (fft base-activity)))))))))) | 207 (max-indexed |
200 | 208 (map #(Math/abs %) |
201 ;; (println-repl | 209 (take 20 (fft base-activity)))))))))) |
202 ;; (apply format "%d %.2f" | 210 |
203 ;; (first (sort-by | 211 (def worm-segment-bottom-tip (rect-region [15 15] [22 22])) |
204 ;; (comp - second) | 212 |
205 ;; (indexed (take 20 )))))))))) | 213 (def worm-segment-top-tip (rect-region [0 15] [7 22])) |
206 | 214 |
207 ;; (println-repl | 215 (defn grand-circle? |
208 ;; (apply | 216 "Does the worm form a majestic circle (one end touching the other)?" |
209 ;; format | 217 [experiences] |
210 ;; (apply str (repeat analysis-interval "%5.1f")) | 218 (and true;; (curled? experiences) |
211 ;; (fft base-activity))) | 219 (let [worm-touch (:touch (peek experiences)) |
212 | 220 tail-touch (worm-touch 0) |
213 ;; ;;(println-repl (last base-activity)) | 221 head-touch (worm-touch 4)] |
214 ;; ))) | 222 (and (< 0.55 (contact worm-segment-bottom-tip tail-touch)) |
215 | 223 (< 0.55 (contact worm-segment-top-tip head-touch)))))) |
216 | |
217 | 224 |
218 (def standard-world-view | 225 (def standard-world-view |
219 [(Vector3f. 4.207176, -3.7366982, 3.0816958) | 226 [(Vector3f. 4.207176, -3.7366982, 3.0816958) |
220 (Quaternion. 0.11118768, 0.87678415, 0.24434438, -0.3989771)]) | 227 (Quaternion. 0.11118768, 0.87678415, 0.24434438, -0.3989771)]) |
221 | 228 |
242 (.mkdir file)) | 249 (.mkdir file)) |
243 file) | 250 file) |
244 | 251 |
245 (defn record-experience! [experiences data] | 252 (defn record-experience! [experiences data] |
246 (swap! experiences #(conj % data))) | 253 (swap! experiences #(conj % data))) |
254 | |
255 | |
256 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
257 ;;;;;;;; Phi-Space ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
258 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
259 | |
260 (defn generate-phi-space [] | |
261 (let [experiences (atom [])] | |
262 (run-world | |
263 (apply-map | |
264 worm-world | |
265 (merge | |
266 (worm-world-defaults) | |
267 {:end-frame 700 | |
268 :motor-control | |
269 (motor-control-program worm-muscle-labels do-all-the-things) | |
270 :experiences experiences}))) | |
271 @experiences)) | |
272 | |
273 | |
274 (defn bin [digits] | |
275 (fn [angles] | |
276 (->> angles | |
277 (flatten) | |
278 (map (juxt #(Math/sin %) #(Math/cos %))) | |
279 (flatten) | |
280 (mapv #(Math/round (* % (Math/pow 10 (dec digits)))))))) | |
281 | |
282 ;; k-nearest neighbors with spatial binning. | |
283 (defn gen-phi-scan [phi-space] | |
284 (let [bin-keys (reverse (map bin (range 4))) | |
285 bin-maps | |
286 (map (fn [bin-key phi-space] | |
287 (group-by (comp bin-key :proprioception) phi-space)) | |
288 bin-keys (repeat phi-space)) | |
289 lookups (map (fn [bin-key bin-map] | |
290 (fn [proprio] (bin-map (bin-key proprio)))) | |
291 bin-keys bin-maps)] | |
292 (fn lookup [proprio-data] | |
293 (some #(% proprio-data) lookups)))) | |
294 | |
295 | |
296 | |
297 | |
247 | 298 |
248 (defn worm-world | 299 (defn worm-world |
249 [& {:keys [record motor-control keybindings view experiences | 300 [& {:keys [record motor-control keybindings view experiences |
250 worm-model end-frame] :as settings}] | 301 worm-model end-frame] :as settings}] |
251 (let [{:keys [record motor-control keybindings view experiences | 302 (let [{:keys [record motor-control keybindings view experiences |
280 (fn [world tpf] | 331 (fn [world tpf] |
281 (if (and end-frame (> (.getTime timer) end-frame)) | 332 (if (and end-frame (> (.getTime timer) end-frame)) |
282 (.stop world)) | 333 (.stop world)) |
283 (let [muscle-data (vec (motor-control muscles)) | 334 (let [muscle-data (vec (motor-control muscles)) |
284 proprioception-data (prop) | 335 proprioception-data (prop) |
285 touch-data (map #(% (.getRootNode world)) touch)] | 336 touch-data (mapv #(% (.getRootNode world)) touch)] |
286 (when experiences | 337 (when experiences |
287 (record-experience! | 338 (record-experience! |
288 experiences {:touch touch-data | 339 experiences {:touch touch-data |
289 :proprioception proprioception-data | 340 :proprioception proprioception-data |
290 :muscle muscle-data}) | 341 :muscle muscle-data}) |
291 ;;(if (curled? @experiences) (println "Curled")) | 342 (cond |
292 ;;(if (straight? @experiences) (println "Straight")) | 343 (grand-circle? @experiences) (println "Grand Circle") |
293 ;; (println-repl | 344 (curled? @experiences) (println "Curled") |
294 ;; (apply format "%.2f %.2f %.2f %.2f %.2f\n" | 345 (wiggling? @experiences) (println "Wiggling") |
295 ;; (map contact touch-data))) | 346 (resting? @experiences) (println "Resting")) |
296 (wiggling? @experiences) | |
297 ) | 347 ) |
298 (muscle-display | 348 (muscle-display |
299 muscle-data | 349 muscle-data |
300 (if record (dir! (File. record "muscle")))) | 350 (if record (dir! (File. record "muscle")))) |
301 (prop-display | 351 (prop-display |