diff org/body.org @ 60:e5e627f50a3a

finally got euler angle stuff working
author Robert McIntyre <rlm@mit.edu>
date Mon, 28 Nov 2011 02:54:48 -0700
parents 25142dad240a
children 7b44348af538
line wrap: on
line diff
     1.1 --- a/org/body.org	Sat Nov 19 23:59:12 2011 -0700
     1.2 +++ b/org/body.org	Mon Nov 28 02:54:48 2011 -0700
     1.3 @@ -143,6 +143,20 @@
     1.4      node))
     1.5  
     1.6    
     1.7 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     1.8 +
     1.9 +;; this could be a good way to give objects special properties like
    1.10 +;; being eyes and the like
    1.11 +
    1.12 +(.getUserData 
    1.13 + (.getChild
    1.14 +  (load-blender-model "Models/property/test.blend") 0)
    1.15 + "properties")
    1.16 +
    1.17 +;; the properties are saved along with the blender file.
    1.18 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.19 +
    1.20 +
    1.21  
    1.22  (defn init-debug-skel-node
    1.23    [f debug-node skeleton]
    1.24 @@ -312,32 +326,27 @@
    1.25    
    1.26  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.27  
    1.28 +;;;;;;;;;;;;  eve-style bodies  ;;;;;;;;
    1.29  
    1.30  
    1.31 -
    1.32 -
    1.33 -
    1.34 -;;;;;;;;;;;;  eve-style bodies  ;;;;;;;;
    1.35 -(defn joint-control
    1.36 -  [joint]
    1.37 -  (let [physics-space (ref nil)]
    1.38 -    (reify PhysicsControl
    1.39 -      (setPhysicsSpace [this space]
    1.40 -        (dosync
    1.41 -         (ref-set physics-space space))
    1.42 -        (.addJoint space joint))
    1.43 -      (update [this tpf])
    1.44 -      (setSpatial [this spatial])
    1.45 -      (render [this rm vp])
    1.46 -      (getPhysicsSpace [this] (deref physics-space))
    1.47 -      (isEnabled [this] true)
    1.48 -      (setEnabled [this state]))))
    1.49 -
    1.50 +(defrecord JointControl [joint physics-space]
    1.51 +  PhysicsControl
    1.52 +  (setPhysicsSpace [this space]
    1.53 +    (dosync
    1.54 +     (ref-set (:physics-space this) space))
    1.55 +    (.addJoint space (:joint this)))
    1.56 +  (update [this tpf])
    1.57 +  (setSpatial [this spatial])
    1.58 +  (render [this rm vp])
    1.59 +  (getPhysicsSpace [this] (deref (:physics-space this)))
    1.60 +  (isEnabled [this] true)
    1.61 +  (setEnabled [this state]))
    1.62 +  
    1.63  (defn add-joint
    1.64    "Add a joint to a particular object. When the object is added to the
    1.65    PhysicsSpace of a simulation, the joint will also be added"
    1.66    [object joint]
    1.67 -  (let [control (joint-control joint)]
    1.68 +  (let [control (JointControl. joint (ref nil))]
    1.69      (.addControl object control))
    1.70    object)
    1.71  
    1.72 @@ -371,7 +380,7 @@
    1.73  
    1.74  (defn nodify
    1.75    "take a sequence of things that can be attached to a node and return
    1.76 -  a node with all of the attached"
    1.77 +  a node with all of them attached"
    1.78    ([name children]
    1.79       (let [node (Node. name)]
    1.80         (dorun (map #(.attachChild node %) children))
    1.81 @@ -427,19 +436,408 @@
    1.82  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.83  
    1.84  
    1.85 +;;;;;;;;;  Mortor Control  ;;;;;;;;;;;;;
    1.86  
    1.87  
    1.88 +;; surprisingly ehough, terristerial creatures only move by using
    1.89 +;; torque applied to their joints.  There's not a single straight line
    1.90 +;; of force in the human body at all!  (a straight line of force would
    1.91 +;; correspond to some sort of jet or rocket propulseion)
    1.92  
    1.93 +(defn node-seq
    1.94 +  "take a node and return a seq of all its children
    1.95 +   recursively. There will be no nodes left in the resulting
    1.96 +   structure"
    1.97 +  [#^Node node]
    1.98 +  (tree-seq #(isa? (class %) Node) #(.getChildren %) node))
    1.99 +  
   1.100 +  
   1.101 +(defn torque-controls [control]
   1.102 +  (let [torques
   1.103 +        (concat
   1.104 +         (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
   1.105 +              (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
   1.106 +         [Vector3f/UNIT_X])]
   1.107 +    (map (fn [torque-axis]
   1.108 +           (fn [torque]
   1.109 +             (.applyTorque
   1.110 +              control
   1.111 +              (.mult (.mult (.getPhysicsRotation control)
   1.112 +                            torque-axis)
   1.113 +                     (float
   1.114 +                      (* (.getMass control) torque))))))
   1.115 +         torques)))
   1.116  
   1.117 +(defn motor-map
   1.118 +  "Take a creature and generate a function that will enable fine
   1.119 +   grained control over all the creature's limbs."  
   1.120 +  [#^Node creature]
   1.121 +  (let [controls (keep #(.getControl % RigidBodyControl)
   1.122 +                       (node-seq creature))
   1.123 +        limb-controls (reduce concat (map torque-controls controls))
   1.124 +        body-control  (partial map #(%1 %2) limb-controls)]
   1.125 +    body-control))
   1.126  
   1.127  
   1.128  
   1.129 +(defn test-motor-map
   1.130 +  "see how torque works."
   1.131 +  []
   1.132 +  (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
   1.133 +                    :mass 1 :color ColorRGBA/Green)
   1.134 +        motor-map (motor-map finger)]
   1.135 +    (world
   1.136 +     (nodify [finger
   1.137 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   1.138 +                   :color ColorRGBA/Gray)])
   1.139 +     standard-debug-controls
   1.140 +     (fn [world]
   1.141 +       (set-gravity world Vector3f/ZERO)
   1.142 +       (light-up-everything world)
   1.143 +       (.setTimer world (NanoTimer.)))
   1.144 +     (fn [_ _]
   1.145 +       (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))
   1.146 +
   1.147 +
   1.148 +
   1.149 +(defn test-torque
   1.150 +  "see how torque works."
   1.151 +  []
   1.152 +  (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
   1.153 +                    :mass 1 :color ColorRGBA/Green)
   1.154 +        move-left? (atom false)
   1.155 +        move-right? (atom false)
   1.156 +        control (.getControl finger RigidBodyControl)]
   1.157 +    (world
   1.158 +     (nodify [finger
   1.159 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   1.160 +                   :color ColorRGBA/Gray)])
   1.161 +     (merge standard-debug-controls
   1.162 +            {"key-k" (fn [_ pressed?] (reset! move-left? pressed?))
   1.163 +             "key-l" (fn [_ pressed?] (reset! move-right? pressed?))})
   1.164 +     (fn [world]
   1.165 +       (set-gravity world Vector3f/ZERO)
   1.166 +       (light-up-everything world)
   1.167 +       (.setTimer world (NanoTimer.)))
   1.168 +     (fn [_ _]
   1.169 +       (if @move-left?
   1.170 +         (.applyTorque control
   1.171 +                       (.mult (.getPhysicsRotation control)
   1.172 +                       (Vector3f. -3 20 0))))
   1.173 +       (if @move-right?
   1.174 +         (.applyTorque control (Vector3f. 0 0 1)))))))
   1.175 +
   1.176 +
   1.177 +(defn worm-pattern [time]
   1.178 +  [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.179 +
   1.180 +   0 0 0 0 0 0 0 0 0 0 0
   1.181 +
   1.182 +   (* 20 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))
   1.183 +
   1.184 +   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.185 +  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.186 +  0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.187 +
   1.188 +   ])
   1.189 +
   1.190 +
   1.191 +;; (defn copier-gen []
   1.192 +;;   (let [count (atom 0)]
   1.193 +;;     (fn [in]
   1.194 +;;       (swap! count inc)
   1.195 +;;       (clojure.contrib.duck-streams/copy
   1.196 +;;        in (File. (str "/home/r/tmp/mao-test/clojure-images/"
   1.197 +;;                      ;;/home/r/tmp/mao-test/clojure-images
   1.198 +;;                (format "%08d.png" @count)))))))
   1.199 +;; (defn decrease-framerate []
   1.200 +;;   (map
   1.201 +;;    (copier-gen)
   1.202 +;;    (sort
   1.203 +;;     (map first
   1.204 +;;          (partition
   1.205 +;;           4
   1.206 +;;           (filter #(re-matches #".*.png$" (.getCanonicalPath %))
   1.207 +;;                   (file-seq
   1.208 +;;                    (file-str
   1.209 +;;                     "/home/r/media/anime/mao-temp/images"))))))))
   1.210 +
   1.211 +
   1.212 +
   1.213 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.214 +
   1.215 +
   1.216 +
   1.217 +
   1.218 +;;;;;;;;;;;;;;;;;;  Proprioception  ;;;;;;;;;;;;;;;;;;;;;;;;
   1.219 +
   1.220 +
   1.221 +;; this is not used as just getting the rotation would be simpler.
   1.222 +(defn proprioception-senses 
   1.223 +  "given a control , create a sequence of thunks that will report the
   1.224 +  rotation of the control's object along the same axes as the motor-control map."
   1.225 +  [control]
   1.226 +  (let [torques
   1.227 +        (concat
   1.228 +         (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
   1.229 +              (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
   1.230 +         [Vector3f/UNIT_X])]
   1.231 +    (map (fn [torque-axis]
   1.232 +           (fn []
   1.233 +             (.getPhysicsRotation control)))
   1.234 +           torques)))
   1.235 +
   1.236 +(defn orthogonal-vect
   1.237 +  "Return a vector orthogonal to the current one"
   1.238 +  [vector]
   1.239 +  (let [x (.getX vector)
   1.240 +        y (.getY vector)
   1.241 +        z (.getZ vector)]
   1.242 +    (cond
   1.243 +     (not= x (float 0)) (Vector3f. (- z) 0 x)
   1.244 +     (not= y (float 0)) (Vector3f. 0 (- z) y)
   1.245 +     (not= z (float 0)) (Vector3f. 0 (- z) y)
   1.246 +     true Vector3f/ZERO)))
   1.247 +
   1.248 +;; from
   1.249 +;; http://stackoverflow.com/questions/3684269/ \\
   1.250 +;;   component-of-a-quaternion-rotation-around-an-axis
   1.251 +(defn rot-about-axis [#^Quaternion q #^Vector3f axis]
   1.252 +  (let [basis-1 (orthogonal-vect axis)
   1.253 +        basis-2 (.cross axis basis-1)
   1.254 +        rotated (.mult q basis-1)
   1.255 +        alpha (.dot basis-1 (.project rotated basis-1))
   1.256 +        beta  (.dot basis-2 (.project rotated basis-2))]
   1.257 +    (println-repl alpha)
   1.258 +    (println-repl beta)
   1.259 +    (Math/atan2 beta alpha)))
   1.260 +
   1.261 +
   1.262 +(defn check-rot [a]
   1.263 +  (rot-about-axis
   1.264 +   (doto (Quaternion.)
   1.265 +     (.fromAngleAxis
   1.266 +      (float a)
   1.267 +      (Vector3f. 1 0 0))) (Vector3f. 1 0 0)))
   1.268 +
   1.269 +(defn relative-positions [joint]
   1.270 +  (let [object-a (.getUserObject (.getBodyA joint))
   1.271 +        object-b (.getUserObject (.getBodyB joint))
   1.272 +        arm-a
   1.273 +        (.normalize
   1.274 +         (.subtract 
   1.275 +          (.localToWorld object-a (.getPivotA joint) nil)
   1.276 +          (.getWorldTranslation object-a)))
   1.277 +        rotate-a
   1.278 +         (doto (Matrix3f.)
   1.279 +           (.fromStartEndVectors arm-a Vector3f/UNIT_X))
   1.280 +        arm-b
   1.281 +        (.mult
   1.282 +         rotate-a 
   1.283 +         (.normalize
   1.284 +          (.subtract 
   1.285 +           (.localToWorld object-b (.getPivotB joint) nil)
   1.286 +           (.getWorldTranslation object-b))))
   1.287 +        rotate-b
   1.288 +        (doto (Matrix3f.)
   1.289 +          (.fromStartEndVectors arm-b Vector3f/UNIT_X))
   1.290 +        
   1.291 +        pitch
   1.292 +        (.angleBetween
   1.293 +         (.normalize (Vector2f. (.getX arm-b) (.getY arm-b)))
   1.294 +         (Vector2f. 1 0))
   1.295 +        yaw
   1.296 +        (.angleBetween
   1.297 +         (.normalize (Vector2f. (.getX arm-b) (.getZ arm-b)))
   1.298 +         (Vector2f. 1 0))
   1.299 +                     
   1.300 +        roll
   1.301 +        (.mult 
   1.302 +         (.getLocalRotation object-b)
   1.303 +         (doto (Quaternion.)
   1.304 +           (.fromRotationMatrix rotate-a)))
   1.305 +         ]
   1.306 +         
   1.307 +                
   1.308 +
   1.309 +    ;;(println-repl
   1.310 +    ;; "arm-b is " arm-b)
   1.311 +    ;;(println-repl
   1.312 +    ;; "pivot-b is " (.getPivotB joint))
   1.313 +    ;;(println-repl
   1.314 +    ;; (format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
   1.315 +    ;;         pitch yaw roll))
   1.316 +    [pitch yaw roll]))
   1.317 +
   1.318 +        
   1.319 +    
   1.320 +        
   1.321 +  
   1.322 +(defn proprioception
   1.323 +  "Create a proprioception map that reports the rotations of the
   1.324 +  various limbs of the creature's body"
   1.325 +  [creature]
   1.326 +  [#^Node creature]
   1.327 +  (let [
   1.328 +        nodes (node-seq creature)
   1.329 +        joints
   1.330 +        (map
   1.331 +         :joint 
   1.332 +         (filter
   1.333 +          #(isa? (class %) JointControl)
   1.334 +          (reduce
   1.335 +           concat
   1.336 +           (map (fn [node]
   1.337 +                  (map (fn [num] (.getControl node num))
   1.338 +                       (range (.getNumControls node))))
   1.339 +                nodes))))]
   1.340 +    (fn []
   1.341 +      (reduce concat (map relative-positions (list (first joints)))))))
   1.342 +        
   1.343 +
   1.344 +(defn test-worm-control
   1.345 +  []
   1.346 +  (let [worm (point-worm)
   1.347 +        time (atom 0)
   1.348 +        worm-motor-map (motor-map worm)
   1.349 +        body-map (proprioception worm)
   1.350 +        debug-segments
   1.351 +        (map
   1.352 +         #(doto
   1.353 +              (make-shape
   1.354 +               (assoc base-shape
   1.355 +                 :name "debug-line"
   1.356 +                 :physical? false
   1.357 +                 :shape
   1.358 +                 (com.jme3.scene.shape.Line.
   1.359 +                  (.add (.getWorldTranslation %)
   1.360 +                        (Vector3f. -0.2 0 0 ))
   1.361 +                  (.add (.getWorldTranslation %)
   1.362 +                        (Vector3f. 0.2 0 0)))))
   1.363 +                 (.setMaterial (green-x-ray)))
   1.364 +            (drop 1 (node-seq worm)))]
   1.365 +    (world
   1.366 +     (nodify [worm
   1.367 +              (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
   1.368 +                   :color ColorRGBA/Gray)])
   1.369 +     standard-debug-controls
   1.370 +     (fn [world]
   1.371 +       (.attachChild (.getRootNode world) (nodify debug-segments))
   1.372 +       (enable-debug world)
   1.373 +       (light-up-everything world)
   1.374 +       (com.aurellem.capture.Capture/captureVideo
   1.375 +        world
   1.376 +        (file-str "/home/r/proj/cortex/tmp/moving-worm")))
   1.377 +     
   1.378 +     (fn [_ _]
   1.379 +       (dorun
   1.380 +        (map
   1.381 +         (fn [worm-segment
   1.382 +              debug-segment]
   1.383 +           (.rotate
   1.384 +            debug-segment
   1.385 +            (Quaternion. (float 0) (float 0.05) (float 0) (float 1))))
   1.386 +         (drop 1 (node-seq worm))
   1.387 +         debug-segments))
   1.388 +       (swap! time inc)
   1.389 +       (println-repl (with-out-str (clojure.pprint/pprint (doall (body-map)))))
   1.390 +       (Thread/sleep 200)
   1.391 +       (dorun (worm-motor-map
   1.392 +               (worm-pattern @time)))))))
   1.393 +
   1.394 +
   1.395 +
   1.396 +
   1.397 +
   1.398 +(defn test-prop
   1.399 +  "see how torque works."
   1.400 +  []
   1.401 +  (let [hand    (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
   1.402 +                     :mass 0 :color ColorRGBA/Green)
   1.403 +        finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
   1.404 +                     :mass 1 :color (ColorRGBA. 0.20 0.40 0.99 1.0))
   1.405 +        floor   (box 10 0.5 10 :position (Vector3f. 0 -5 0)
   1.406 +                     :mass 0 :color ColorRGBA/Gray)
   1.407 +
   1.408 +        move-up? (atom false)
   1.409 +        move-down? (atom false)
   1.410 +        move-left? (atom false)
   1.411 +        move-right? (atom false)
   1.412 +        roll-left? (atom false)
   1.413 +        roll-right? (atom false)
   1.414 +        control (.getControl finger RigidBodyControl)
   1.415 +        joint
   1.416 +        (doto 
   1.417 +            (Point2PointJoint.
   1.418 +             (.getControl hand RigidBodyControl)
   1.419 +             control
   1.420 +             (Vector3f. 1.2 0 0)
   1.421 +             (Vector3f. -1.2 0 0 ))
   1.422 +          (.setCollisionBetweenLinkedBodys false))
   1.423 +        time (atom 0)
   1.424 +        ]
   1.425 +    (world
   1.426 +     (nodify [hand finger floor])
   1.427 +     (merge standard-debug-controls
   1.428 +            {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
   1.429 +             "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
   1.430 +             "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
   1.431 +             "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
   1.432 +             "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
   1.433 +             "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})     
   1.434 +     (fn [world]
   1.435 +       (set-gravity world Vector3f/ZERO)
   1.436 +       (.setMoveSpeed (.getFlyByCamera world) 50)
   1.437 +       (.setRotationSpeed (.getFlyByCamera world) 50)
   1.438 +       (light-up-everything world)
   1.439 +       (.setTimer world (NanoTimer.))
   1.440 +       )
   1.441 +     (fn [_ _]
   1.442 +       (if @move-up?
   1.443 +         (.applyTorque control
   1.444 +                       (.mult (.getPhysicsRotation control)
   1.445 +                       (Vector3f. 0 0 1))))
   1.446 +       (if @move-down?
   1.447 +         (.applyTorque control
   1.448 +                       (.mult (.getPhysicsRotation control)
   1.449 +                              (Vector3f. 0 0 -1))))
   1.450 +       (if @move-left?
   1.451 +         (.applyTorque control
   1.452 +                       (.mult (.getPhysicsRotation control)
   1.453 +                              (Vector3f. 0 1 0))))
   1.454 +       (if @move-right?
   1.455 +         (.applyTorque control
   1.456 +                       (.mult (.getPhysicsRotation control)
   1.457 +                              (Vector3f. 0 -1 0))))
   1.458 +       (if @roll-left?
   1.459 +         (.applyTorque control
   1.460 +                       (.mult (.getPhysicsRotation control)
   1.461 +                              (Vector3f. -0.1 0 0))))
   1.462 +       (if @roll-right?
   1.463 +         (.applyTorque control
   1.464 +                       (.mult (.getPhysicsRotation control)
   1.465 +                              (Vector3f. 0.1 0 0))))
   1.466 +
   1.467 +       (if (= 0 (rem (swap! time inc) 2000))
   1.468 +         (do 
   1.469 +           ;;(println-repl (.getLocalRotation finger))
   1.470 +           (println-repl (nth (relative-positions joint) 2))))
   1.471 +
   1.472 +       ))))
   1.473 +
   1.474 +
   1.475 +
   1.476 +
   1.477 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.478  
   1.479  
   1.480  
   1.481  
   1.482  #+end_src
   1.483  
   1.484 +#+results: body-main
   1.485 +: #'cortex.body/test-prop
   1.486 +
   1.487  
   1.488  
   1.489  
   1.490 @@ -452,3 +850,4 @@
   1.491  <<body-main>>
   1.492  #+end_src
   1.493    
   1.494 +