diff 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
line wrap: on
line diff
     1.1 --- a/org/worm_learn.clj	Tue Mar 18 19:53:42 2014 -0400
     1.2 +++ b/org/worm_learn.clj	Tue Mar 18 21:28:04 2014 -0400
     1.3 @@ -2,7 +2,8 @@
     1.4    "General worm creation framework."
     1.5    {:author "Robert McIntyre"}
     1.6    (:use (cortex world util import body sense
     1.7 -                hearing touch vision proprioception movement))
     1.8 +                hearing touch vision proprioception movement
     1.9 +                test))
    1.10    (:import (com.jme3.math ColorRGBA Vector3f))
    1.11    (:import java.io.File)
    1.12    (:import com.jme3.audio.AudioNode)
    1.13 @@ -11,7 +12,7 @@
    1.14    (:import (com.jme3.math Vector3f ColorRGBA)))
    1.15  
    1.16  (use 'clojure.pprint)
    1.17 -
    1.18 +(use 'clojure.set)
    1.19  (dorun (cortex.import/mega-import-jme3))
    1.20  (rlm.rlm-commands/help)
    1.21  
    1.22 @@ -247,7 +248,7 @@
    1.23                experiences {:touch touch-data
    1.24                             :proprioception proprioception-data
    1.25                             :muscle muscle-data})
    1.26 -             (if (curled? @experiences) (println "Curled"))
    1.27 +             ;;(if (curled? @experiences) (println "Curled"))
    1.28               ;;(if (straight? @experiences)    (println "Straight"))
    1.29               ;; (println-repl
    1.30               ;;  (apply format "%.2f %.2f %.2f %.2f %.2f\n"
    1.31 @@ -286,7 +287,7 @@
    1.32     [590 :lift-2 20]
    1.33     [606 :lift-2  0]
    1.34  
    1.35 -   [800 :lift-1 40]
    1.36 +   [800 :lift-1 30]
    1.37     [809 :lift-1 0]
    1.38  
    1.39     [900 :roll-2 40]
    1.40 @@ -302,6 +303,9 @@
    1.41     [1110 :roll-2  0]
    1.42     ])
    1.43  
    1.44 +(defn single-worm-segment []
    1.45 +  (load-blender-model "Models/worm/worm-single-segment.blend"))
    1.46 +
    1.47  (defn worm-segment-defaults []
    1.48    (let [direct-control (worm-direct-control worm-muscle-labels 40)]
    1.49      (merge (worm-world-defaults)
    1.50 @@ -310,14 +314,82 @@
    1.51              :motor-control
    1.52              (motor-control-program
    1.53               worm-single-segment-muscle-labels
    1.54 -             (touch-kinesthetics))})))
    1.55 +             (touch-kinesthetics))
    1.56 +            :end-frame 1200})))
    1.57  
    1.58 -(defn single-worm-segment []
    1.59 -  (load-blender-model "Models/worm/worm-single-segment.blend"))
    1.60 -
    1.61 +(def full-contact [(float 0.0) (float 0.1)])
    1.62  
    1.63  (defn pure-touch?
    1.64    "This is worm specific code to determine if a large region of touch
    1.65     sensors is either all on or all off."
    1.66    [[coords touch :as touch-data]]
    1.67 -  (= (set (map first touch)) #{(float 0.1)  (float 0.0)}))
    1.68 \ No newline at end of file
    1.69 +  (= (set (map first touch)) (set full-contact)))
    1.70 +
    1.71 +(defn remove-similar
    1.72 +  [coll]
    1.73 +  (loop [result () coll (sort-by (comp - count) coll)]
    1.74 +    (if (empty? coll) result
    1.75 +        (let  [x  (first coll)
    1.76 +               xs (rest coll)
    1.77 +               c (count x)]
    1.78 +          (if (some
    1.79 +               (fn [other-set]
    1.80 +                 (let [oc (count other-set)]
    1.81 +                   (< (- (count (union other-set x)) c) (* oc 0.1))))
    1.82 +               xs)
    1.83 +            (recur result xs)
    1.84 +            (recur (cons x result) xs))))))
    1.85 +
    1.86 +
    1.87 +(defn rect-region [[x0 y0] [x1 y1]]
    1.88 +  (vec
    1.89 +   (for [x (range x0 (inc x1))
    1.90 +         y (range y0 (inc y1))]
    1.91 +     [x y])))
    1.92 +
    1.93 +(def all-touch-coordinates
    1.94 +  (concat
    1.95 +   (rect-region [0  15] [7  22])
    1.96 +   (rect-region [8   0] [14 29])
    1.97 +   (rect-region [15 15] [22 22])))
    1.98 +
    1.99 +(defn view-touch-region [coords]
   1.100 +  (let [touched-region
   1.101 +        (reduce
   1.102 +         (fn [m k]
   1.103 +           (assoc m k [0.0 0.1]))
   1.104 +         (zipmap all-touch-coordinates (repeat [0.1 0.1])) coords)
   1.105 +        data
   1.106 +        [[(vec (keys touched-region)) (vec (vals touched-region))]]
   1.107 +        touch-display (view-touch)]
   1.108 +    (touch-display data)
   1.109 +    (touch-display data)))
   1.110 +
   1.111 +(defn learn-touch-regions []
   1.112 +  (let [experiences (atom [])
   1.113 +        world (apply-map
   1.114 +               worm-world
   1.115 +               (assoc (worm-segment-defaults)
   1.116 +                 :experiences experiences))]
   1.117 +    (run-world world)
   1.118 +    (->>
   1.119 +     @experiences
   1.120 +     (drop 175)
   1.121 +     ;; access the single segment's touch data
   1.122 +     (map (comp first :touch))
   1.123 +     ;; only deal with "pure" touch data to determine surfaces
   1.124 +     (filter pure-touch?)
   1.125 +     ;; associate coordinates with touch values
   1.126 +     (map (partial apply zipmap))
   1.127 +     ;; select those regions where contact is being made
   1.128 +     (map (partial group-by second))
   1.129 +     (map #(get % full-contact))
   1.130 +     (map (partial map first))
   1.131 +     ;; remove redundant/subset regions
   1.132 +     (map set)
   1.133 +     remove-similar)))
   1.134 +
   1.135 +(defn learn-and-view-touch-regions []
   1.136 +  (map view-touch-region
   1.137 +       (learn-touch-regions)))
   1.138 +