comparison org/worm_learn.clj @ 408:3b4012b42611

completed demonstration showing automatic partitioning of touch space based on experience.
author Robert McIntyre <rlm@mit.edu>
date Tue, 18 Mar 2014 21:28:04 -0400
parents bd6d03596ea8
children e6a7e80f885a
comparison
equal deleted inserted replaced
407:bd6d03596ea8 408:3b4012b42611
1 (ns org.aurellem.worm-learn 1 (ns org.aurellem.worm-learn
2 "General worm creation framework." 2 "General worm creation framework."
3 {:author "Robert McIntyre"} 3 {:author "Robert McIntyre"}
4 (:use (cortex world util import body sense 4 (:use (cortex world util import body sense
5 hearing touch vision proprioception movement)) 5 hearing touch vision proprioception movement
6 test))
6 (:import (com.jme3.math ColorRGBA Vector3f)) 7 (:import (com.jme3.math ColorRGBA Vector3f))
7 (:import java.io.File) 8 (:import java.io.File)
8 (:import com.jme3.audio.AudioNode) 9 (:import com.jme3.audio.AudioNode)
9 (:import com.aurellem.capture.RatchetTimer) 10 (:import com.aurellem.capture.RatchetTimer)
10 (:import (com.aurellem.capture Capture IsoTimer)) 11 (:import (com.aurellem.capture Capture IsoTimer))
11 (:import (com.jme3.math Vector3f ColorRGBA))) 12 (:import (com.jme3.math Vector3f ColorRGBA)))
12 13
13 (use 'clojure.pprint) 14 (use 'clojure.pprint)
14 15 (use 'clojure.set)
15 (dorun (cortex.import/mega-import-jme3)) 16 (dorun (cortex.import/mega-import-jme3))
16 (rlm.rlm-commands/help) 17 (rlm.rlm-commands/help)
17 18
18 (load-bullet) 19 (load-bullet)
19 20
245 (when experiences 246 (when experiences
246 (record-experience! 247 (record-experience!
247 experiences {:touch touch-data 248 experiences {:touch touch-data
248 :proprioception proprioception-data 249 :proprioception proprioception-data
249 :muscle muscle-data}) 250 :muscle muscle-data})
250 (if (curled? @experiences) (println "Curled")) 251 ;;(if (curled? @experiences) (println "Curled"))
251 ;;(if (straight? @experiences) (println "Straight")) 252 ;;(if (straight? @experiences) (println "Straight"))
252 ;; (println-repl 253 ;; (println-repl
253 ;; (apply format "%.2f %.2f %.2f %.2f %.2f\n" 254 ;; (apply format "%.2f %.2f %.2f %.2f %.2f\n"
254 ;; (map floor-contact touch-data))) 255 ;; (map floor-contact touch-data)))
255 256
284 285
285 [570 :lift-2 40] 286 [570 :lift-2 40]
286 [590 :lift-2 20] 287 [590 :lift-2 20]
287 [606 :lift-2 0] 288 [606 :lift-2 0]
288 289
289 [800 :lift-1 40] 290 [800 :lift-1 30]
290 [809 :lift-1 0] 291 [809 :lift-1 0]
291 292
292 [900 :roll-2 40] 293 [900 :roll-2 40]
293 [905 :roll-2 20] 294 [905 :roll-2 20]
294 [910 :roll-2 0] 295 [910 :roll-2 0]
300 [1100 :roll-2 40] 301 [1100 :roll-2 40]
301 [1105 :roll-2 20] 302 [1105 :roll-2 20]
302 [1110 :roll-2 0] 303 [1110 :roll-2 0]
303 ]) 304 ])
304 305
306 (defn single-worm-segment []
307 (load-blender-model "Models/worm/worm-single-segment.blend"))
308
305 (defn worm-segment-defaults [] 309 (defn worm-segment-defaults []
306 (let [direct-control (worm-direct-control worm-muscle-labels 40)] 310 (let [direct-control (worm-direct-control worm-muscle-labels 40)]
307 (merge (worm-world-defaults) 311 (merge (worm-world-defaults)
308 {:worm-model single-worm-segment 312 {:worm-model single-worm-segment
309 :view single-worm-segment-view 313 :view single-worm-segment-view
310 :motor-control 314 :motor-control
311 (motor-control-program 315 (motor-control-program
312 worm-single-segment-muscle-labels 316 worm-single-segment-muscle-labels
313 (touch-kinesthetics))}))) 317 (touch-kinesthetics))
314 318 :end-frame 1200})))
315 (defn single-worm-segment [] 319
316 (load-blender-model "Models/worm/worm-single-segment.blend")) 320 (def full-contact [(float 0.0) (float 0.1)])
317
318 321
319 (defn pure-touch? 322 (defn pure-touch?
320 "This is worm specific code to determine if a large region of touch 323 "This is worm specific code to determine if a large region of touch
321 sensors is either all on or all off." 324 sensors is either all on or all off."
322 [[coords touch :as touch-data]] 325 [[coords touch :as touch-data]]
323 (= (set (map first touch)) #{(float 0.1) (float 0.0)})) 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