Mercurial > cortex
view org/test-creature.org @ 85:00ab1f10266f
creatig cone joints for hand
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 07 Jan 2012 01:32:15 -0700 |
parents | 4f5e2c629e45 |
children | af1bb43661f9 |
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 (let [sim (world (Node.) {} no-op no-op)]57 (.enqueue58 sim59 (fn []60 (.stop sim)))61 (.start sim)))63 (defn load-blender-model64 "Load a .blend file using an asset folder relative path."65 [^String model]66 (.loadModel67 (doto (asset-manager)68 (.registerLoader BlenderModelLoader (into-array String ["blend"])))69 model))71 (defn meta-data [blender-node key]72 (if-let [data (.getUserData blender-node "properties")]73 (.findValue data key)74 nil))76 (defn blender-to-jme77 "Convert from Blender coordinates to JME coordinates"78 [#^Vector3f in]79 (Vector3f. (.getX in)80 (.getZ in)81 (- (.getY in))))83 (defn jme-to-blender84 "Convert from JME coordinates to Blender coordinates"85 [#^Vector3f in]86 (Vector3f. (.getX in)87 (- (.getZ in))88 (.getY in)))90 (defn joint-targets91 "Return the two closest two objects to the joint object, ordered92 from bottom to top according to the joint's rotation."93 [#^Node parts #^Node joint]94 ;;(println (meta-data joint "joint"))95 (.getWorldRotation joint)96 (loop [radius (float 0.01)]97 (let [results (CollisionResults.)]98 (.collideWith99 parts100 (BoundingBox. (.getWorldTranslation joint)101 radius radius radius)102 results)103 (let [targets104 (distinct105 (map #(.getGeometry %) results))]106 (if (>= (count targets) 2)107 (sort-by108 #(let [v109 (jme-to-blender110 (.mult111 (.inverse (.getWorldRotation joint))112 (.subtract (.getWorldTranslation %)113 (.getWorldTranslation joint))))]114 (println-repl (.getName %) ":" v)115 (.dot (Vector3f. 1 1 1)116 v))117 (take 2 targets))118 (recur (float (* radius 2))))))))120 (defn connect121 "here are some examples:122 {:type :point}123 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}124 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)126 {:type :cone :limit-xz 0]127 :limit-xy 0]128 :twist 0]} (use XZY rotation mode in blender!)"129 [#^Node obj-a #^Node obj-b #^Node joint]130 (let [center-a (.getWorldTranslation obj-a)131 center-b (.getWorldTranslation obj-b)132 joint-center (.getWorldTranslation joint)133 pivot-a (.subtract joint-center center-a)134 pivot-b (.subtract joint-center center-b)135 control-a (.getControl obj-a RigidBodyControl)136 control-b (.getControl obj-b RigidBodyControl)]137 ;; A side-effect of creating a joint registers138 ;; it with both physics objects which in turn139 ;; will register the joint with the physics system140 ;; when the simulation is started.141 (if-let [constraints142 (map-vals143 eval144 (read-string145 (meta-data joint "joint")))]147 (let [joint-type (:type constraints)]148 (println-repl "creating joint between"149 (.getName obj-a) "and" (.getName obj-b))150 (cond (= :point joint-type)151 (do152 (println-repl "creating POINT joint")153 (Point2PointJoint.154 control-a155 control-b156 pivot-a157 pivot-b))158 (= :hinge joint-type)159 (do160 (println-repl "creating HINGE joint")161 (let [axis (if-let162 [axis (:axis constraints)]163 axis164 Vector3f/UNIT_X)165 [limit-1 limit-2] (:limit constraints)166 hinge-axis167 (.mult168 (.getWorldRotation joint)169 (blender-to-jme axis))]170 (doto171 (HingeJoint.172 control-a173 control-b174 pivot-a175 pivot-b176 hinge-axis177 hinge-axis)178 (.setLimit limit-1 limit-2))))179 (= :cone joint-type)180 (do181 (let [limit-xz (:limit-xz constraints)182 limit-xy (:limit-xy constraints)183 twist (:twist constraints)184 rotation (.toRotationMatrix (.getWorldRotation joint))]186 (println-repl "creating CONE joint")187 (println-repl rotation)188 (println-repl189 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))190 (println-repl191 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))192 (println-repl193 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))194 (doto195 (ConeJoint.196 control-a197 control-b198 pivot-a199 pivot-b200 rotation201 rotation202 )203 (.setLimit (float limit-xz)204 (float limit-xy)205 (float twist)))))206 true207 (println-repl208 "joint-type" joint-type "not recognized")))210 (println-repl "could not find joint meta-data!"))))213 (defn assemble-creature [#^Node pieces joints]214 (dorun215 (map216 (fn [geom]217 (let [physics-control218 (RigidBodyControl.219 (HullCollisionShape.220 (.getMesh geom))221 (if-let [mass (meta-data geom "mass")]222 (do223 (println-repl224 "setting" (.getName geom) "mass to" (float mass))225 (float mass))226 (float 1)))]228 (.addControl geom physics-control)))229 (filter #(isa? (class %) Geometry )230 (node-seq pieces))))232 (dorun233 (map234 (fn [joint]235 (let [[obj-a obj-b]236 (joint-targets pieces joint)]237 (connect obj-a obj-b joint)))238 joints))239 pieces)241 (defn blender-creature [blender-path]242 (let [model (load-blender-model blender-path)243 joints244 (if-let [joint-node (.getChild model "joints")]245 (seq (.getChildren joint-node))246 (do (println-repl "could not find joints node")247 []))]248 (assemble-creature model joints)))250 (def hand "Models/creature1/one.blend")252 (def worm "Models/creature1/try-again.blend")254 (defn x-ray [#^ColorRGBA color]255 (doto (Material. (asset-manager)256 "Common/MatDefs/Misc/Unshaded.j3md")257 (.setColor "Color" color)258 (-> (.getAdditionalRenderState)259 (.setDepthTest false))))261 (defn test-creature [thing]262 (let [x-axis263 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)264 y-axis265 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)266 z-axis267 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]268 (world269 (nodify [(blender-creature thing)270 (box 10 2 10 :position (Vector3f. 0 -9 0)271 :color ColorRGBA/Gray :mass 0)272 x-axis y-axis z-axis273 ])274 standard-debug-controls275 (comp light-up-everything enable-debug276 (fn [world]277 (.setTimer world (NanoTimer.))278 (set-gravity world (Vector3f. 0 0 0))279 (speed-up world)280 world281 ))282 no-op)))284 (defn world-setup [joint]285 (let [287 joint-position (Vector3f. 0 0 0)288 joint-rotation289 (.toRotationMatrix290 (.mult291 (doto (Quaternion.)292 (.fromAngleAxis293 (* 1 (/ Math/PI 4))294 (Vector3f. -1 0 0)))295 (doto (Quaternion.)296 (.fromAngleAxis297 (* 1 (/ Math/PI 2))298 (Vector3f. 0 0 1)))))299 top-position (.mult joint-rotation (Vector3f. 8 0 0))301 origin (doto302 (sphere 0.1 :physical? false :color ColorRGBA/Cyan303 :position top-position))304 top (doto305 (sphere 0.1 :physical? false :color ColorRGBA/Yellow306 :position top-position)308 (.addControl309 (RigidBodyControl.310 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))311 bottom (doto312 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray313 :position (Vector3f. 0 0 0))314 (.addControl315 (RigidBodyControl.316 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))317 table (box 10 2 10 :position (Vector3f. 0 -20 0)318 :color ColorRGBA/Gray :mass 0)319 a (.getControl top RigidBodyControl)320 b (.getControl bottom RigidBodyControl)]322 (cond323 (= joint :cone)325 (doto (ConeJoint.326 a b327 (get-subjective-position joint-position top)328 (get-subjective-position joint-position bottom)329 joint-rotation330 joint-rotation331 )334 (.setLimit (* (/ 10) Math/PI)335 (* (/ 4) Math/PI)336 0)))337 [origin top bottom table]))341 (defn test-joint [joint]342 (let [[origin top bottom floor] (world-setup joint)343 control (.getControl top RigidBodyControl)344 move-up? (atom false)345 move-down? (atom false)346 move-left? (atom false)347 move-right? (atom false)348 roll-left? (atom false)349 roll-right? (atom false)350 timer (atom 0)]352 (world353 (nodify [top bottom floor origin])354 (merge standard-debug-controls355 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))356 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))357 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))358 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))359 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))360 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})362 (fn [world]363 (light-up-everything world)364 (enable-debug world)365 (set-gravity world (Vector3f. 0 0 0))366 )368 (fn [world _]369 (if (zero? (rem (swap! timer inc) 100))370 (do371 ;; (println-repl @timer)372 (.attachChild (.getRootNode world)373 (sphere 0.05 :color ColorRGBA/Yellow374 :position (.getWorldTranslation top)375 :physical? false))376 (.attachChild (.getRootNode world)377 (sphere 0.05 :color ColorRGBA/LightGray378 :position (.getWorldTranslation bottom)379 :physical? false))))381 (if @move-up?382 (.applyTorque control383 (.mult (.getPhysicsRotation control)384 (Vector3f. 0 0 10))))385 (if @move-down?386 (.applyTorque control387 (.mult (.getPhysicsRotation control)388 (Vector3f. 0 0 -10))))389 (if @move-left?390 (.applyTorque control391 (.mult (.getPhysicsRotation control)392 (Vector3f. 0 10 0))))393 (if @move-right?394 (.applyTorque control395 (.mult (.getPhysicsRotation control)396 (Vector3f. 0 -10 0))))397 (if @roll-left?398 (.applyTorque control399 (.mult (.getPhysicsRotation control)400 (Vector3f. -1 0 0))))401 (if @roll-right?402 (.applyTorque control403 (.mult (.getPhysicsRotation control)404 (Vector3f. 1 0 0))))))))418 ;; please validate these.420 (defn get-subjective-position421 "Convert the world coordinates into coordinates relative to422 object (i.e. local coordinates), taking into account the rotation423 of object."424 [#^Vector3f world-coordinates object]425 ;; I don't know if it's important to take into account the rotation426 ;; of the object. If it isn't, then remove the multiplication-by-inverse.427 (.mult (.inverse (.getWorldRotation object))428 (.subtract world-coordinates (.getWorldTranslation object))))431 (defn get-subjective-rotation432 "cf get-subjective-position. Converts a rotation specified relative433 to the world's axes into a rotation specified in terms of the object's434 coordinate system."435 [#^Quaternion world-rotation object]436 (.mult (.inverse (.getWorldRotation object)) world-rotation))441 (defn joint-create "Connect objects 1 and 2 using a joint constraint. If442 only position is specified, creates a point-to-point joint at the443 given location444 in world coordinates. etc. etc. for other joints.445 To ensure consistency, I may alter this function446 so that it moves obj-1 to be at the apex of the cone.448 NOTE:449 In the usual construction method, you create a joint and, if your450 contraints are consistent, all the objects snap into position and451 orientation around it, otherwise the systen explodes.453 This construction method assumes that you have in mind a position and454 rotation for the joint, and that you have already put your objects455 at the required distances from that joint so that no snapping needs456 to occur. The radial distances ('pivot lengths') are therefore just set to be457 the pre-existing distances between the objects and the joint."458 [#^Node obj-1459 #^Node obj-2460 #^Vector3f joint-position461 #^Quaternion joint-rotation462 span-1463 span-2464 twist465 ]467 (let468 [body-1 (.getControl obj-1 RigidBodyControl)469 body-2 (.getControl obj-2 RigidBodyControl)470 ]471 (doto (ConeJoint.472 body-1473 body-2474 (get-subjective-position joint-position body-1)475 (get-subjective-position joint-position body-2)476 ;; ALIGN X-AXIS OF OBJECT-1 WITH THE CENTRAL AXIS OF THE CONE TO477 ;;LOWER THE RISK OF INCONSISTENCY478 ;;(Matrix3f/IDENTITY)479 (.toRotationMatrix (get-subjective-rotation joint-rotation body-1))480 (.toRotationMatrix (get-subjective-rotation joint-rotation body-2))481 )482 (.setLimit483 span-1484 span-2485 twist))))492 #+end_src495 * COMMENT purgatory496 #+begin_src clojure497 (defn bullet-trans []498 (let [obj-a (sphere 0.5 :color ColorRGBA/Red499 :position (Vector3f. -10 5 0))500 obj-b (sphere 0.5 :color ColorRGBA/Blue501 :position (Vector3f. -10 -5 0)502 :mass 0)503 control-a (.getControl obj-a RigidBodyControl)504 control-b (.getControl obj-b RigidBodyControl)505 swivel506 (.toRotationMatrix507 (doto (Quaternion.)508 (.fromAngleAxis (/ Math/PI 2)509 Vector3f/UNIT_X)))]510 (doto511 (ConeJoint.512 control-a control-b513 (Vector3f. 0 5 0)514 (Vector3f. 0 -5 0)515 swivel swivel)516 (.setLimit (* 0.6 (/ Math/PI 4))517 (/ Math/PI 4)518 (* Math/PI 0.8)))519 (world (nodify520 [obj-a obj-b])521 standard-debug-controls522 enable-debug523 no-op)))526 (defn bullet-trans* []527 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red528 :position (Vector3f. 5 0 0)529 :mass 90)530 obj-b (sphere 0.5 :color ColorRGBA/Blue531 :position (Vector3f. -5 0 0)532 :mass 0)533 control-a (.getControl obj-a RigidBodyControl)534 control-b (.getControl obj-b RigidBodyControl)535 move-up? (atom nil)536 move-down? (atom nil)537 move-left? (atom nil)538 move-right? (atom nil)539 roll-left? (atom nil)540 roll-right? (atom nil)541 force 100542 swivel543 (.toRotationMatrix544 (doto (Quaternion.)545 (.fromAngleAxis (/ Math/PI 2)546 Vector3f/UNIT_X)))547 x-move548 (doto (Matrix3f.)549 (.fromStartEndVectors Vector3f/UNIT_X550 (.normalize (Vector3f. 1 1 0))))552 timer (atom 0)]553 (doto554 (ConeJoint.555 control-a control-b556 (Vector3f. -8 0 0)557 (Vector3f. 2 0 0)558 ;;swivel swivel559 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY560 x-move Matrix3f/IDENTITY561 )562 (.setCollisionBetweenLinkedBodys false)563 (.setLimit (* 1 (/ Math/PI 4)) ;; twist564 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane565 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane566 (world (nodify567 [obj-a obj-b])568 (merge standard-debug-controls569 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))570 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))571 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))572 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))573 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))574 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})576 (fn [world]577 (enable-debug world)578 (set-gravity world Vector3f/ZERO)579 )581 (fn [world _]583 (if @move-up?584 (.applyForce control-a585 (Vector3f. force 0 0)586 (Vector3f. 0 0 0)))587 (if @move-down?588 (.applyForce control-a589 (Vector3f. (- force) 0 0)590 (Vector3f. 0 0 0)))591 (if @move-left?592 (.applyForce control-a593 (Vector3f. 0 force 0)594 (Vector3f. 0 0 0)))595 (if @move-right?596 (.applyForce control-a597 (Vector3f. 0 (- force) 0)598 (Vector3f. 0 0 0)))600 (if @roll-left?601 (.applyForce control-a602 (Vector3f. 0 0 force)603 (Vector3f. 0 0 0)))604 (if @roll-right?605 (.applyForce control-a606 (Vector3f. 0 0 (- force))607 (Vector3f. 0 0 0)))609 (if (zero? (rem (swap! timer inc) 100))610 (.attachChild611 (.getRootNode world)612 (sphere 0.05 :color ColorRGBA/Yellow613 :physical? false :position614 (.getWorldTranslation obj-a)))))615 )616 ))620 #+end_src623 * COMMENT generate source624 #+begin_src clojure :tangle ../src/cortex/silly.clj625 <<body-1>>626 #+end_src