comparison org/worm_learn.clj @ 410:e6a7e80f885a

refactor, fix null pointer bug.
author Robert McIntyre <rlm@mit.edu>
date Tue, 18 Mar 2014 22:29:03 -0400
parents 3b4012b42611
children a331d5ff73e0
comparison
equal deleted inserted replaced
409:ea524e4d8f8d 410:e6a7e80f885a
194 :record nil 194 :record nil
195 :experiences nil 195 :experiences nil
196 :worm-model worm-model 196 :worm-model worm-model
197 :end-frame nil})) 197 :end-frame nil}))
198 198
199
200 (defn dir! [file] 199 (defn dir! [file]
201 (if (not (.exists file)) 200 (if-not (.exists file)
202 (.mkdir file)) 201 (.mkdir file))
203 file) 202 file)
204 203
205 (defn record-experience! [experiences data] 204 (defn record-experience! [experiences data]
206 (swap! experiences #(conj % data))) 205 (swap! experiences #(conj % data)))
236 world 235 world
237 (dir! (File. record "main-view")))) 236 (dir! (File. record "main-view"))))
238 (speed-up world) 237 (speed-up world)
239 (light-up-everything world)) 238 (light-up-everything world))
240 (fn [world tpf] 239 (fn [world tpf]
241 (if (> (.getTime timer) end-frame) 240 (if (and end-frame (> (.getTime timer) end-frame))
242 (.stop world)) 241 (.stop world))
243 (let [muscle-data (motor-control muscles) 242 (let [muscle-data (motor-control muscles)
244 proprioception-data (prop) 243 proprioception-data (prop)
245 touch-data (map #(% (.getRootNode world)) touch)] 244 touch-data (map #(% (.getRootNode world)) touch)]
246 (when experiences 245 (when experiences
264 (touch-display 263 (touch-display
265 touch-data 264 touch-data
266 (if record (dir! (File. record "touch"))))))))) 265 (if record (dir! (File. record "touch")))))))))
267 266
268 267
269 ;; A demonstration of self organiging touch maps through experience. 268
270
271 (def single-worm-segment-view
272 [(Vector3f. 2.0681207, -6.1406755, 1.6106138)
273 (Quaternion. -0.15558705, 0.843615, -0.3428654, -0.38281822)])
274
275 (def worm-single-segment-muscle-labels
276 [:lift-1 :lift-2 :roll-1 :roll-2])
277
278 (defn touch-kinesthetics []
279 [[170 :lift-1 40]
280 [190 :lift-1 20]
281 [206 :lift-1 0]
282
283 [400 :lift-2 40]
284 [410 :lift-2 0]
285
286 [570 :lift-2 40]
287 [590 :lift-2 20]
288 [606 :lift-2 0]
289
290 [800 :lift-1 30]
291 [809 :lift-1 0]
292
293 [900 :roll-2 40]
294 [905 :roll-2 20]
295 [910 :roll-2 0]
296
297 [1000 :roll-2 40]
298 [1005 :roll-2 20]
299 [1010 :roll-2 0]
300
301 [1100 :roll-2 40]
302 [1105 :roll-2 20]
303 [1110 :roll-2 0]
304 ])
305
306 (defn single-worm-segment []
307 (load-blender-model "Models/worm/worm-single-segment.blend"))
308
309 (defn worm-segment-defaults []
310 (let [direct-control (worm-direct-control worm-muscle-labels 40)]
311 (merge (worm-world-defaults)
312 {:worm-model single-worm-segment
313 :view single-worm-segment-view
314 :motor-control
315 (motor-control-program
316 worm-single-segment-muscle-labels
317 (touch-kinesthetics))
318 :end-frame 1200})))
319
320 (def full-contact [(float 0.0) (float 0.1)])
321
322 (defn pure-touch?
323 "This is worm specific code to determine if a large region of touch
324 sensors is either all on or all off."
325 [[coords touch :as touch-data]]
326 (= (set (map first touch)) (set full-contact)))
327
328 (defn remove-similar
329 [coll]
330 (loop [result () coll (sort-by (comp - count) coll)]
331 (if (empty? coll) result
332 (let [x (first coll)
333 xs (rest coll)
334 c (count x)]
335 (if (some
336 (fn [other-set]
337 (let [oc (count other-set)]
338 (< (- (count (union other-set x)) c) (* oc 0.1))))
339 xs)
340 (recur result xs)
341 (recur (cons x result) xs))))))
342
343
344 (defn rect-region [[x0 y0] [x1 y1]]
345 (vec
346 (for [x (range x0 (inc x1))
347 y (range y0 (inc y1))]
348 [x y])))
349
350 (def all-touch-coordinates
351 (concat
352 (rect-region [0 15] [7 22])
353 (rect-region [8 0] [14 29])
354 (rect-region [15 15] [22 22])))
355
356 (defn view-touch-region [coords]
357 (let [touched-region
358 (reduce
359 (fn [m k]
360 (assoc m k [0.0 0.1]))
361 (zipmap all-touch-coordinates (repeat [0.1 0.1])) coords)
362 data
363 [[(vec (keys touched-region)) (vec (vals touched-region))]]
364 touch-display (view-touch)]
365 (touch-display data)
366 (touch-display data)))
367
368 (defn learn-touch-regions []
369 (let [experiences (atom [])
370 world (apply-map
371 worm-world
372 (assoc (worm-segment-defaults)
373 :experiences experiences))]
374 (run-world world)
375 (->>
376 @experiences
377 (drop 175)
378 ;; access the single segment's touch data
379 (map (comp first :touch))
380 ;; only deal with "pure" touch data to determine surfaces
381 (filter pure-touch?)
382 ;; associate coordinates with touch values
383 (map (partial apply zipmap))
384 ;; select those regions where contact is being made
385 (map (partial group-by second))
386 (map #(get % full-contact))
387 (map (partial map first))
388 ;; remove redundant/subset regions
389 (map set)
390 remove-similar)))
391
392 (defn learn-and-view-touch-regions []
393 (map view-touch-region
394 (learn-touch-regions)))
395