diff org/body.org @ 64:ab1fee4280c3

divided body into test suite and core functions
author Robert McIntyre <rlm@mit.edu>
date Wed, 30 Nov 2011 20:42:07 -0700
parents 7f2653ad3199
children 4b5f00110d8c
line wrap: on
line diff
     1.1 --- a/org/body.org	Tue Nov 29 02:46:46 2011 -0700
     1.2 +++ b/org/body.org	Wed Nov 30 20:42:07 2011 -0700
     1.3 @@ -5,90 +5,21 @@
     1.4  #+SETUPFILE: ../../aurellem/org/setup.org
     1.5  #+INCLUDE: ../../aurellem/org/level-0.org
     1.6  
     1.7 -* COMMENT Body  
     1.8  
     1.9 -#+srcname: body-main
    1.10 +
    1.11 +* Proprioception
    1.12 +#+srcname: proprioception
    1.13  #+begin_src clojure 
    1.14  (ns cortex.body
    1.15 -  (use (cortex world util import)))
    1.16 +  (:use (cortex world util))
    1.17 +  (:import
    1.18 +   com.jme3.math.Vector3f
    1.19 +   com.jme3.math.Quaternion
    1.20 +   com.jme3.math.Vector2f
    1.21 +   com.jme3.math.Matrix3f
    1.22 +   com.jme3.bullet.control.RigidBodyControl))
    1.23  
    1.24 -(use 'clojure.contrib.def)
    1.25 -(cortex.import/mega-import-jme3)
    1.26 -(rlm.rlm-commands/help)
    1.27 -
    1.28 -(defn load-blender-model
    1.29 -  "Load a .blend file using an asset folder relative path."
    1.30 -  [^String model]
    1.31 -  (.loadModel
    1.32 -   (doto (asset-manager)
    1.33 -     (.registerLoader BlenderModelLoader (into-array String ["blend"])))
    1.34 -   model))
    1.35 -
    1.36 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.37 -
    1.38 -;;;;;;;;;;;;  eve-style bodies  ;;;;;;;;
    1.39 -
    1.40 -(defn worm-segments
    1.41 -  "Create multiple evenly spaced box segments. They're fabulous!"
    1.42 -  [segment-length num-segments interstitial-space radius]
    1.43 -  (letfn [(nth-segment
    1.44 -            [n]
    1.45 -            (box segment-length radius radius :mass 0.1
    1.46 -                 :position
    1.47 -                 (Vector3f.
    1.48 -                  (* 2 n (+ interstitial-space segment-length)) 0 0)
    1.49 -                 :name (str "worm-segment" n)
    1.50 -                 :color (ColorRGBA/randomColor)))]
    1.51 -    (map nth-segment (range num-segments))))
    1.52 -
    1.53 -(defn connect-at-midpoint
    1.54 -  "Connect two physics objects with a Point2Point joint constraint at
    1.55 -  the point equidistant from both objects' centers."
    1.56 -  [segmentA segmentB]
    1.57 -  (let [centerA (.getWorldTranslation segmentA)
    1.58 -        centerB (.getWorldTranslation segmentB)
    1.59 -        midpoint (.mult (.add centerA centerB) (float 0.5))
    1.60 -        pivotA (.subtract midpoint centerA)
    1.61 -        pivotB (.subtract midpoint centerB)
    1.62 -
    1.63 -        ;; A side-effect of creating a joint registers
    1.64 -        ;; it with both physics objects which in turn
    1.65 -        ;; will register the joint with the physics system
    1.66 -        ;; when the simulation is started.
    1.67 -        joint (Point2PointJoint.
    1.68 -               (.getControl segmentA RigidBodyControl)
    1.69 -               (.getControl segmentB RigidBodyControl)
    1.70 -               pivotA
    1.71 -               pivotB)]
    1.72 -  segmentB))
    1.73 -
    1.74 -(defn point-worm []
    1.75 -  (let [segments (worm-segments 0.2 5 0.1 0.1)]
    1.76 -    (dorun (map (partial apply connect-at-midpoint)
    1.77 -                (partition 2 1 segments)))
    1.78 -    (nodify "worm" segments)))
    1.79 -
    1.80 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.81 -;;;;;;;;;  Proprioception  ;;;;;;;;;;;;;
    1.82 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    1.83 -
    1.84 -(declare
    1.85 - ;; generate an arbitray (but stable) orthogonal vector
    1.86 - ;; to a given vector.
    1.87 - some-orthogonal
    1.88 -
    1.89 - ;; determine the amount of rotation a quaternion will
    1.90 - ;; cause about a given axis
    1.91 - project-quaternion
    1.92 -
    1.93 - ;; proprioception for a single joint
    1.94 - joint-proprioception
    1.95 - 
    1.96 - ;; create a function that provides proprioceptive information
    1.97 - ;; about an entire body.
    1.98 - proprioception)
    1.99 -
   1.100 -(defn some-orthogonal
   1.101 +(defn any-orthogonal
   1.102    "Generate an arbitray (but stable) orthogonal vector to a given
   1.103     vector."
   1.104    [vector]
   1.105 @@ -108,7 +39,7 @@
   1.106     Determine the amount of rotation a quaternion will
   1.107     cause about a given axis."
   1.108    [#^Quaternion q #^Vector3f axis]
   1.109 -  (let [basis-1 (orthogonal-vect axis)
   1.110 +  (let [basis-1 (any-orthogonal axis)
   1.111          basis-2 (.cross axis basis-1)
   1.112          rotated (.mult q basis-1)
   1.113          alpha (.dot basis-1 (.project rotated basis-1))
   1.114 @@ -147,7 +78,7 @@
   1.115           (Vector2f. 1 0))
   1.116                       
   1.117          roll
   1.118 -        (rot-about-axis
   1.119 +        (project-quaternion
   1.120           (.mult 
   1.121            (.getLocalRotation object-b)
   1.122            (doto (Quaternion.)
   1.123 @@ -171,11 +102,11 @@
   1.124      (fn []
   1.125        (map joint-proprioception joints))))
   1.126    
   1.127 +#+end_src
   1.128  
   1.129 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.130 -;;;;;;;;;  Mortor Control  ;;;;;;;;;;;;;
   1.131 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.132 -
   1.133 +#+srcname: motor-control
   1.134 +#+begin_src clojure
   1.135 +(in-ns 'cortex.body)
   1.136  
   1.137  ;; surprisingly enough, terristerial creatures only move by using
   1.138  ;; torque applied about their joints.  There's not a single straight
   1.139 @@ -191,29 +122,73 @@
   1.140      (fn [torques]
   1.141        (map #(.applyTorque %1 %2)
   1.142             controls torques))))
   1.143 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.144 +#+end_src
   1.145 + 
   1.146 +## note -- might want to add a lower dimensional, discrete version of
   1.147 +## this if it proves useful from a x-modal clustering perspective.
   1.148  
   1.149 -;; note -- might want to add a lower dimensional, discrete version of
   1.150 -;; this if it proves usefull from a x-modal clustering perspective.
   1.151 +* Examples
   1.152  
   1.153 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   1.154 +#+srcname: test-body
   1.155 +#+begin_src clojure
   1.156 +(ns test.body
   1.157 +  (:use (cortex world util body))
   1.158 +  (:import
   1.159 +   com.jme3.math.Vector3f
   1.160 +   com.jme3.math.ColorRGBA
   1.161 +   com.jme3.bullet.joints.Point2PointJoint
   1.162 +   com.jme3.bullet.control.RigidBodyControl
   1.163 +   com.jme3.system.NanoTimer))
   1.164  
   1.165 +(defn worm-segments
   1.166 +  "Create multiple evenly spaced box segments. They're fabulous!"
   1.167 +  [segment-length num-segments interstitial-space radius]
   1.168 +  (letfn [(nth-segment
   1.169 +            [n]
   1.170 +            (box segment-length radius radius :mass 0.1
   1.171 +                 :position
   1.172 +                 (Vector3f.
   1.173 +                  (* 2 n (+ interstitial-space segment-length)) 0 0)
   1.174 +                 :name (str "worm-segment" n)
   1.175 +                 :color (ColorRGBA/randomColor)))]
   1.176 +    (map nth-segment (range num-segments))))
   1.177  
   1.178 +(defn connect-at-midpoint
   1.179 +  "Connect two physics objects with a Point2Point joint constraint at
   1.180 +  the point equidistant from both objects' centers."
   1.181 +  [segmentA segmentB]
   1.182 +  (let [centerA (.getWorldTranslation segmentA)
   1.183 +        centerB (.getWorldTranslation segmentB)
   1.184 +        midpoint (.mult (.add centerA centerB) (float 0.5))
   1.185 +        pivotA (.subtract midpoint centerA)
   1.186 +        pivotB (.subtract midpoint centerB)
   1.187 +        
   1.188 +        ;; A side-effect of creating a joint registers
   1.189 +        ;; it with both physics objects which in turn
   1.190 +        ;; will register the joint with the physics system
   1.191 +        ;; when the simulation is started.
   1.192 +        joint (Point2PointJoint.
   1.193 +               (.getControl segmentA RigidBodyControl)
   1.194 +               (.getControl segmentB RigidBodyControl)
   1.195 +               pivotA
   1.196 +               pivotB)]
   1.197 +    segmentB))
   1.198  
   1.199 -(defn worm-pattern [time]
   1.200 -  [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.201 +(defn eve-worm
   1.202 +  "Create a worm body bound by invisible joint constraints."
   1.203 +  []
   1.204 +  (let [segments (worm-segments 0.2 5 0.1 0.1)]
   1.205 +    (dorun (map (partial apply connect-at-midpoint)
   1.206 +                (partition 2 1 segments)))
   1.207 +    (nodify "worm" segments)))
   1.208  
   1.209 -   0 0 0 0 0 0 0 0 0 0 0
   1.210 -
   1.211 -   (* 20 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))
   1.212 -
   1.213 -   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.214 -  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.215 -  0 0 0 0 0 0 0 0 0 0 0 0 0 0
   1.216 -
   1.217 -   ])
   1.218 -
   1.219 -(defn worm-pattern [time]
   1.220 -  (let [angle (* Math/PI (/ 4 20))
   1.221 +(defn worm-pattern
   1.222 +  "This is a simple, mindless motor control pattern that drives the
   1.223 +   second segment of the worm's body at an offset angle with
   1.224 +   sinusoidally varying strength."
   1.225 +  [time]
   1.226 +  (let [angle (* Math/PI (/ 9 20))
   1.227          direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]
   1.228      [Vector3f/ZERO
   1.229       (.mult
   1.230 @@ -223,9 +198,11 @@
   1.231       Vector3f/ZERO
   1.232       Vector3f/ZERO]))
   1.233  
   1.234 -(defn test-worm-control
   1.235 +(defn test-motor-control
   1.236 +  "You should see a multi-segmented worm-like object fall onto the
   1.237 +   table and begin writhing and moving."
   1.238    []
   1.239 -  (let [worm (point-worm)
   1.240 +  (let [worm (eve-worm)
   1.241          time (atom 0)
   1.242          worm-motor-map (vector-motor-control worm)]
   1.243      (world
   1.244 @@ -244,15 +221,16 @@
   1.245       
   1.246       (fn [_ _]
   1.247         (swap! time inc)
   1.248 -       ;;(Thread/sleep 200)
   1.249 +       (Thread/sleep 20)
   1.250         (dorun (worm-motor-map
   1.251                 (worm-pattern @time)))))))
   1.252  
   1.253 -
   1.254 -
   1.255 -
   1.256 -(defn test-prop
   1.257 -  "see how torque works."
   1.258 +(defn test-proprioception
   1.259 +  "You should see two foating bars, and a printout of pitch, yaw, and
   1.260 +   roll. Pressing key-r/key-t should move the blue bar up and down and
   1.261 +   change only the value of pitch. key-f/key-g moves it side to side
   1.262 +   and changes yaw. key-v/key-b will spin the blue segment clockwise
   1.263 +   and counterclockwise, and only affect roll."
   1.264    []
   1.265    (let [hand    (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
   1.266                       :mass 0 :color ColorRGBA/Green)
   1.267 @@ -276,8 +254,7 @@
   1.268               (Vector3f. 1.2 0 0)
   1.269               (Vector3f. -1.2 0 0 ))
   1.270            (.setCollisionBetweenLinkedBodys false))
   1.271 -        time (atom 0)
   1.272 -        ]
   1.273 +        time (atom 0)]
   1.274      (world
   1.275       (nodify [hand finger floor])
   1.276       (merge standard-debug-controls
   1.277 @@ -327,9 +304,12 @@
   1.278              (comp
   1.279               println-repl
   1.280               #(format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n" %1 %2 %3))
   1.281 -            (relative-positions joint))))))))
   1.282 +            (joint-proprioception joint))))))))
   1.283 +#+end_src
   1.284  
   1.285 -#+end_src
   1.286 +#+results: test-body
   1.287 +: #'test.body/test-proprioception
   1.288 +
   1.289  
   1.290  
   1.291  * COMMENT code-limbo
   1.292 @@ -339,6 +319,16 @@
   1.293  ;;   (.registerLoader BlenderModelLoader (into-array String ["blend"])))
   1.294  ;;   "Models/person/person.blend")
   1.295  
   1.296 +
   1.297 +(defn load-blender-model
   1.298 +  "Load a .blend file using an asset folder relative path."
   1.299 +  [^String model]
   1.300 +  (.loadModel
   1.301 +   (doto (asset-manager)
   1.302 +     (.registerLoader BlenderModelLoader (into-array String ["blend"])))
   1.303 +   model))
   1.304 +
   1.305 +
   1.306  (defn view-model [^String model]
   1.307    (view 
   1.308     (.loadModel 
   1.309 @@ -757,7 +747,13 @@
   1.310  
   1.311  * COMMENT generate Source.
   1.312  #+begin_src clojure :tangle ../src/cortex/body.clj
   1.313 -<<body-main>>
   1.314 +<<proprioception>>
   1.315 +<<motor-control>>
   1.316  #+end_src
   1.317 +
   1.318 +#+begin_src clojure :tangle ../src/test/body.clj
   1.319 +<<test-body>>
   1.320 +#+end_src  
   1.321 +
   1.322 +
   1.323    
   1.324 -