Mercurial > cortex
view org/test-creature.org @ 158:811127d79d24
refactored muscles
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 03 Feb 2012 06:33:37 -0700 |
parents | 84c67be00abe |
children | 75b6c2ebbf8e |
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.org12 * Intro13 So far, I've made the following senses --14 - Vision15 - Hearing16 - Touch17 - Proprioception19 And one effector:20 - Movement22 However, the code so far has only enabled these senses, but has not23 actually implemented them. For example, there is still a lot of work24 to be done for vision. I need to be able to create an /eyeball/ in25 simulation that can be moved around and see the world from different26 angles. I also need to determine weather to use log-polar or cartesian27 for the visual input, and I need to determine how/wether to28 disceritise the visual input.30 I also want to be able to visualize both the sensors and the31 effectors in pretty pictures. This semi-retarted creature will be my32 first attempt at bringing everything together.34 * The creature's body36 Still going to do an eve-like body in blender, but due to problems37 importing the joints, etc into jMonkeyEngine3, I'm going to do all38 the connecting here in clojure code, using the names of the individual39 components and trial and error. Later, I'll maybe make some sort of40 creature-building modifications to blender that support whatever41 discritized senses I'm going to make.43 #+name: body-144 #+begin_src clojure45 (ns cortex.silly46 "let's play!"47 {:author "Robert McIntyre"})49 ;; TODO remove this!50 (require 'cortex.import)51 (cortex.import/mega-import-jme3)52 (use '(cortex world util body hearing touch vision sense53 proprioception movement))55 (rlm.rlm-commands/help)56 (import java.awt.image.BufferedImage)57 (import javax.swing.JPanel)58 (import javax.swing.SwingUtilities)59 (import java.awt.Dimension)60 (import javax.swing.JFrame)61 (import java.awt.Dimension)62 (import com.aurellem.capture.RatchetTimer)63 (declare joint-create)64 (use 'clojure.contrib.def)66 (defn load-blender-model67 "Load a .blend file using an asset folder relative path."68 [^String model]69 (.loadModel70 (doto (asset-manager)71 (.registerLoader BlenderModelLoader (into-array String ["blend"])))72 model))74 (defn blender-to-jme75 "Convert from Blender coordinates to JME coordinates"76 [#^Vector3f in]77 (Vector3f. (.getX in)78 (.getZ in)79 (- (.getY in))))82 (defmulti joint-dispatch83 "Translate blender pseudo-joints into real JME joints."84 (fn [constraints & _]85 (:type constraints)))87 (defmethod joint-dispatch :point88 [constraints control-a control-b pivot-a pivot-b rotation]89 (println-repl "creating POINT2POINT joint")90 ;; bullet's point2point joints are BROKEN, so we must use the91 ;; generic 6DOF joint instead of an actual Point2Point joint!93 ;; should be able to do this:94 (comment95 (Point2PointJoint.96 control-a97 control-b98 pivot-a99 pivot-b))101 ;; but instead we must do this:102 (println-repl "substuting 6DOF joint for POINT2POINT joint!")103 (doto104 (SixDofJoint.105 control-a106 control-b107 pivot-a108 pivot-b109 false)110 (.setLinearLowerLimit Vector3f/ZERO)111 (.setLinearUpperLimit Vector3f/ZERO)112 ;;(.setAngularLowerLimit (Vector3f. 1 1 1))113 ;;(.setAngularUpperLimit (Vector3f. 0 0 0))115 ))118 (defmethod joint-dispatch :hinge119 [constraints control-a control-b pivot-a pivot-b rotation]120 (println-repl "creating HINGE joint")121 (let [axis122 (if-let123 [axis (:axis constraints)]124 axis125 Vector3f/UNIT_X)126 [limit-1 limit-2] (:limit constraints)127 hinge-axis128 (.mult129 rotation130 (blender-to-jme axis))]131 (doto132 (HingeJoint.133 control-a134 control-b135 pivot-a136 pivot-b137 hinge-axis138 hinge-axis)139 (.setLimit limit-1 limit-2))))141 (defmethod joint-dispatch :cone142 [constraints control-a control-b pivot-a pivot-b rotation]143 (let [limit-xz (:limit-xz constraints)144 limit-xy (:limit-xy constraints)145 twist (:twist constraints)]147 (println-repl "creating CONE joint")148 (println-repl rotation)149 (println-repl150 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))151 (println-repl152 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))153 (println-repl154 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))155 (doto156 (ConeJoint.157 control-a158 control-b159 pivot-a160 pivot-b161 rotation162 rotation)163 (.setLimit (float limit-xz)164 (float limit-xy)165 (float twist)))))167 (defn connect168 "here are some examples:169 {:type :point}170 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}171 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)173 {:type :cone :limit-xz 0]174 :limit-xy 0]175 :twist 0]} (use XZY rotation mode in blender!)"176 [#^Node obj-a #^Node obj-b #^Node joint]177 (let [control-a (.getControl obj-a RigidBodyControl)178 control-b (.getControl obj-b RigidBodyControl)179 joint-center (.getWorldTranslation joint)180 joint-rotation (.toRotationMatrix (.getWorldRotation joint))181 pivot-a (world-to-local obj-a joint-center)182 pivot-b (world-to-local obj-b joint-center)]184 (if-let [constraints185 (map-vals186 eval187 (read-string188 (meta-data joint "joint")))]189 ;; A side-effect of creating a joint registers190 ;; it with both physics objects which in turn191 ;; will register the joint with the physics system192 ;; when the simulation is started.193 (do194 (println-repl "creating joint between"195 (.getName obj-a) "and" (.getName obj-b))196 (joint-dispatch constraints197 control-a control-b198 pivot-a pivot-b199 joint-rotation))200 (println-repl "could not find joint meta-data!"))))205 (defn assemble-creature [#^Node pieces joints]206 (dorun207 (map208 (fn [geom]209 (let [physics-control210 (RigidBodyControl.211 (HullCollisionShape.212 (.getMesh geom))213 (if-let [mass (meta-data geom "mass")]214 (do215 (println-repl216 "setting" (.getName geom) "mass to" (float mass))217 (float mass))218 (float 1)))]220 (.addControl geom physics-control)))221 (filter #(isa? (class %) Geometry )222 (node-seq pieces))))223 (dorun224 (map225 (fn [joint]226 (let [[obj-a obj-b] (joint-targets pieces joint)]227 (connect obj-a obj-b joint)))228 joints))229 pieces)231 (declare blender-creature)233 (def hand "Models/creature1/one.blend")235 (def worm "Models/creature1/try-again.blend")237 (defn worm-model [] (load-blender-model worm))239 (defn x-ray [#^ColorRGBA color]240 (doto (Material. (asset-manager)241 "Common/MatDefs/Misc/Unshaded.j3md")242 (.setColor "Color" color)243 (-> (.getAdditionalRenderState)244 (.setDepthTest false))))246 (defn colorful []247 (.getChild (worm-model) "worm-21"))249 (import jme3tools.converters.ImageToAwt)251 (import ij.ImagePlus)255 (defn test-eye []256 (.getChild257 (.getChild (worm-model) "eyes")258 "eye"))262 ;; Ears work the same way as vision.264 ;; (hearing creature) will return [init-functions265 ;; sensor-functions]. The init functions each take the world and266 ;; register a SoundProcessor that does foureier transforms on the267 ;; incommong sound data, making it available to each sensor function.269 (defn creature-ears270 "Return the children of the creature's \"ears\" node."271 ;;dylan272 ;;"The ear nodes which are children of the \"ears\" node in the273 ;;creature."274 [#^Node creature]275 (if-let [ear-node (.getChild creature "ears")]276 (seq (.getChildren ear-node))277 (do (println-repl "could not find ears node") [])))280 ;;dylan (defn follow-sense, adjoin-sense, attach-stimuli,281 ;;anchor-qualia, augment-organ, with-organ284 (defn update-listener-velocity285 "Update the listener's velocity every update loop."286 [#^Spatial obj #^Listener lis]287 (let [old-position (atom (.getLocation lis))]288 (.addControl289 obj290 (proxy [AbstractControl] []291 (controlUpdate [tpf]292 (let [new-position (.getLocation lis)]293 (.setVelocity294 lis295 (.mult (.subtract new-position @old-position)296 (float (/ tpf))))297 (reset! old-position new-position)))298 (controlRender [_ _])))))300 (import com.aurellem.capture.audio.AudioSendRenderer)302 (defn attach-ear303 [#^Application world #^Node creature #^Spatial ear continuation]304 (let [target (closest-node creature ear)305 lis (Listener.)306 audio-renderer (.getAudioRenderer world)307 sp (sound-processor continuation)]308 (.setLocation lis (.getWorldTranslation ear))309 (.setRotation lis (.getWorldRotation ear))310 (bind-sense target lis)311 (update-listener-velocity target lis)312 (.addListener audio-renderer lis)313 (.registerSoundProcessor audio-renderer lis sp)))315 (defn enable-hearing316 [#^Node creature #^Spatial ear]317 (let [hearing-data (atom [])]318 [(fn [world]319 (attach-ear world creature ear320 (fn [data]321 (reset! hearing-data (vec data)))))322 [(fn []323 (let [data @hearing-data324 topology325 (vec (map #(vector % 0) (range 0 (count data))))326 scaled-data327 (vec328 (map329 #(rem (int (* 255 (/ (+ 1 %) 2))) 256)330 data))]331 [topology scaled-data]))332 ]]))334 (defn hearing335 [#^Node creature]336 (reduce337 (fn [[init-a senses-a]338 [init-b senses-b]]339 [(conj init-a init-b)340 (into senses-a senses-b)])341 [[][]]342 (for [ear (creature-ears creature)]343 (enable-hearing creature ear))))350 ;; lower level --- nodes351 ;; closest-node "parse/compile-x" -> makes organ, which is spatial, fn pair353 ;; higher level -- organs354 ;;356 ;; higher level --- sense/effector357 ;; these are the functions that provide world i/o, chinese-room style362 (defn blender-creature363 "Return a creature with all joints in place."364 [blender-path]365 (let [model (load-blender-model blender-path)366 joints (creature-joints model)]367 (assemble-creature model joints)))369 (defn gray-scale [num]370 (+ num371 (bit-shift-left num 8)372 (bit-shift-left num 16)))374 (defn debug-touch-window375 "creates function that offers a debug view of sensor data"376 []377 (let [vi (view-image)]378 (fn379 [[coords sensor-data]]380 (let [image (points->image coords)]381 (dorun382 (for [i (range (count coords))]383 (.setRGB image ((coords i) 0) ((coords i) 1)384 (gray-scale (sensor-data i)))))387 (vi image)))))389 (defn debug-vision-window390 "creates function that offers a debug view of sensor data"391 []392 (let [vi (view-image)]393 (fn394 [[coords sensor-data]]395 (let [image (points->image coords)]396 (dorun397 (for [i (range (count coords))]398 (.setRGB image ((coords i) 0) ((coords i) 1)399 (sensor-data i))))400 (vi image)))))402 (defn debug-hearing-window403 "view audio data"404 [height]405 (let [vi (view-image)]406 (fn [[coords sensor-data]]407 (let [image (BufferedImage. (count coords) height408 BufferedImage/TYPE_INT_RGB)]409 (dorun410 (for [x (range (count coords))]411 (dorun412 (for [y (range height)]413 (let [raw-sensor (sensor-data x)]414 (.setRGB image x y (gray-scale raw-sensor)))))))416 (vi image)))))420 ;;(defn test-touch [world creature]426 (defn test-creature [thing]427 (let [x-axis428 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)429 y-axis430 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)431 z-axis432 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)433 creature (blender-creature thing)434 touch-nerves (touch creature)435 touch-debug-windows (map (fn [_] (debug-touch-window)) touch-nerves)436 [init-vision-fns vision-data] (vision creature)437 vision-debug (map (fn [_] (debug-vision-window)) vision-data)438 me (sphere 0.5 :color ColorRGBA/Blue :physical? false)439 [init-hearing-fns hearing-senses] (hearing creature)440 hearing-windows (map (fn [_] (debug-hearing-window 50))441 hearing-senses)442 bell (AudioNode. (asset-manager)443 "Sounds/pure.wav" false)444 prop (proprioception creature)445 prop-debug (proprioception-debug-window)447 muscle-fns (enable-muscles creature)448 ;; dream450 ]453 (apply454 world455 (with-movement456 (.getChild creature "worm-21")457 ["key-r" "key-t"458 "key-f" "key-g"459 "key-v" "key-b"]460 [10 10 10 10 1 1]461 [(nodify [creature462 (box 10 2 10 :position (Vector3f. 0 -9 0)463 :color ColorRGBA/Gray :mass 0)464 x-axis y-axis z-axis465 me466 ])467 (merge standard-debug-controls468 {"key-return"469 (fn [_ value]470 (if value471 (do472 (println-repl "play-sound")473 (.play bell))))474 "key-h"475 (fn [_ value]476 (if value477 (do478 (println-repl "muscle activating!")479 ((first muscle-fns) 199))))481 })482 (fn [world]483 (light-up-everything world)484 (enable-debug world)485 (dorun (map #(% world) init-vision-fns))486 (dorun (map #(% world) init-hearing-fns))488 (add-eye world489 (attach-eye creature (test-eye))490 (comp (view-image) BufferedImage!))492 (add-eye world (.getCamera world) no-op)493 ;;(set-gravity world (Vector3f. 0 0 0))494 ;;(com.aurellem.capture.Capture/captureVideo495 ;; world (file-str "/home/r/proj/ai-videos/hand"))496 ;;(.setTimer world (RatchetTimer. 60))497 (speed-up world)498 (set-gravity world (Vector3f. 0 0 0))499 )500 (fn [world tpf]501 ;;(dorun502 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))504 (prop-debug (prop))506 (dorun507 (map #(%1 (%2 (.getRootNode world)))508 touch-debug-windows touch-nerves))510 (dorun511 (map #(%1 (%2))512 vision-debug vision-data))513 (dorun514 (map #(%1 (%2)) hearing-windows hearing-senses))517 ;;(println-repl (vision-data))518 (.setLocalTranslation me (.getLocation (.getCamera world)))521 )]522 ;;(let [timer (atom 0)]523 ;; (fn [_ _]524 ;; (swap! timer inc)525 ;; (if (= (rem @timer 60) 0)526 ;; (println-repl (float (/ @timer 60))))))527 ))))531 ;; the camera will stay in its initial position/rotation with relation532 ;; to the spatial.535 (defn follow-test536 "show a camera that stays in the same relative position to a blue cube."537 []538 (let [camera-pos (Vector3f. 0 30 0)539 rock (box 1 1 1 :color ColorRGBA/Blue540 :position (Vector3f. 0 10 0)541 :mass 30542 )543 rot (.getWorldRotation rock)545 table (box 3 1 10 :color ColorRGBA/Gray :mass 0546 :position (Vector3f. 0 -3 0))]548 (world549 (nodify [rock table])550 standard-debug-controls551 (fn [world]552 (let553 [cam (doto (.clone (.getCamera world))554 (.setLocation camera-pos)555 (.lookAt Vector3f/ZERO556 Vector3f/UNIT_X))]557 (bind-sense rock cam)559 (.setTimer world (RatchetTimer. 60))560 (add-eye world cam (comp (view-image) BufferedImage!))561 (add-eye world (.getCamera world) no-op))562 )563 (fn [_ _] (println-repl rot)))))567 #+end_src569 #+results: body-1570 : #'cortex.silly/follow-test573 * COMMENT purgatory574 #+begin_src clojure576 (defn bullet-trans* []577 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red578 :position (Vector3f. 5 0 0)579 :mass 90)580 obj-b (sphere 0.5 :color ColorRGBA/Blue581 :position (Vector3f. -5 0 0)582 :mass 0)583 control-a (.getControl obj-a RigidBodyControl)584 control-b (.getControl obj-b RigidBodyControl)585 move-up? (atom nil)586 move-down? (atom nil)587 move-left? (atom nil)588 move-right? (atom nil)589 roll-left? (atom nil)590 roll-right? (atom nil)591 force 100592 swivel593 (.toRotationMatrix594 (doto (Quaternion.)595 (.fromAngleAxis (/ Math/PI 2)596 Vector3f/UNIT_X)))597 x-move598 (doto (Matrix3f.)599 (.fromStartEndVectors Vector3f/UNIT_X600 (.normalize (Vector3f. 1 1 0))))602 timer (atom 0)]603 (doto604 (ConeJoint.605 control-a control-b606 (Vector3f. -8 0 0)607 (Vector3f. 2 0 0)608 ;;swivel swivel609 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY610 x-move Matrix3f/IDENTITY611 )612 (.setCollisionBetweenLinkedBodys false)613 (.setLimit (* 1 (/ Math/PI 4)) ;; twist614 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane615 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane616 (world (nodify617 [obj-a obj-b])618 (merge standard-debug-controls619 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))620 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))621 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))622 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))623 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))624 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})626 (fn [world]627 (enable-debug world)628 (set-gravity world Vector3f/ZERO)629 )631 (fn [world _]633 (if @move-up?634 (.applyForce control-a635 (Vector3f. force 0 0)636 (Vector3f. 0 0 0)))637 (if @move-down?638 (.applyForce control-a639 (Vector3f. (- force) 0 0)640 (Vector3f. 0 0 0)))641 (if @move-left?642 (.applyForce control-a643 (Vector3f. 0 force 0)644 (Vector3f. 0 0 0)))645 (if @move-right?646 (.applyForce control-a647 (Vector3f. 0 (- force) 0)648 (Vector3f. 0 0 0)))650 (if @roll-left?651 (.applyForce control-a652 (Vector3f. 0 0 force)653 (Vector3f. 0 0 0)))654 (if @roll-right?655 (.applyForce control-a656 (Vector3f. 0 0 (- force))657 (Vector3f. 0 0 0)))659 (if (zero? (rem (swap! timer inc) 100))660 (.attachChild661 (.getRootNode world)662 (sphere 0.05 :color ColorRGBA/Yellow663 :physical? false :position664 (.getWorldTranslation obj-a)))))665 )666 ))668 (defn test-joint [joint]669 (let [[origin top bottom floor] (world-setup joint)670 control (.getControl top RigidBodyControl)671 move-up? (atom false)672 move-down? (atom false)673 move-left? (atom false)674 move-right? (atom false)675 roll-left? (atom false)676 roll-right? (atom false)677 timer (atom 0)]679 (world680 (nodify [top bottom floor origin])681 (merge standard-debug-controls682 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))683 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))684 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))685 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))686 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))687 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})689 (fn [world]690 (light-up-everything world)691 (enable-debug world)692 (set-gravity world (Vector3f. 0 0 0))693 )695 (fn [world _]696 (if (zero? (rem (swap! timer inc) 100))697 (do698 ;; (println-repl @timer)699 (.attachChild (.getRootNode world)700 (sphere 0.05 :color ColorRGBA/Yellow701 :position (.getWorldTranslation top)702 :physical? false))703 (.attachChild (.getRootNode world)704 (sphere 0.05 :color ColorRGBA/LightGray705 :position (.getWorldTranslation bottom)706 :physical? false))))708 (if @move-up?709 (.applyTorque control710 (.mult (.getPhysicsRotation control)711 (Vector3f. 0 0 10))))712 (if @move-down?713 (.applyTorque control714 (.mult (.getPhysicsRotation control)715 (Vector3f. 0 0 -10))))716 (if @move-left?717 (.applyTorque control718 (.mult (.getPhysicsRotation control)719 (Vector3f. 0 10 0))))720 (if @move-right?721 (.applyTorque control722 (.mult (.getPhysicsRotation control)723 (Vector3f. 0 -10 0))))724 (if @roll-left?725 (.applyTorque control726 (.mult (.getPhysicsRotation control)727 (Vector3f. -1 0 0))))728 (if @roll-right?729 (.applyTorque control730 (.mult (.getPhysicsRotation control)731 (Vector3f. 1 0 0))))))))732 #+end_src735 * COMMENT generate source736 #+begin_src clojure :tangle ../src/cortex/silly.clj737 <<body-1>>738 #+end_src