Mercurial > cortex
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