Mercurial > cortex
view org/proprioception.org @ 258:f4b67005b702
reorganized proprioception
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 14 Feb 2012 00:39:16 -0700 |
parents | 5d7961d7fded |
children | 7cac5ef852e3 |
line wrap: on
line source
1 #+title: The Sense of Proprioception2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: proprioception for simulated creatures5 #+keywords: simulation, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org9 * Proprioception11 Close your eyes, and touch your nose with your right index finger. How12 did you do it? You could not see your hand, and neither your hand nor13 your nose could use the sense of touch to guide the path of your hand.14 There are no sound cues, and Taste and Smell certainly don't provide15 any help. You know where your hand is without your other senses16 because of Proprioception.18 Humans can sometimes loose this sense through viral infections or19 damage to the spinal cord or brain, and when they do, they loose the20 ability to control their own bodies without looking directly at the21 parts they want to move. In [[http://en.wikipedia.org/wiki/The_Man_Who_Mistook_His_Wife_for_a_Hat][The Man Who Mistook His Wife for a Hat]],22 a woman named Christina looses this sense and has to learn how to move23 by carefully watching her arms and legs. She describes proprioception24 as the "eyes of the body, the way the body sees itself".26 Proprioception in humans is mediated by [[http://en.wikipedia.org/wiki/Articular_capsule][joint capsules]], [[http://en.wikipedia.org/wiki/Muscle_spindle][muscle27 spindles]], and the [[http://en.wikipedia.org/wiki/Golgi_tendon_organ][Golgi tendon organs]]. These measure the relative28 positions of each pody part by monitoring muscle strain and length.30 It's clear that this is a vital sense for fulid, graceful31 movement. It's also particurally easy to implement in jMonkeyEngine.33 My simulated proprioception calculates the relative angles of each34 joint from the rest position defined in the blender file. This35 simulates the muscle-spindles and joint capsules. I will deal with36 Golgi tendon organs, which calculate muscle strain, in the [[./movement.org][next post]].38 * Helper Functions40 #+name: helpers41 #+begin_src clojure42 (in-ns 'cortex.proprioception)44 (defn right-handed?45 "true iff the three vectors form a right handed coordinate46 system. The three vectors do not have to be normalized or47 orthogonal."48 [vec1 vec2 vec3]49 (< 0 (.dot (.cross vec1 vec2) vec3)))51 (defn absolute-angle52 "The angle between 'vec1 and 'vec2. Positive if the angle to get53 from 'vec1 to 'vec2 is counterclockwise around 'axis, and negative54 otherwise."55 [vec1 vec2 axis]56 (let [angle (.angleBetween vec1 vec2)]57 (if (right-handed? vec1 vec2 axis)58 angle (- (* 2 Math/PI) angle))))59 #+end_src61 * Proprioception Kernel63 #+name: proprioception64 #+begin_src clojure65 (defn proprioception-kernel66 "Returns a function which returns proprioceptive sensory data when67 called inside a running simulation."68 [#^Node parts #^Node joint]69 (let [[obj-a obj-b] (joint-targets parts joint)70 joint-rot (.getWorldRotation joint)71 x0 (.mult joint-rot Vector3f/UNIT_X)72 y0 (.mult joint-rot Vector3f/UNIT_Y)73 z0 (.mult joint-rot Vector3f/UNIT_Z)]74 (println-repl "x:" x0)75 (println-repl "y:" y0)76 (println-repl "z:" z0)77 (println-repl "init-a:" (.getWorldRotation obj-a))78 (println-repl "init-b:" (.getWorldRotation obj-b))80 (fn []81 (let [rot-a (.clone (.getWorldRotation obj-a))82 rot-b (.clone (.getWorldRotation obj-b))83 x (.mult rot-a x0)84 y (.mult rot-a y0)85 z (.mult rot-a z0)87 X (.mult rot-b x0)88 Y (.mult rot-b y0)89 Z (.mult rot-b z0)90 heading (Math/atan2 (.dot X z) (.dot X x))91 pitch (Math/atan2 (.dot X y) (.dot X x))93 ;; rotate x-vector back to origin94 reverse95 (doto (Quaternion.)96 (.fromAngleAxis97 (.angleBetween X x)98 (let [cross (.normalize (.cross X x))]99 (if (= 0 (.length cross)) y cross))))100 roll (absolute-angle (.mult reverse Y) y x)]101 [heading pitch roll]))))103 (defn proprioception!104 "Endow the creature with the sense of proprioception. Returns a105 sequence of functions, one for each child of the \"joints\" node in106 the creature, which each report proprioceptive information about107 that joint."108 [#^Node creature]109 ;; extract the body's joints110 (let [senses (map (partial proprioception-kernel creature)111 (joints creature))]112 (fn []113 (map #(%) senses))))114 #+end_src116 * Visualizing Proprioception118 #+name: visualize119 #+begin_src clojure120 (in-ns 'cortex.proprioception)122 (defn draw-sprite [image sprite x y color ]123 (dorun124 (for [[u v] sprite]125 (.setRGB image (+ u x) (+ v y) color))))127 (defn view-angle128 "create a debug view of an angle"129 [color]130 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)131 previous (atom [25 25])132 sprite [[0 0] [0 1]133 [0 -1] [-1 0] [1 0]]]134 (fn [angle]135 (let [angle (float angle)]136 (let [position137 [(+ 25 (int (* 20 (Math/cos angle))))138 (+ 25 (int (* -20 (Math/sin angle))))]]139 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)140 (draw-sprite image sprite (position 0) (position 1) color)141 (reset! previous position))142 image))))145 (defn proprioception-display-kernel146 "Display proprioception angles in a BufferedImage"147 [[h p r]]148 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)149 previous-heading (atom [25 25])150 previous-pitch (atom [25 25])151 previous-roll (atom [25 25])153 heading-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]154 pitch-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]155 roll-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]156 draw-angle157 (fn [angle sprite previous color]158 (let [angle (float angle)]159 (let [position160 [(+ 25 (int (* 20 (Math/cos angle))))161 (+ 25 (int (* -20 (Math/sin angle))))]]162 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)163 (draw-sprite image sprite (position 0) (position 1) color)164 (reset! previous position))165 image))]166 (dorun (map draw-angle167 [h p r]168 [heading-sprite pitch-sprite roll-sprite]169 [previous-heading previous-pitch previous-roll]170 [0xFF0000 0x00FF00 0xFFFFFF]))171 image))173 (defn view-proprioception174 "Creates a function which accepts a list of proprioceptive data and175 display each element of the list to the screen as an image."176 []177 (view-sense proprioception-display-kernel))178 #+end_src180 * Demonstration of Proprioception182 #+name: test-body183 #+begin_src clojure184 (defn test-proprioception185 "Testing proprioception:186 You should see two foating bars, and a printout of pitch, yaw, and187 roll. Pressing key-r/key-t should move the blue bar up and down and188 change only the value of pitch. key-f/key-g moves it side to side189 and changes yaw. key-v/key-b will spin the blue segment clockwise190 and counterclockwise, and only affect roll."191 []192 (let [hand (box 0.2 1 0.2 :position (Vector3f. 0 0 0)193 :mass 0 :color ColorRGBA/Green :name "hand")194 finger (box 0.2 1 0.2 :position (Vector3f. 0 2.4 0)195 :mass 1 :color ColorRGBA/Red :name "finger")196 joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow197 :position (Vector3f. 0 1.2 0)198 :rotation (doto (Quaternion.)199 (.fromAngleAxis200 (/ Math/PI 2)201 (Vector3f. 0 0 1)))202 :physical? false)203 joint (join-at-point hand finger (Vector3f. 0 1.2 0 ))204 creature (nodify [hand finger joint-node])205 finger-control (.getControl finger RigidBodyControl)206 hand-control (.getControl hand RigidBodyControl)]209 (let210 ;; *******************************************212 [floor (box 10 10 10 :position (Vector3f. 0 -15 0)213 :mass 0 :color ColorRGBA/Gray)215 root (nodify [creature floor])216 prop (joint-proprioception creature joint-node)217 prop-view (proprioception-debug-window)219 controls220 (merge standard-debug-controls221 {"key-o"222 (fn [_ _] (.setEnabled finger-control true))223 "key-p"224 (fn [_ _] (.setEnabled finger-control false))225 "key-k"226 (fn [_ _] (.setEnabled hand-control true))227 "key-l"228 (fn [_ _] (.setEnabled hand-control false))229 "key-i"230 (fn [world _] (set-gravity world (Vector3f. 0 0 0)))231 "key-period"232 (fn [world _]233 (.setEnabled finger-control false)234 (.setEnabled hand-control false)235 (.rotate creature (doto (Quaternion.)236 (.fromAngleAxis237 (float (/ Math/PI 15))238 (Vector3f. 0 0 -1))))240 (.setEnabled finger-control true)241 (.setEnabled hand-control true)242 (set-gravity world (Vector3f. 0 0 0))243 )246 }247 )249 ]250 (comment251 (.setCollisionGroup252 (.getControl hand RigidBodyControl)253 PhysicsCollisionObject/COLLISION_GROUP_NONE)254 )255 (apply256 world257 (with-movement258 hand259 ["key-y" "key-u" "key-h" "key-j" "key-n" "key-m"]260 [10 10 10 10 1 1]261 (with-movement262 finger263 ["key-r" "key-t" "key-f" "key-g" "key-v" "key-b"]264 [1 1 10 10 10 10]265 [root266 controls267 (fn [world]268 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))269 (set-gravity world (Vector3f. 0 0 0))270 (light-up-everything world))271 (fn [_ _] (prop-view (list (prop))))]))))))272 #+end_src274 * Headers275 #+name: proprioception-header276 #+begin_src clojure277 (ns cortex.proprioception278 "Simulate the sense of proprioception (ability to detect the279 relative positions of body parts with repsect to other body parts)280 in jMonkeyEngine3. Reads specially prepared blender files to281 automatically generate proprioceptive senses."282 (:use (cortex world util sense body))283 (:use clojure.contrib.def)284 (:import com.jme3.scene.Node)285 (:import java.awt.image.BufferedImage)286 (:import (com.jme3.math Vector3f Quaternion)))287 #+end_src290 * COMMENT generate source291 #+begin_src clojure :tangle ../src/cortex/proprioception.clj292 <<proprioception-header>>293 <<helpers>>294 <<proprioception>>295 <<visualize>>296 #+end_src