# HG changeset patch # User Robert McIntyre # Date 1322710927 25200 # Node ID ab1fee4280c39a50328787d381b0a942d77ba82c # Parent 7f2653ad3199319c72462b5e9e997e810643f831 divided body into test suite and core functions diff -r 7f2653ad3199 -r ab1fee4280c3 org/body.org --- a/org/body.org Tue Nov 29 02:46:46 2011 -0700 +++ b/org/body.org Wed Nov 30 20:42:07 2011 -0700 @@ -5,90 +5,21 @@ #+SETUPFILE: ../../aurellem/org/setup.org #+INCLUDE: ../../aurellem/org/level-0.org -* COMMENT Body -#+srcname: body-main + +* Proprioception +#+srcname: proprioception #+begin_src clojure (ns cortex.body - (use (cortex world util import))) + (:use (cortex world util)) + (:import + com.jme3.math.Vector3f + com.jme3.math.Quaternion + com.jme3.math.Vector2f + com.jme3.math.Matrix3f + com.jme3.bullet.control.RigidBodyControl)) -(use 'clojure.contrib.def) -(cortex.import/mega-import-jme3) -(rlm.rlm-commands/help) - -(defn load-blender-model - "Load a .blend file using an asset folder relative path." - [^String model] - (.loadModel - (doto (asset-manager) - (.registerLoader BlenderModelLoader (into-array String ["blend"]))) - model)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;;;;;;;;;;; eve-style bodies ;;;;;;;; - -(defn worm-segments - "Create multiple evenly spaced box segments. They're fabulous!" - [segment-length num-segments interstitial-space radius] - (letfn [(nth-segment - [n] - (box segment-length radius radius :mass 0.1 - :position - (Vector3f. - (* 2 n (+ interstitial-space segment-length)) 0 0) - :name (str "worm-segment" n) - :color (ColorRGBA/randomColor)))] - (map nth-segment (range num-segments)))) - -(defn connect-at-midpoint - "Connect two physics objects with a Point2Point joint constraint at - the point equidistant from both objects' centers." - [segmentA segmentB] - (let [centerA (.getWorldTranslation segmentA) - centerB (.getWorldTranslation segmentB) - midpoint (.mult (.add centerA centerB) (float 0.5)) - pivotA (.subtract midpoint centerA) - pivotB (.subtract midpoint centerB) - - ;; A side-effect of creating a joint registers - ;; it with both physics objects which in turn - ;; will register the joint with the physics system - ;; when the simulation is started. - joint (Point2PointJoint. - (.getControl segmentA RigidBodyControl) - (.getControl segmentB RigidBodyControl) - pivotA - pivotB)] - segmentB)) - -(defn point-worm [] - (let [segments (worm-segments 0.2 5 0.1 0.1)] - (dorun (map (partial apply connect-at-midpoint) - (partition 2 1 segments))) - (nodify "worm" segments))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;; Proprioception ;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(declare - ;; generate an arbitray (but stable) orthogonal vector - ;; to a given vector. - some-orthogonal - - ;; determine the amount of rotation a quaternion will - ;; cause about a given axis - project-quaternion - - ;; proprioception for a single joint - joint-proprioception - - ;; create a function that provides proprioceptive information - ;; about an entire body. - proprioception) - -(defn some-orthogonal +(defn any-orthogonal "Generate an arbitray (but stable) orthogonal vector to a given vector." [vector] @@ -108,7 +39,7 @@ Determine the amount of rotation a quaternion will cause about a given axis." [#^Quaternion q #^Vector3f axis] - (let [basis-1 (orthogonal-vect axis) + (let [basis-1 (any-orthogonal axis) basis-2 (.cross axis basis-1) rotated (.mult q basis-1) alpha (.dot basis-1 (.project rotated basis-1)) @@ -147,7 +78,7 @@ (Vector2f. 1 0)) roll - (rot-about-axis + (project-quaternion (.mult (.getLocalRotation object-b) (doto (Quaternion.) @@ -171,11 +102,11 @@ (fn [] (map joint-proprioception joints)))) +#+end_src -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;; Mortor Control ;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - +#+srcname: motor-control +#+begin_src clojure +(in-ns 'cortex.body) ;; surprisingly enough, terristerial creatures only move by using ;; torque applied about their joints. There's not a single straight @@ -191,29 +122,73 @@ (fn [torques] (map #(.applyTorque %1 %2) controls torques)))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +#+end_src + +## note -- might want to add a lower dimensional, discrete version of +## this if it proves useful from a x-modal clustering perspective. -;; note -- might want to add a lower dimensional, discrete version of -;; this if it proves usefull from a x-modal clustering perspective. +* Examples -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +#+srcname: test-body +#+begin_src clojure +(ns test.body + (:use (cortex world util body)) + (:import + com.jme3.math.Vector3f + com.jme3.math.ColorRGBA + com.jme3.bullet.joints.Point2PointJoint + com.jme3.bullet.control.RigidBodyControl + com.jme3.system.NanoTimer)) +(defn worm-segments + "Create multiple evenly spaced box segments. They're fabulous!" + [segment-length num-segments interstitial-space radius] + (letfn [(nth-segment + [n] + (box segment-length radius radius :mass 0.1 + :position + (Vector3f. + (* 2 n (+ interstitial-space segment-length)) 0 0) + :name (str "worm-segment" n) + :color (ColorRGBA/randomColor)))] + (map nth-segment (range num-segments)))) +(defn connect-at-midpoint + "Connect two physics objects with a Point2Point joint constraint at + the point equidistant from both objects' centers." + [segmentA segmentB] + (let [centerA (.getWorldTranslation segmentA) + centerB (.getWorldTranslation segmentB) + midpoint (.mult (.add centerA centerB) (float 0.5)) + pivotA (.subtract midpoint centerA) + pivotB (.subtract midpoint centerB) + + ;; A side-effect of creating a joint registers + ;; it with both physics objects which in turn + ;; will register the joint with the physics system + ;; when the simulation is started. + joint (Point2PointJoint. + (.getControl segmentA RigidBodyControl) + (.getControl segmentB RigidBodyControl) + pivotA + pivotB)] + segmentB)) -(defn worm-pattern [time] - [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +(defn eve-worm + "Create a worm body bound by invisible joint constraints." + [] + (let [segments (worm-segments 0.2 5 0.1 0.1)] + (dorun (map (partial apply connect-at-midpoint) + (partition 2 1 segments))) + (nodify "worm" segments))) - 0 0 0 0 0 0 0 0 0 0 0 - - (* 20 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300)))) - - 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 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 0 0 - - ]) - -(defn worm-pattern [time] - (let [angle (* Math/PI (/ 4 20)) +(defn worm-pattern + "This is a simple, mindless motor control pattern that drives the + second segment of the worm's body at an offset angle with + sinusoidally varying strength." + [time] + (let [angle (* Math/PI (/ 9 20)) direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))] [Vector3f/ZERO (.mult @@ -223,9 +198,11 @@ Vector3f/ZERO Vector3f/ZERO])) -(defn test-worm-control +(defn test-motor-control + "You should see a multi-segmented worm-like object fall onto the + table and begin writhing and moving." [] - (let [worm (point-worm) + (let [worm (eve-worm) time (atom 0) worm-motor-map (vector-motor-control worm)] (world @@ -244,15 +221,16 @@ (fn [_ _] (swap! time inc) - ;;(Thread/sleep 200) + (Thread/sleep 20) (dorun (worm-motor-map (worm-pattern @time))))))) - - - -(defn test-prop - "see how torque works." +(defn test-proprioception + "You should see two foating bars, and a printout of pitch, yaw, and + roll. Pressing key-r/key-t should move the blue bar up and down and + change only the value of pitch. key-f/key-g moves it side to side + and changes yaw. key-v/key-b will spin the blue segment clockwise + and counterclockwise, and only affect roll." [] (let [hand (box 1 0.2 0.2 :position (Vector3f. 0 2 0) :mass 0 :color ColorRGBA/Green) @@ -276,8 +254,7 @@ (Vector3f. 1.2 0 0) (Vector3f. -1.2 0 0 )) (.setCollisionBetweenLinkedBodys false)) - time (atom 0) - ] + time (atom 0)] (world (nodify [hand finger floor]) (merge standard-debug-controls @@ -327,9 +304,12 @@ (comp println-repl #(format "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n" %1 %2 %3)) - (relative-positions joint)))))))) + (joint-proprioception joint)))))))) +#+end_src -#+end_src +#+results: test-body +: #'test.body/test-proprioception + * COMMENT code-limbo @@ -339,6 +319,16 @@ ;; (.registerLoader BlenderModelLoader (into-array String ["blend"]))) ;; "Models/person/person.blend") + +(defn load-blender-model + "Load a .blend file using an asset folder relative path." + [^String model] + (.loadModel + (doto (asset-manager) + (.registerLoader BlenderModelLoader (into-array String ["blend"]))) + model)) + + (defn view-model [^String model] (view (.loadModel @@ -757,7 +747,13 @@ * COMMENT generate Source. #+begin_src clojure :tangle ../src/cortex/body.clj -<> +<> +<> #+end_src + +#+begin_src clojure :tangle ../src/test/body.clj +<> +#+end_src + + -