Mercurial > cortex
view org/test-creature.org @ 83:14b604e955ed
still testing joints... Dylan is helping
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 07 Jan 2012 00:58:47 -0700 |
parents | 6b4ca076285e |
children | 4f5e2c629e45 |
line wrap: on
line source
1 #+title: First attempt at a creature!2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description:5 #+keywords: simulation, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org9 * Intro10 So far, I've made the following senses --11 - Vision12 - Hearing13 - Touch14 - Proprioception16 And one effector:17 - Movement19 However, the code so far has only enabled these senses, but has not20 actually implemented them. For example, there is still a lot of work21 to be done for vision. I need to be able to create an /eyeball/ in22 simulation that can be moved around and see the world from different23 angles. I also need to determine weather to use log-polar or cartesian24 for the visual input, and I need to determine how/wether to25 disceritise the visual input.27 I also want to be able to visualize both the sensors and the28 effectors in pretty pictures. This semi-retarted creature will by my29 first attempt at bringing everything together.31 * The creature's body33 Still going to do an eve-like body in blender, but due to problems34 importing the joints, etc into jMonkeyEngine3, I',m going to do all35 the connecting here in clojure code, using the names of the individual36 components and trial and error. Later, I'll maybe make some sort of37 creature-building modifications to blender that support whatever38 discreitized senses I'm going to make.40 #+name: body-141 #+begin_src clojure42 (ns cortex.silly43 "let's play!"44 {:author "Robert McIntyre"})46 ;; TODO remove this!47 (require 'cortex.import)48 (cortex.import/mega-import-jme3)49 (use '(cortex world util body hearing touch vision))51 (rlm.rlm-commands/help)53 (declare joint-create get-subjective-position)55 (defn load-bullet []56 (.start (world (Node.) {} no-op no-op)))58 (defn load-blender-model59 "Load a .blend file using an asset folder relative path."60 [^String model]61 (.loadModel62 (doto (asset-manager)63 (.registerLoader BlenderModelLoader (into-array String ["blend"])))64 model))66 (defn meta-data [blender-node key]67 (if-let [data (.getUserData blender-node "properties")]68 (.findValue data key)69 nil))71 (defn blender-to-jme72 "Convert from Blender coordinates to JME coordinates"73 [#^Vector3f in]74 (Vector3f. (.getX in)75 (.getZ in)76 (- (.getY in))))78 (defn jme-to-blender79 "Convert from JME coordinates to Blender coordinates"80 [#^Vector3f in]81 (Vector3f. (.getX in)82 (- (.getZ in))83 (.getY in)))85 (defn joint-targets86 "Return the two closest two objects to the joint object, ordered87 from bottom to top according to the joint's rotation."88 [#^Node parts #^Node joint]89 ;;(println (meta-data joint "joint"))90 (.getWorldRotation joint)91 (loop [radius (float 0.01)]92 (let [results (CollisionResults.)]93 (.collideWith94 parts95 (BoundingBox. (.getWorldTranslation joint)96 radius radius radius)97 results)98 (let [targets99 (distinct100 (map #(.getGeometry %) results))]101 (if (>= (count targets) 2)102 (sort-by103 #(let [v104 (jme-to-blender105 (.mult106 (.inverse (.getWorldRotation joint))107 (.subtract (.getWorldTranslation %)108 (.getWorldTranslation joint))))]109 (println-repl (.getName %) ":" v)110 (.dot (Vector3f. 1 1 1)111 v))112 (take 2 targets))113 (recur (float (* radius 2))))))))115 (defn connect116 "here are some examples:117 {:type :point}118 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}119 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)121 {:type :cone :limit-xz 0]122 :limit-xy 0]123 :twist 0]} (use XZY rotation mode in blender!)"124 [#^Node obj-a #^Node obj-b #^Node joint]125 (let [center-a (.getWorldTranslation obj-a)126 center-b (.getWorldTranslation obj-b)127 joint-center (.getWorldTranslation joint)128 pivot-a (.subtract joint-center center-a)129 pivot-b (.subtract joint-center center-b)130 control-a (.getControl obj-a RigidBodyControl)131 control-b (.getControl obj-b RigidBodyControl)]132 ;; A side-effect of creating a joint registers133 ;; it with both physics objects which in turn134 ;; will register the joint with the physics system135 ;; when the simulation is started.136 (if-let [constraints137 (map-vals138 eval139 (read-string140 (meta-data joint "joint")))]142 (let [joint-type (:type constraints)]143 (println-repl "creating joint between"144 (.getName obj-a) "and" (.getName obj-b))145 (cond (= :point joint-type)146 (do147 (println-repl "creating POINT joint")148 (Point2PointJoint.149 control-a150 control-b151 pivot-a152 pivot-b))153 (= :hinge joint-type)154 (do155 (println-repl "creating HINGE joint")156 (let [axis (if-let157 [axis (:axis constraints)]158 axis159 Vector3f/UNIT_X)160 [limit-1 limit-2] (:limit constraints)161 hinge-axis162 (.mult163 (.getWorldRotation joint)164 (blender-to-jme axis))]165 (doto166 (HingeJoint.167 control-a168 control-b169 pivot-a170 pivot-b171 hinge-axis172 hinge-axis)173 (.setLimit limit-1 limit-2))))174 (= :cone joint-type)175 (do176 (let [limit-xz (:limit-xz constraints)177 limit-xy (:limit-xy constraints)178 twist (:twist constraints)]180 (println-repl "creating CONE joint")181 (let [frame-a182 (.toRotationMatrix183 (doto (Quaternion.)184 (.fromAngleAxis185 (float186 (.angleBetween187 (.normalize pivot-a) Vector3f/UNIT_X))188 (.normalize189 (.cross pivot-a190 Vector3f/UNIT_X)))))191 ]192 (println-repl "pivot-a" pivot-a)193 (println-repl194 "angle between pivot-a and UNIT_X is"195 (.angleBetween Vector3f/UNIT_X (.normalize pivot-a)))196 (println-repl "frame-a:" frame-a)197 (println-repl198 "frame-a moves Vector3f/UNIT_X to"199 (.mult frame-a Vector3f/UNIT_X ))202 (doto203 (ConeJoint.204 control-a205 control-b206 pivot-a207 pivot-b210 ;; frame-in-A211 ;;frame-a212 ;;frame-a214 (.toRotationMatrix215 (doto (Quaternion.)216 (.fromAngles217 0 0 (* -0.5 (/ Math/PI 2)))))220 ;; frame-in-B221 (.toRotationMatrix222 (doto (Quaternion.)223 (.fromAngles224 0 0 (* -0.5 (/ Math/PI 2)))))227 )228 (.setLimit (float limit-xz)229 (float limit-xy)230 (float twist))))))231 true232 (println-repl233 "joint-type" joint-type "not recognized")))235 (println-repl "could not find joint meta-data!"))))238 (defn assemble-creature [#^Node pieces joints]239 (dorun240 (map241 (fn [geom]242 (let [physics-control243 (RigidBodyControl.244 (HullCollisionShape.245 (.getMesh geom))246 (if-let [mass (meta-data geom "mass")]247 (do248 (println-repl249 "setting" (.getName geom) "mass to" (float mass))250 (float mass))251 (float 1)))]253 (.addControl geom physics-control)))254 (filter #(isa? (class %) Geometry )255 (node-seq pieces))))257 (dorun258 (map259 (fn [joint]260 (let [[obj-a obj-b]261 (joint-targets pieces joint)]262 (connect obj-a obj-b joint)))263 joints))264 pieces)266 (defn blender-creature [blender-path]267 (let [model (load-blender-model blender-path)268 joints269 (if-let [joint-node (.getChild model "joints")]270 (seq (.getChildren joint-node))271 (do (println-repl "could not find joints node")272 []))]273 (assemble-creature model joints)))275 (def hand "Models/creature1/one.blend")277 (def worm "Models/creature1/try-again.blend")279 (defn x-ray [#^ColorRGBA color]280 (doto (Material. (asset-manager)281 "Common/MatDefs/Misc/Unshaded.j3md")282 (.setColor "Color" color)283 (-> (.getAdditionalRenderState)284 (.setDepthTest false))))286 (defn test-creature [thing]287 (let [x-axis288 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)289 y-axis290 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)291 z-axis292 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]293 (world294 (nodify [(blender-creature thing)295 (box 10 2 10 :position (Vector3f. 0 -9 0)296 :color ColorRGBA/Gray :mass 0)297 x-axis y-axis z-axis298 ])299 standard-debug-controls300 (comp light-up-everything enable-debug301 (fn [world]302 (.setTimer world (NanoTimer.))303 (set-gravity world (Vector3f. 0 0 0))304 (speed-up world)305 world306 ))307 no-op)))309 (defn world-setup [joint]310 (let [312 joint-position (Vector3f. 0 4 0)313 joint-rotation314 (.toRotationMatrix315 (.mult316 (doto (Quaternion.)317 (.fromAngleAxis318 (* 1 (/ Math/PI 4))319 (Vector3f. -1 0 0)))320 (doto (Quaternion.)321 (.fromAngleAxis322 (/ Math/PI 2)323 (Vector3f. 0 0 1)))))325 origin (doto326 (sphere 0.1 :physical? false :color ColorRGBA/Cyan327 :position (Vector3f. 0 0 0)))328 top (doto329 (sphere 0.1 :physical? false :color ColorRGBA/Yellow330 :position (.mult joint-rotation (Vector3f. 8 0 0)))332 (.addControl333 (RigidBodyControl.334 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))335 bottom (doto336 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray337 :position (Vector3f. 0 0 0))338 (.addControl339 (RigidBodyControl.340 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))341 table (box 10 2 10 :position (Vector3f. 0 -20 0)342 :color ColorRGBA/Gray :mass 0)343 a (.getControl top RigidBodyControl)344 b (.getControl bottom RigidBodyControl)]346 (cond347 (= joint :cone)349 (doto (ConeJoint.350 a b351 (get-subjective-position joint-position top)352 (get-subjective-position joint-position bottom)353 joint-rotation354 joint-rotation355 )358 (.setLimit (* (/ 10) Math/PI)359 (* (/ 4) Math/PI)360 0)))361 [origin top bottom table]))365 (defn test-joint [joint]366 (let [[origin top bottom floor] (world-setup joint)367 control (.getControl top RigidBodyControl)368 move-up? (atom false)369 move-down? (atom false)370 move-left? (atom false)371 move-right? (atom false)372 roll-left? (atom false)373 roll-right? (atom false)374 timer (atom 0)]376 (world377 (nodify [top bottom floor origin])378 (merge standard-debug-controls379 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))380 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))381 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))382 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))383 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))384 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})386 (fn [world]387 (light-up-everything world)388 (enable-debug world)389 (set-gravity world (Vector3f. 0 0 0))390 )392 (fn [world _]393 (if (zero? (rem (swap! timer inc) 100))394 (do395 ;; (println-repl @timer)396 (.attachChild (.getRootNode world)397 (sphere 0.05 :color ColorRGBA/Yellow398 :position (.getWorldTranslation top)399 :physical? false))400 (.attachChild (.getRootNode world)401 (sphere 0.05 :color ColorRGBA/LightGray402 :position (.getWorldTranslation bottom)403 :physical? false))))405 (if @move-up?406 (.applyTorque control407 (.mult (.getPhysicsRotation control)408 (Vector3f. 0 0 10))))409 (if @move-down?410 (.applyTorque control411 (.mult (.getPhysicsRotation control)412 (Vector3f. 0 0 -10))))413 (if @move-left?414 (.applyTorque control415 (.mult (.getPhysicsRotation control)416 (Vector3f. 0 10 0))))417 (if @move-right?418 (.applyTorque control419 (.mult (.getPhysicsRotation control)420 (Vector3f. 0 -10 0))))421 (if @roll-left?422 (.applyTorque control423 (.mult (.getPhysicsRotation control)424 (Vector3f. -1 0 0))))425 (if @roll-right?426 (.applyTorque control427 (.mult (.getPhysicsRotation control)428 (Vector3f. 1 0 0))))))))442 ;; please validate these.444 (defn get-subjective-position445 "Convert the world coordinates into coordinates relative to446 object (i.e. local coordinates), taking into account the rotation447 of object."448 [#^Vector3f world-coordinates object]449 ;; I don't know if it's important to take into account the rotation450 ;; of the object. If it isn't, then remove the multiplication-by-inverse.451 (.mult (.inverse (.getWorldRotation object))452 (.subtract world-coordinates (.getWorldTranslation object))))455 (defn get-subjective-rotation456 "cf get-subjective-position. Converts a rotation specified relative457 to the world's axes into a rotation specified in terms of the object's458 coordinate system."459 [#^Quaternion world-rotation object]460 (.mult (.inverse (.getWorldRotation object)) world-rotation))465 (defn joint-create "Connect objects 1 and 2 using a joint constraint. If466 only position is specified, creates a point-to-point joint at the467 given location468 in world coordinates. etc. etc. for other joints.469 To ensure consistency, I may alter this function470 so that it moves obj-1 to be at the apex of the cone.472 NOTE:473 In the usual construction method, you create a joint and, if your474 contraints are consistent, all the objects snap into position and475 orientation around it, otherwise the systen explodes.477 This construction method assumes that you have in mind a position and478 rotation for the joint, and that you have already put your objects479 at the required distances from that joint so that no snapping needs480 to occur. The radial distances ('pivot lengths') are therefore just set to be481 the pre-existing distances between the objects and the joint."482 [#^Node obj-1483 #^Node obj-2484 #^Vector3f joint-position485 #^Quaternion joint-rotation486 span-1487 span-2488 twist489 ]491 (let492 [body-1 (.getControl obj-1 RigidBodyControl)493 body-2 (.getControl obj-2 RigidBodyControl)494 ]495 (doto (ConeJoint.496 body-1497 body-2498 (get-subjective-position joint-position body-1)499 (get-subjective-position joint-position body-2)500 ;; ALIGN X-AXIS OF OBJECT-1 WITH THE CENTRAL AXIS OF THE CONE TO501 ;;LOWER THE RISK OF INCONSISTENCY502 ;;(Matrix3f/IDENTITY)503 (.toRotationMatrix (get-subjective-rotation joint-rotation body-1))504 (.toRotationMatrix (get-subjective-rotation joint-rotation body-2))505 )506 (.setLimit507 span-1508 span-2509 twist))))516 #+end_src519 * COMMENT purgatory520 #+begin_src clojure521 (defn bullet-trans []522 (let [obj-a (sphere 0.5 :color ColorRGBA/Red523 :position (Vector3f. -10 5 0))524 obj-b (sphere 0.5 :color ColorRGBA/Blue525 :position (Vector3f. -10 -5 0)526 :mass 0)527 control-a (.getControl obj-a RigidBodyControl)528 control-b (.getControl obj-b RigidBodyControl)529 swivel530 (.toRotationMatrix531 (doto (Quaternion.)532 (.fromAngleAxis (/ Math/PI 2)533 Vector3f/UNIT_X)))]534 (doto535 (ConeJoint.536 control-a control-b537 (Vector3f. 0 5 0)538 (Vector3f. 0 -5 0)539 swivel swivel)540 (.setLimit (* 0.6 (/ Math/PI 4))541 (/ Math/PI 4)542 (* Math/PI 0.8)))543 (world (nodify544 [obj-a obj-b])545 standard-debug-controls546 enable-debug547 no-op)))550 (defn bullet-trans* []551 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red552 :position (Vector3f. 5 0 0)553 :mass 90)554 obj-b (sphere 0.5 :color ColorRGBA/Blue555 :position (Vector3f. -5 0 0)556 :mass 0)557 control-a (.getControl obj-a RigidBodyControl)558 control-b (.getControl obj-b RigidBodyControl)559 move-up? (atom nil)560 move-down? (atom nil)561 move-left? (atom nil)562 move-right? (atom nil)563 roll-left? (atom nil)564 roll-right? (atom nil)565 force 100566 swivel567 (.toRotationMatrix568 (doto (Quaternion.)569 (.fromAngleAxis (/ Math/PI 2)570 Vector3f/UNIT_X)))571 x-move572 (doto (Matrix3f.)573 (.fromStartEndVectors Vector3f/UNIT_X574 (.normalize (Vector3f. 1 1 0))))576 timer (atom 0)]577 (doto578 (ConeJoint.579 control-a control-b580 (Vector3f. -8 0 0)581 (Vector3f. 2 0 0)582 ;;swivel swivel583 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY584 x-move Matrix3f/IDENTITY585 )586 (.setCollisionBetweenLinkedBodys false)587 (.setLimit (* 1 (/ Math/PI 4)) ;; twist588 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane589 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane590 (world (nodify591 [obj-a obj-b])592 (merge standard-debug-controls593 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))594 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))595 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))596 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))597 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))598 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})600 (fn [world]601 (enable-debug world)602 (set-gravity world Vector3f/ZERO)603 )605 (fn [world _]607 (if @move-up?608 (.applyForce control-a609 (Vector3f. force 0 0)610 (Vector3f. 0 0 0)))611 (if @move-down?612 (.applyForce control-a613 (Vector3f. (- force) 0 0)614 (Vector3f. 0 0 0)))615 (if @move-left?616 (.applyForce control-a617 (Vector3f. 0 force 0)618 (Vector3f. 0 0 0)))619 (if @move-right?620 (.applyForce control-a621 (Vector3f. 0 (- force) 0)622 (Vector3f. 0 0 0)))624 (if @roll-left?625 (.applyForce control-a626 (Vector3f. 0 0 force)627 (Vector3f. 0 0 0)))628 (if @roll-right?629 (.applyForce control-a630 (Vector3f. 0 0 (- force))631 (Vector3f. 0 0 0)))633 (if (zero? (rem (swap! timer inc) 100))634 (.attachChild635 (.getRootNode world)636 (sphere 0.05 :color ColorRGBA/Yellow637 :physical? false :position638 (.getWorldTranslation obj-a)))))639 )640 ))644 #+end_src647 * COMMENT generate source648 #+begin_src clojure :tangle ../src/cortex/silly.clj649 <<body-1>>650 #+end_src