Mercurial > cortex
view org/proprioception.org @ 257:5d7961d7fded
wrote intro text for proprioception
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 14 Feb 2012 00:37:42 -0700 |
parents | df46a609fed9 |
children | f4b67005b702 |
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 Functions41 #+name: helpers42 #+begin_src clojure43 (in-ns 'cortex.proprioception)45 (defn right-handed?46 "true iff the three vectors form a right handed coordinate47 system. The three vectors do not have to be normalized or48 orthogonal."49 [vec1 vec2 vec3]50 (< 0 (.dot (.cross vec1 vec2) vec3)))52 (defn absolute-angle53 "The angle between 'vec1 and 'vec2. Positive if the angle to get54 from 'vec1 to 'vec2 is counterclockwise around 'axis, and negative55 otherwise."56 [vec1 vec2 axis]57 (let [angle (.angleBetween vec1 vec2)]58 (if (right-handed? vec1 vec2 axis)59 angle (- (* 2 Math/PI) angle))))60 #+end_src62 #+name: proprioception63 #+begin_src clojure64 (defn proprioception-kernel65 "Returns a function which returns proprioceptive sensory data when66 called inside a running simulation."67 [#^Node parts #^Node joint]68 (let [[obj-a obj-b] (joint-targets parts joint)69 joint-rot (.getWorldRotation joint)70 x0 (.mult joint-rot Vector3f/UNIT_X)71 y0 (.mult joint-rot Vector3f/UNIT_Y)72 z0 (.mult joint-rot Vector3f/UNIT_Z)]73 (println-repl "x:" x0)74 (println-repl "y:" y0)75 (println-repl "z:" z0)76 (println-repl "init-a:" (.getWorldRotation obj-a))77 (println-repl "init-b:" (.getWorldRotation obj-b))79 (fn []80 (let [rot-a (.clone (.getWorldRotation obj-a))81 rot-b (.clone (.getWorldRotation obj-b))82 x (.mult rot-a x0)83 y (.mult rot-a y0)84 z (.mult rot-a z0)86 X (.mult rot-b x0)87 Y (.mult rot-b y0)88 Z (.mult rot-b z0)89 heading (Math/atan2 (.dot X z) (.dot X x))90 pitch (Math/atan2 (.dot X y) (.dot X x))92 ;; rotate x-vector back to origin93 reverse94 (doto (Quaternion.)95 (.fromAngleAxis96 (.angleBetween X x)97 (let [cross (.normalize (.cross X x))]98 (if (= 0 (.length cross)) y cross))))99 roll (absolute-angle (.mult reverse Y) y x)]100 [heading pitch roll]))))102 (defn proprioception!103 "Endow the creature with the sense of proprioception. Returns a104 sequence of functions, one for each child of the \"joints\" node in105 the creature, which each report proprioceptive information about106 that joint."107 [#^Node creature]108 ;; extract the body's joints109 (let [senses (map (partial proprioception-kernel creature)110 (joints creature))]111 (fn []112 (map #(%) senses))))113 #+end_src115 #+name: visualize116 #+begin_src clojure117 (in-ns 'cortex.proprioception)119 (defn draw-sprite [image sprite x y color ]120 (dorun121 (for [[u v] sprite]122 (.setRGB image (+ u x) (+ v y) color))))124 (defn view-angle125 "create a debug view of an angle"126 [color]127 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)128 previous (atom [25 25])129 sprite [[0 0] [0 1]130 [0 -1] [-1 0] [1 0]]]131 (fn [angle]132 (let [angle (float angle)]133 (let [position134 [(+ 25 (int (* 20 (Math/cos angle))))135 (+ 25 (int (* -20 (Math/sin angle))))]]136 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)137 (draw-sprite image sprite (position 0) (position 1) color)138 (reset! previous position))139 image))))142 (defn proprioception-display-kernel143 "Display proprioception angles in a BufferedImage"144 [[h p r]]145 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)146 previous-heading (atom [25 25])147 previous-pitch (atom [25 25])148 previous-roll (atom [25 25])150 heading-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]151 pitch-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]152 roll-sprite [[0 0] [0 1] [0 -1] [-1 0] [1 0]]153 draw-angle154 (fn [angle sprite previous color]155 (let [angle (float angle)]156 (let [position157 [(+ 25 (int (* 20 (Math/cos angle))))158 (+ 25 (int (* -20 (Math/sin angle))))]]159 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)160 (draw-sprite image sprite (position 0) (position 1) color)161 (reset! previous position))162 image))]163 (dorun (map draw-angle164 [h p r]165 [heading-sprite pitch-sprite roll-sprite]166 [previous-heading previous-pitch previous-roll]167 [0xFF0000 0x00FF00 0xFFFFFF]))168 image))170 (defn view-proprioception171 "Creates a function which accepts a list of proprioceptive data and172 display each element of the list to the screen as an image."173 []174 (view-sense proprioception-display-kernel))175 #+end_src177 #+name: proprioception-header178 #+begin_src clojure179 (ns cortex.proprioception180 "Simulate the sense of proprioception (ability to detect the181 relative positions of body parts with repsect to other body parts)182 in jMonkeyEngine3. Reads specially prepared blender files to183 automatically generate proprioceptive senses."184 (:use (cortex world util sense body))185 (:use clojure.contrib.def)186 (:import com.jme3.scene.Node)187 (:import java.awt.image.BufferedImage)188 (:import (com.jme3.math Vector3f Quaternion)))189 #+end_src191 #+name: test-body192 #+begin_src clojure193 (defn test-proprioception194 "Testing proprioception:195 You should see two foating bars, and a printout of pitch, yaw, and196 roll. Pressing key-r/key-t should move the blue bar up and down and197 change only the value of pitch. key-f/key-g moves it side to side198 and changes yaw. key-v/key-b will spin the blue segment clockwise199 and counterclockwise, and only affect roll."200 []201 (let [hand (box 0.2 1 0.2 :position (Vector3f. 0 0 0)202 :mass 0 :color ColorRGBA/Green :name "hand")203 finger (box 0.2 1 0.2 :position (Vector3f. 0 2.4 0)204 :mass 1 :color ColorRGBA/Red :name "finger")205 joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow206 :position (Vector3f. 0 1.2 0)207 :rotation (doto (Quaternion.)208 (.fromAngleAxis209 (/ Math/PI 2)210 (Vector3f. 0 0 1)))211 :physical? false)212 joint (join-at-point hand finger (Vector3f. 0 1.2 0 ))213 creature (nodify [hand finger joint-node])214 finger-control (.getControl finger RigidBodyControl)215 hand-control (.getControl hand RigidBodyControl)]218 (let219 ;; *******************************************221 [floor (box 10 10 10 :position (Vector3f. 0 -15 0)222 :mass 0 :color ColorRGBA/Gray)224 root (nodify [creature floor])225 prop (joint-proprioception creature joint-node)226 prop-view (proprioception-debug-window)228 controls229 (merge standard-debug-controls230 {"key-o"231 (fn [_ _] (.setEnabled finger-control true))232 "key-p"233 (fn [_ _] (.setEnabled finger-control false))234 "key-k"235 (fn [_ _] (.setEnabled hand-control true))236 "key-l"237 (fn [_ _] (.setEnabled hand-control false))238 "key-i"239 (fn [world _] (set-gravity world (Vector3f. 0 0 0)))240 "key-period"241 (fn [world _]242 (.setEnabled finger-control false)243 (.setEnabled hand-control false)244 (.rotate creature (doto (Quaternion.)245 (.fromAngleAxis246 (float (/ Math/PI 15))247 (Vector3f. 0 0 -1))))249 (.setEnabled finger-control true)250 (.setEnabled hand-control true)251 (set-gravity world (Vector3f. 0 0 0))252 )255 }256 )258 ]259 (comment260 (.setCollisionGroup261 (.getControl hand RigidBodyControl)262 PhysicsCollisionObject/COLLISION_GROUP_NONE)263 )264 (apply265 world266 (with-movement267 hand268 ["key-y" "key-u" "key-h" "key-j" "key-n" "key-m"]269 [10 10 10 10 1 1]270 (with-movement271 finger272 ["key-r" "key-t" "key-f" "key-g" "key-v" "key-b"]273 [1 1 10 10 10 10]274 [root275 controls276 (fn [world]277 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))278 (set-gravity world (Vector3f. 0 0 0))279 (light-up-everything world))280 (fn [_ _] (prop-view (list (prop))))]))))))282 #+end_src285 * COMMENT generate source286 #+begin_src clojure :tangle ../src/cortex/proprioception.clj287 <<proprioception-header>>288 <<helpers>>289 <<proprioception>>290 <<visualize>>291 #+end_src