changeset 259:7cac5ef852e3

proprioception rough draft complete.
author Robert McIntyre <rlm@mit.edu>
date Tue, 14 Feb 2012 02:28:25 -0700
parents f4b67005b702
children 959127e21f81
files org/proprioception.org
diffstat 1 files changed, 182 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/proprioception.org	Tue Feb 14 00:39:16 2012 -0700
     1.2 +++ b/org/proprioception.org	Tue Feb 14 02:28:25 2012 -0700
     1.3 @@ -37,6 +37,12 @@
     1.4  
     1.5  * Helper Functions
     1.6  
     1.7 +=(absolute-angle)= calculates the angle between two vectors, relative to a
     1.8 +third axis vector. This angle is the number of radians you have to
     1.9 +move counterclockwise around the axis vector to get from the first to
    1.10 +the second vector. It is not commutative like a normal dot-product
    1.11 +angle is.
    1.12 +
    1.13  #+name: helpers
    1.14  #+begin_src clojure
    1.15  (in-ns 'cortex.proprioception)
    1.16 @@ -49,17 +55,37 @@
    1.17    (< 0 (.dot (.cross vec1 vec2) vec3)))
    1.18  
    1.19  (defn absolute-angle
    1.20 -  "The angle between 'vec1 and 'vec2. Positive if the angle to get
    1.21 -  from 'vec1 to 'vec2 is counterclockwise around 'axis, and negative
    1.22 -  otherwise." 
    1.23 +  "The angle between 'vec1 and 'vec2 around 'axis. In the range 
    1.24 +   [0 (* 2 Math/PI)]."
    1.25    [vec1 vec2 axis]
    1.26    (let [angle (.angleBetween vec1 vec2)]
    1.27      (if (right-handed? vec1 vec2 axis)
    1.28        angle (- (* 2 Math/PI) angle))))
    1.29  #+end_src
    1.30  
    1.31 +#+begin_src clojure :exports both
    1.32 +(in-ns 'cortex.proprioception)
    1.33 +(absolute-angle  Vector3f/UNIT_X Vector3f/UNIT_Y Vector3f/UNIT_Z)
    1.34 +#+end_src
    1.35 +
    1.36 +#+results:
    1.37 +: 1.5707964
    1.38 +
    1.39 +#+begin_src clojure :exports both
    1.40 +(in-ns 'cortex.proprioception)
    1.41 +(absolute-angle 
    1.42 + Vector3f/UNIT_X (.mult Vector3f/UNIT_Y (float -1)) Vector3f/UNIT_Z)
    1.43 +#+end_src
    1.44 +
    1.45 +#+results:
    1.46 +: 4.7123889366733
    1.47 +
    1.48  * Proprioception Kernel
    1.49  
    1.50 +Given a joint, =(proprioception-kernel)= produces a function that
    1.51 +calculates the euler angles between the the objects the joint
    1.52 +connects. 
    1.53 +
    1.54  #+name: proprioception
    1.55  #+begin_src clojure
    1.56  (defn proprioception-kernel
    1.57 @@ -71,12 +97,6 @@
    1.58          x0 (.mult joint-rot Vector3f/UNIT_X)
    1.59          y0 (.mult joint-rot Vector3f/UNIT_Y)
    1.60          z0 (.mult joint-rot Vector3f/UNIT_Z)]
    1.61 -    (println-repl "x:" x0)
    1.62 -    (println-repl "y:" y0)
    1.63 -    (println-repl "z:" z0)
    1.64 -    (println-repl "init-a:" (.getWorldRotation obj-a))
    1.65 -    (println-repl "init-b:" (.getWorldRotation obj-b))
    1.66 -
    1.67      (fn []
    1.68        (let [rot-a (.clone (.getWorldRotation obj-a))
    1.69              rot-b (.clone (.getWorldRotation obj-b))
    1.70 @@ -113,8 +133,18 @@
    1.71        (map #(%) senses))))
    1.72  #+end_src
    1.73  
    1.74 +
    1.75 +=(proprioception!)= maps =(proprioception-kernel)= across all the
    1.76 +joints of the creature. It uses the same list of joints that
    1.77 +=(cortex.body/joints)= uses.
    1.78 +
    1.79  * Visualizing Proprioception
    1.80  
    1.81 +Proprioception has the lowest bandwidth of all the senses so far, and
    1.82 +it doesn't lend itself as readily to visual representation like
    1.83 +vision, hearing, or touch. This visualization code creates a "guage"
    1.84 +to view each of the three relative angles along a circle.
    1.85 +
    1.86  #+name: visualize
    1.87  #+begin_src clojure 
    1.88  (in-ns 'cortex.proprioception)
    1.89 @@ -141,7 +171,6 @@
    1.90            (reset! previous position))
    1.91          image))))
    1.92  
    1.93 -
    1.94  (defn proprioception-display-kernel
    1.95    "Display proprioception angles in a BufferedImage"
    1.96    [[h p r]]
    1.97 @@ -177,10 +206,15 @@
    1.98    (view-sense proprioception-display-kernel))
    1.99  #+end_src
   1.100  
   1.101 -* Demonstration of Proprioception
   1.102 +* Proprioception Test
   1.103 +This test does not use the worm, but instead uses two bars, bound
   1.104 +together by a point2point joint. One bar is fixed, and I control the
   1.105 +other bar from the keyboard. 
   1.106  
   1.107 -#+name: test-body
   1.108 +#+name: test-proprioception
   1.109  #+begin_src clojure
   1.110 +(in-ns 'cortex.test.proprioception)
   1.111 +
   1.112  (defn test-proprioception
   1.113    "Testing proprioception:
   1.114     You should see two foating bars, and a printout of pitch, yaw, and
   1.115 @@ -188,87 +222,115 @@
   1.116     change only the value of pitch. key-f/key-g moves it side to side
   1.117     and changes yaw. key-v/key-b will spin the blue segment clockwise
   1.118     and counterclockwise, and only affect roll."
   1.119 -  []
   1.120 -  (let [hand    (box 0.2 1 0.2 :position (Vector3f. 0 0 0)
   1.121 -                     :mass 0 :color ColorRGBA/Green :name "hand")
   1.122 -        finger (box 0.2 1 0.2 :position (Vector3f. 0 2.4 0)
   1.123 -                    :mass 1 :color ColorRGBA/Red :name "finger")
   1.124 -        joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow
   1.125 -                        :position (Vector3f. 0 1.2 0)
   1.126 -                        :rotation (doto (Quaternion.)
   1.127 -                                    (.fromAngleAxis
   1.128 -                                     (/ Math/PI 2)
   1.129 -                                     (Vector3f. 0 0 1)))
   1.130 -                        :physical? false)
   1.131 -        joint (join-at-point hand finger (Vector3f. 0 1.2 0 ))
   1.132 -        creature (nodify [hand finger joint-node])
   1.133 -        finger-control (.getControl finger RigidBodyControl)
   1.134 -        hand-control (.getControl hand RigidBodyControl)]
   1.135 -    
   1.136 +  ([] (test-proprioception false))
   1.137 +  ([record?]
   1.138 +     (let [hand    (box 0.2 1 0.2 :position (Vector3f. 0 0 0)
   1.139 +                        :mass 0 :color ColorRGBA/Gray :name "hand")
   1.140 +           finger (box 0.2 1 0.2 :position (Vector3f. 0 2.4 0)
   1.141 +                       :mass 1
   1.142 +                       :color
   1.143 +                       (ColorRGBA. (/ 184 255) (/ 127 255) (/ 201 255) 1) 
   1.144 +                       :name "finger")
   1.145 +           joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow
   1.146 +                           :position (Vector3f. 0 1.2 0)
   1.147 +                           :rotation (doto (Quaternion.)
   1.148 +                                       (.fromAngleAxis
   1.149 +                                        (/ Math/PI 2)
   1.150 +                                        (Vector3f. 0 0 1)))
   1.151 +                           :physical? false)
   1.152 +           creature (nodify [hand finger joint-node])
   1.153 +           finger-control (.getControl finger RigidBodyControl)
   1.154 +           hand-control (.getControl hand RigidBodyControl)
   1.155 +           joint (joint-dispatch {:type :point} hand-control finger-control
   1.156 +                                 (Vector3f. 0 1.2  0)
   1.157 +                                 (Vector3f. 0 -1.2 0) nil)
   1.158  
   1.159 -    (let
   1.160 -        ;; *******************************************
   1.161 -                
   1.162 -        [floor   (box 10 10 10 :position (Vector3f. 0 -15 0)
   1.163 -                     :mass 0 :color ColorRGBA/Gray)
   1.164 -        
   1.165 -        root (nodify [creature floor])
   1.166 -        prop (joint-proprioception creature joint-node)
   1.167 -        prop-view (proprioception-debug-window)
   1.168 -        
   1.169 -        controls
   1.170 -        (merge standard-debug-controls
   1.171 -               {"key-o"
   1.172 -                (fn [_ _] (.setEnabled finger-control true))
   1.173 -                "key-p"
   1.174 -                (fn [_ _] (.setEnabled finger-control false))
   1.175 -                "key-k"
   1.176 -                (fn [_ _] (.setEnabled hand-control true))
   1.177 -                "key-l"
   1.178 -                (fn [_ _] (.setEnabled hand-control false))
   1.179 -                "key-i"
   1.180 -                (fn [world _] (set-gravity world (Vector3f. 0 0 0)))
   1.181 -                "key-period"
   1.182 -                (fn [world _]
   1.183 -                  (.setEnabled finger-control false)
   1.184 -                  (.setEnabled hand-control false)
   1.185 -                  (.rotate creature (doto (Quaternion.)
   1.186 -                                      (.fromAngleAxis
   1.187 -                                       (float (/ Math/PI 15))
   1.188 -                                       (Vector3f. 0 0 -1))))
   1.189 -                                              
   1.190 -                  (.setEnabled finger-control true)
   1.191 -                  (.setEnabled hand-control true)
   1.192 -                  (set-gravity world (Vector3f. 0 0 0))
   1.193 -                  )
   1.194 -                
   1.195 -                  
   1.196 -                }
   1.197 -               )
   1.198 +           root (nodify [creature])
   1.199 +           prop (proprioception-kernel creature joint-node)
   1.200 +           prop-view (view-proprioception)]
   1.201 +       (.setCollisionGroup
   1.202 +        (.getControl hand RigidBodyControl)
   1.203 +        PhysicsCollisionObject/COLLISION_GROUP_NONE)
   1.204 +       (apply
   1.205 +        world
   1.206 +        (with-movement
   1.207 +          finger
   1.208 +          ["key-r" "key-t" "key-f" "key-g" "key-v" "key-b"]
   1.209 +          [1 1 10 10 10 10]
   1.210 +          [root
   1.211 +           standard-debug-controls
   1.212 +           (fn [world]
   1.213 +             (if record?
   1.214 +               (Capture/captureVideo
   1.215 +                world
   1.216 +                (File. "/home/r/proj/cortex/render/proprio/main-view")))
   1.217 +             (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
   1.218 +             (set-gravity world (Vector3f. 0 0 0))
   1.219 +             (enable-debug world)
   1.220 +             (light-up-everything world))
   1.221 +           (fn [_ _]
   1.222 +             (prop-view
   1.223 +              (list (prop))
   1.224 +              (if record?
   1.225 +                (File. "/home/r/proj/cortex/render/proprio/proprio"))))])))))
   1.226 +#+end_src
   1.227  
   1.228 -        ]
   1.229 -    (comment
   1.230 -      (.setCollisionGroup
   1.231 -       (.getControl hand RigidBodyControl)
   1.232 -       PhysicsCollisionObject/COLLISION_GROUP_NONE)
   1.233 -      )
   1.234 -    (apply
   1.235 -     world
   1.236 -     (with-movement
   1.237 -       hand
   1.238 -       ["key-y" "key-u" "key-h" "key-j" "key-n" "key-m"]
   1.239 -       [10 10 10 10 1 1]
   1.240 -       (with-movement
   1.241 -         finger
   1.242 -         ["key-r" "key-t" "key-f" "key-g" "key-v" "key-b"]
   1.243 -         [1 1 10 10 10 10]
   1.244 -         [root
   1.245 -          controls
   1.246 -          (fn [world]
   1.247 -            (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
   1.248 -            (set-gravity world (Vector3f. 0 0 0))
   1.249 -            (light-up-everything world))
   1.250 -          (fn [_ _] (prop-view (list (prop))))]))))))
   1.251 +#+results: test-proprioception
   1.252 +: #'cortex.test.proprioception/test-proprioception
   1.253 +
   1.254 +* Video of Proprioception
   1.255 +
   1.256 +#+begin_html
   1.257 +<div class="figure">
   1.258 +<center>
   1.259 +<video controls="controls" width="550">
   1.260 +  <source src="../video/test-proprioception.ogg" type="video/ogg"
   1.261 +	  preload="none" poster="../images/aurellem-1280x480.png" />
   1.262 +</video>
   1.263 +</center>
   1.264 +<p>Proprioception in a simple creature. The proprioceptive readout is
   1.265 +  in the upper left corner of the screen.</p>
   1.266 +</div>
   1.267 +#+end_html
   1.268 +
   1.269 +** Generating the Proprioception Video
   1.270 +#+name: magick6
   1.271 +#+begin_src clojure
   1.272 +(ns cortex.video.magick6
   1.273 +  (:import java.io.File)
   1.274 +  (:use clojure.contrib.shell-out))
   1.275 +
   1.276 +(defn images [path]
   1.277 +  (sort (rest (file-seq (File. path)))))
   1.278 +
   1.279 +(def base "/home/r/proj/cortex/render/proprio/")
   1.280 +
   1.281 +(defn pics [file]
   1.282 +  (images (str base file)))
   1.283 +
   1.284 +(defn combine-images []
   1.285 +  (let [main-view (pics "main-view")
   1.286 +        proprioception (pics "proprio/0")
   1.287 +        targets (map
   1.288 +                 #(File. (str base "out/" (format "%07d.png" %)))
   1.289 +                 (range 0 (count main-view)))]
   1.290 +    (dorun
   1.291 +     (pmap
   1.292 +      (comp
   1.293 +       (fn [[ main-view proprioception target]]
   1.294 +         (println target)
   1.295 +         (sh "convert"
   1.296 +             main-view 
   1.297 +             proprioception "-geometry" "+20+20" "-composite"
   1.298 +             target))
   1.299 +       (fn [& args] (map #(.getCanonicalPath %) args)))
   1.300 +       main-view proprioception targets))))
   1.301 +#+end_src
   1.302 +
   1.303 +#+begin_src sh :results silent
   1.304 +cd ~/proj/cortex/render/proprio
   1.305 +ffmpeg -r 60 -i out/%07d.png -b:v 9000k -c:v libtheora \
   1.306 +       test-proprioception.ogg
   1.307  #+end_src
   1.308  
   1.309  * Headers
   1.310 @@ -286,6 +348,26 @@
   1.311    (:import (com.jme3.math Vector3f Quaternion)))
   1.312  #+end_src
   1.313  
   1.314 +#+name: test-proprioception-header
   1.315 +#+begin_src clojure
   1.316 +(ns cortex.test.proprioception
   1.317 +(:import (com.aurellem.capture Capture RatchetTimer))
   1.318 +(:use (cortex util world proprioception body))
   1.319 +(:import java.io.File))
   1.320 +(cortex.import/mega-import-jme3)
   1.321 +#+end_src
   1.322 +
   1.323 +* Source Listing
   1.324 +  - [[../src/cortex/proprioception.clj][cortex.proprioception]]
   1.325 +  - [[../src/cortex/test/touch.clj][cortex.test.proprioception]]
   1.326 +  - [[../src/cortex/video/magick6.clj][cortex.video.magick6]]
   1.327 +#+html: <ul> <li> <a href="../org/proprioception.org">This org file</a> </li> </ul>
   1.328 +  - [[http://hg.bortreb.com ][source-repository]]
   1.329 +
   1.330 +* Next 
   1.331 +
   1.332 +Next time, I'll give the Worm the power to [[./movement.org][move on it's own]].
   1.333 +
   1.334  
   1.335  * COMMENT generate source
   1.336  #+begin_src clojure :tangle ../src/cortex/proprioception.clj
   1.337 @@ -294,3 +376,12 @@
   1.338  <<proprioception>>
   1.339  <<visualize>>
   1.340  #+end_src
   1.341 +
   1.342 +#+begin_src clojure :tangle ../src/cortex/test/proprioception.clj
   1.343 +<<test-proprioception-header>>
   1.344 +<<test-proprioception>>
   1.345 +#+end_src
   1.346 +
   1.347 +#+begin_src clojure :tangle ../src/cortex/video/magick6.clj
   1.348 +<<magick6>>
   1.349 +#+end_src