diff org/body.org @ 133:2ed7e60d3821

FINALLY got proprioception working
author Robert McIntyre <rlm@mit.edu>
date Wed, 01 Feb 2012 02:27:18 -0700
parents 3206d5e20bee
children ac350a0ac6b0
line wrap: on
line diff
     1.1 --- a/org/body.org	Tue Jan 31 01:40:47 2012 -0700
     1.2 +++ b/org/body.org	Wed Feb 01 02:27:18 2012 -0700
     1.3 @@ -17,67 +17,8 @@
     1.4     com.jme3.math.Matrix3f
     1.5     com.jme3.bullet.control.RigidBodyControl))
     1.6  
     1.7 -
     1.8 -
     1.9 -(defn quaternion-decompose [#^Quaternion q]
    1.10 -  (map
    1.11 -   #(arc-between % (.rotate q %))
    1.12 -   [Vector3f/UNIT_X
    1.13 -    Vector3f/UNIT_Y
    1.14 -    Vector3f/UNIT_Z]))
    1.15 -
    1.16 -(defn any-orthogonal
    1.17 -  "Generate an arbitray (but stable) orthogonal vector to a given
    1.18 -   vector."
    1.19 -  [vector]
    1.20 -  (let [x (.getX vector)
    1.21 -        y (.getY vector)
    1.22 -        z (.getZ vector)]
    1.23 -    (cond
    1.24 -     (not= x (float 0)) (Vector3f. (- z) 0 x)
    1.25 -     (not= y (float 0)) (Vector3f. 0 (- z) y)
    1.26 -     (not= z (float 0)) (Vector3f. 0 (- z) y)
    1.27 -     true Vector3f/ZERO)))
    1.28 -
    1.29 -(defn project-quaternion
    1.30 -  "From http://stackoverflow.com/questions/3684269/
    1.31 -   component-of-a-quaternion-rotation-around-an-axis.
    1.32 -
    1.33 -   Determine the amount of rotation a quaternion will
    1.34 -   cause about a given axis."
    1.35 -  [#^Quaternion q #^Vector3f axis]
    1.36 -  (let [basis-1 (any-orthogonal axis)
    1.37 -        basis-2 (.cross axis basis-1)
    1.38 -        rotated (.mult q basis-1)
    1.39 -        alpha (.dot basis-1 (.project rotated basis-1))
    1.40 -        beta  (.dot basis-2 (.project rotated basis-2))]
    1.41 -    (Math/atan2 beta alpha)))
    1.42 -
    1.43 -(defn right-handed? [vec1 vec2 vec3]
    1.44 -  (< 0 (.dot (.cross vec1 vec2) vec3)))
    1.45 -
    1.46 -(defn project-quaternion
    1.47 -  "From http://stackoverflow.com/questions/3684269/
    1.48 -   component-of-a-quaternion-rotation-around-an-axis.
    1.49 -
    1.50 -   Determine the amount of rotation a quaternion will
    1.51 -   cause about a given axis."
    1.52 -  [#^Quaternion q #^Vector3f axis]
    1.53 -  (let [axis (.normalize axis)
    1.54 -        basis-1 (any-orthogonal axis)
    1.55 -        basis-2 (.cross axis basis-1)
    1.56 -        rotated (.mult q basis-1)
    1.57 -        rotated-in-plane (.add (.project rotated basis-1)
    1.58 -                               (.project rotated basis-2))]
    1.59 -
    1.60 -    ;; be sure to get sign from cross product
    1.61 -    (if (right-handed? basis-1 rotated-in-plane axis)
    1.62 -      (.angleBetween rotated-in-plane basis-1)
    1.63 -      (- (* 2 Math/PI) (.angleBetween rotated-in-plane basis-1)))))
    1.64 -
    1.65 -
    1.66 -
    1.67 -(defn joint-proprioception
    1.68 +(comment
    1.69 +  (defn joint-proprioception
    1.70    "Relative position information for a two-part system connected by a
    1.71     joint. Gives the pitch, yaw, and roll of the 'B' object relative to
    1.72     the 'A' object, as determined by the joint."
    1.73 @@ -120,63 +61,148 @@
    1.74           arm-b)]
    1.75      ;;(println-repl (.getName object-a) (.getName object-b))
    1.76      [pitch yaw roll]))
    1.77 +)
    1.78  
    1.79 +(defn any-orthogonal
    1.80 +  "Generate an arbitray (but stable) orthogonal vector to a given
    1.81 +   vector."
    1.82 +  [vector]
    1.83 +  (let [x (.getX vector)
    1.84 +        y (.getY vector)
    1.85 +        z (.getZ vector)]
    1.86 +    (cond
    1.87 +     (not= x (float 0)) (Vector3f. (- z) 0 x)
    1.88 +     (not= y (float 0)) (Vector3f. 0 (- z) y)
    1.89 +     (not= z (float 0)) (Vector3f. 0 (- z) y)
    1.90 +     true Vector3f/ZERO)))
    1.91  
    1.92 +(comment
    1.93 +(defn project-quaternion
    1.94 +  "From http://stackoverflow.com/questions/3684269/
    1.95 +   component-of-a-quaternion-rotation-around-an-axis.
    1.96  
    1.97 +   Determine the amount of rotation a quaternion will
    1.98 +   cause about a given axis."
    1.99 +  [#^Quaternion q #^Vector3f axis]
   1.100 +  (let [basis-1 (any-orthogonal axis)
   1.101 +        basis-2 (.cross axis basis-1)
   1.102 +        rotated (.mult q basis-1)
   1.103 +        alpha (.dot basis-1 (.project rotated basis-1))
   1.104 +        beta  (.dot basis-2 (.project rotated basis-2))]
   1.105 +    (Math/atan2 beta alpha)))
   1.106 +)
   1.107  
   1.108 -(defn absolute-angle-between
   1.109 -  [vec-1 vec-2]
   1.110 +(defn right-handed? [vec1 vec2 vec3]
   1.111 +  (< 0 (.dot (.cross vec1 vec2) vec3)))
   1.112 +
   1.113 +(defn absolute-angle [vec1 vec2 axis]
   1.114 +  (let [angle (.angleBetween vec1 vec2)]
   1.115 +    (if (right-handed? vec1 vec2 axis)
   1.116 +      angle (- (* 2 Math/PI) angle))))
   1.117 +
   1.118 +(defn angle-min [& angles]
   1.119 +  (first
   1.120 +   (sort-by 
   1.121 +    (fn [angle]
   1.122 +      (let [in-circle (Math/abs (rem angle (* 2 Math/PI)))]
   1.123 +        (min in-circle
   1.124 +             (- (* Math/PI 2) in-circle))))
   1.125 +    angles)))
   1.126 +
   1.127 +(defn project-quaternion
   1.128 +  "From http://stackoverflow.com/questions/3684269/
   1.129 +   component-of-a-quaternion-rotation-around-an-axis.
   1.130 +
   1.131 +   Determine the amount of rotation a quaternion will
   1.132 +   cause about a given axis."
   1.133 +  [#^Quaternion q #^Vector3f axis]
   1.134 +  (let [axis (.normalize axis)
   1.135 +        basis-1 (.normalize (any-orthogonal axis))
   1.136 +        basis-2 (.cross axis basis-1)
   1.137 +        rotated-1 (.mult q basis-1)
   1.138 +        basis-1* (.normalize
   1.139 +                          (.add (.project rotated-1 basis-1)
   1.140 +                                (.project rotated-1 basis-2)))
   1.141 +        rotated-2 (.mult q basis-2)
   1.142 +        basis-2* (.normalize
   1.143 +                          (.add (.project rotated-2 basis-1)
   1.144 +                                (.project rotated-2 basis-2)))
   1.145 +        angle-1
   1.146 +        (absolute-angle basis-1 basis-1* axis)
   1.147 +        angle-2
   1.148 +        (absolute-angle basis-2 basis-2* axis)
   1.149 +
   1.150 +
   1.151 +        angle (angle-min angle-1 angle-2)
   1.152 +        ]
   1.153    
   1.154  
   1.155 +    ;; be sure to get sign from cross product
   1.156 +    (if false
   1.157 +      (do
   1.158 +        (println-repl "axis" axis)
   1.159 +        (println-repl "basis-1" basis-1)
   1.160 +        (println-repl "basis-2" basis-2)
   1.161 +        (println-repl "rotated-1" rotated-1)
   1.162 +        (println-repl "rotated-2" rotated-2)
   1.163 +        (println-repl "basis-1*" basis-1*)
   1.164 +        (println-repl "basis-2*" basis-2*)
   1.165 +        (println-repl "angle-1" angle-1)
   1.166 +        (println-repl "angle-2" angle-2)
   1.167 +        
   1.168 +        (println-repl "angle" angle)
   1.169 +        (println-repl "")))
   1.170 +    angle))
   1.171 +    
   1.172  
   1.173 +(import com.jme3.scene.Node)
   1.174 +
   1.175 +(defn joint-proprioception [#^Node parts #^Node joint]
   1.176 +  (let [[obj-a obj-b] (cortex.silly/joint-targets parts joint)
   1.177 +        joint-rot (.getWorldRotation joint)
   1.178 +        x (.mult joint-rot Vector3f/UNIT_X)
   1.179 +        y (.mult joint-rot Vector3f/UNIT_Y)
   1.180 +        z (.mult joint-rot Vector3f/UNIT_Z)]
   1.181 +    ;; this function will report proprioceptive information for the
   1.182 +    ;; joint 
   1.183 +    (fn []
   1.184 +      ;; x is the "twist" axis, y and z are the "bend" axes
   1.185 +      (let [rot-a (.getWorldRotation obj-a)
   1.186 +            rot-b (.getWorldRotation obj-b)
   1.187 +            relative (.mult (.inverse rot-a) rot-b)
   1.188 +            basis (doto (Matrix3f.)
   1.189 +                    (.setColumn 0 x)
   1.190 +                    (.setColumn 1 y)
   1.191 +                    (.setColumn 2 z))
   1.192 +            rotation-about-joint
   1.193 +            (doto (Quaternion.)
   1.194 +              (.fromRotationMatrix 
   1.195 +               (.mult (.invert basis)
   1.196 +                      (.toRotationMatrix relative))))
   1.197 +            [yaw roll pitch]
   1.198 +            (seq (.toAngles rotation-about-joint nil))]
   1.199 +        ;;return euler angles of the quaternion around the new basis            
   1.200 +        ;;[yaw pitch roll]
   1.201 +        [yaw roll pitch]
   1.202 +        ))))
   1.203 +
   1.204 +
   1.205 +(comment
   1.206  
   1.207  (defn joint-proprioception
   1.208    [joint]
   1.209    (let [object-a (.getUserObject (.getBodyA joint))
   1.210          object-b (.getUserObject (.getBodyB joint))
   1.211 -
   1.212 -        arm-a
   1.213 -        (.normalize
   1.214 -         (.subtract 
   1.215 -          (.localToWorld object-a (.getPivotA joint) nil)
   1.216 -          (.getWorldTranslation object-a)))
   1.217 -        arm-b
   1.218 -        (.normalize
   1.219 -         (.subtract 
   1.220 -          (.localToWorld object-b (.getPivotB joint) nil)
   1.221 -          (.getWorldTranslation object-b)))
   1.222 -
   1.223 -        rotate-a (.clone (.getWorldRotation object-a))
   1.224 -        unrotate-a (.inverse (.getWorldRotation object-a))
   1.225 -
   1.226 -        canonical-arm-a (.mult unrotate-a arm-a)
   1.227 -
   1.228 -        basis-1 (any-orthogonal canonical-arm-a)
   1.229 -        basis-2 (.normalize (.cross basis-1 canonical-arm-a))
   1.230 -
   1.231 -        pitch (.angleBetween arm-b basis-1)
   1.232 -        yaw (.angleBetween arm-b basis-2)
   1.233 -
   1.234 -        twist-a
   1.235 -        (project-quaternion
   1.236 -         (.getWorldRotation object-a) arm-a)
   1.237 -        
   1.238 -        twist-b
   1.239 -        (project-quaternion
   1.240 -         (.getWorldRotation object-b) arm-b)
   1.241 -
   1.242 -        roll (- twist-b 0)
   1.243 -        ;; "un-rotate" arm-a to it's canonical position, get two
   1.244 -        ;; orthogonal basis vectors. Rotate those two vectors back to
   1.245 -        ;; the correct position get the rotations between them.
   1.246 -
   1.247 -        ;; twist is the rotation about arm-a of obj-b minus the
   1.248 -        ;; rotation about arm-a of obj-a
   1.249 +        rot-a (.clone (.getWorldRotation object-a))
   1.250 +        rot-b (.clone (.getWorldRotation object-b))
   1.251          ]
   1.252 +    
   1.253 +    (.mult rot-b (.inverse rot-a))
   1.254 +    
   1.255      ;; object-a == hand
   1.256      ;; object-b == finger
   1.257 -    [pitch yaw roll]))
   1.258 -
   1.259 +    ))
   1.260 +)
   1.261  ;; (defn joint-proprioception*
   1.262  ;;   [joint]
   1.263  ;;   (let [object-a (.getUserObject (.getBodyA joint))
   1.264 @@ -211,6 +237,9 @@
   1.265    
   1.266  #+end_src
   1.267  
   1.268 +#+results: proprioception
   1.269 +: #'cortex.body/proprioception
   1.270 +
   1.271  * Motor Control
   1.272  #+name: motor-control
   1.273  #+begin_src clojure
   1.274 @@ -346,7 +375,7 @@
   1.275     nil
   1.276     ))
   1.277  
   1.278 -
   1.279 +(import com.jme3.bullet.collision.PhysicsCollisionObject)
   1.280  
   1.281  (defn blab-* []
   1.282    (let [hand   (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)
   1.283 @@ -397,21 +426,30 @@
   1.284  (defn proprioception-debug-window
   1.285    []
   1.286    (let [yaw (view-angle 0xFF0000)
   1.287 -        pitch (view-angle 0x00FF00)
   1.288 -        roll (view-angle 0xFFFFFF)
   1.289 +        roll (view-angle 0x00FF00)
   1.290 +        pitch (view-angle 0xFFFFFF)
   1.291          v-yaw (view-image)
   1.292 +        v-roll (view-image)
   1.293          v-pitch (view-image)
   1.294 -        v-roll (view-image)
   1.295          ]
   1.296      (fn [prop-data]
   1.297        (dorun
   1.298         (map
   1.299 -        (fn [[p y r]]
   1.300 +        (fn [[y r p]]
   1.301            (v-yaw (yaw y))
   1.302            (v-roll (roll r))
   1.303            (v-pitch (pitch p)))
   1.304          prop-data)))))
   1.305 -       
   1.306 +(comment  
   1.307 +     
   1.308 +(defn proprioception-debug-window
   1.309 +  []
   1.310 +  (let [time (atom 0)]
   1.311 +    (fn [prop-data]
   1.312 +      (if (= 0 (rem (swap! time inc) 40))
   1.313 +        (println-repl prop-data)))))
   1.314 +)
   1.315 +
   1.316  (comment
   1.317    (dorun
   1.318     (map
   1.319 @@ -439,8 +477,11 @@
   1.320                       :mass 0 :color ColorRGBA/Green :name "hand")
   1.321          finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
   1.322                      :mass 1 :color ColorRGBA/Red :name "finger")
   1.323 -        floor   (box 10 0.5 10 :position (Vector3f. 0 -5 0)
   1.324 +        floor   (box 10 10 10 :position (Vector3f. 0 -15 0)
   1.325                       :mass 0 :color ColorRGBA/Gray)
   1.326 +        joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow
   1.327 +                        :position (Vector3f. 1.2 2 0)
   1.328 +                        :physical? false)
   1.329  
   1.330          move-up? (atom false)
   1.331          move-down? (atom false)
   1.332 @@ -451,8 +492,8 @@
   1.333          control (.getControl finger RigidBodyControl)
   1.334          time (atom 0)
   1.335          joint (join-at-point hand finger (Vector3f. 1.2 2 0 ))
   1.336 -        creature (nodify [hand finger])
   1.337 -        prop (proprioception creature)
   1.338 +        creature (nodify [hand finger joint-node])
   1.339 +        prop (joint-proprioception creature joint-node)
   1.340  
   1.341          prop-view (proprioception-debug-window)
   1.342  
   1.343 @@ -461,13 +502,14 @@
   1.344      
   1.345  
   1.346      
   1.347 +
   1.348      (.setCollisionGroup
   1.349       (.getControl hand RigidBodyControl)
   1.350       PhysicsCollisionObject/COLLISION_GROUP_NONE)
   1.351  
   1.352      
   1.353      (world
   1.354 -     (nodify [hand finger floor])
   1.355 +     (nodify [hand finger floor joint-node])
   1.356       (merge standard-debug-controls
   1.357              {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
   1.358               "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
   1.359 @@ -506,7 +548,7 @@
   1.360                                (Vector3f. 1 0 0))))
   1.361  
   1.362         ;;(if (= 0 (rem (swap! time inc) 20))
   1.363 -         (prop-view (prop))))))
   1.364 +         (prop-view (list (prop)))))))
   1.365  
   1.366  #+end_src
   1.367