view org/test-creature.org @ 159:75b6c2ebbf8e

refactored audio code
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 06:41:16 -0700
parents 811127d79d24
children 33278bf028e7
line wrap: on
line source
1 #+title: First attempt at a creature!
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description:
5 #+keywords: simulation, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
12 * Intro
13 So far, I've made the following senses --
14 - Vision
15 - Hearing
16 - Touch
17 - Proprioception
19 And one effector:
20 - Movement
22 However, the code so far has only enabled these senses, but has not
23 actually implemented them. For example, there is still a lot of work
24 to be done for vision. I need to be able to create an /eyeball/ in
25 simulation that can be moved around and see the world from different
26 angles. I also need to determine weather to use log-polar or cartesian
27 for the visual input, and I need to determine how/wether to
28 disceritise the visual input.
30 I also want to be able to visualize both the sensors and the
31 effectors in pretty pictures. This semi-retarted creature will be my
32 first attempt at bringing everything together.
34 * The creature's body
36 Still going to do an eve-like body in blender, but due to problems
37 importing the joints, etc into jMonkeyEngine3, I'm going to do all
38 the connecting here in clojure code, using the names of the individual
39 components and trial and error. Later, I'll maybe make some sort of
40 creature-building modifications to blender that support whatever
41 discritized senses I'm going to make.
43 #+name: body-1
44 #+begin_src clojure
45 (ns cortex.silly
46 "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 sense
53 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-model
67 "Load a .blend file using an asset folder relative path."
68 [^String model]
69 (.loadModel
70 (doto (asset-manager)
71 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
72 model))
74 (defn blender-to-jme
75 "Convert from Blender coordinates to JME coordinates"
76 [#^Vector3f in]
77 (Vector3f. (.getX in)
78 (.getZ in)
79 (- (.getY in))))
82 (defmulti joint-dispatch
83 "Translate blender pseudo-joints into real JME joints."
84 (fn [constraints & _]
85 (:type constraints)))
87 (defmethod joint-dispatch :point
88 [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 the
91 ;; generic 6DOF joint instead of an actual Point2Point joint!
93 ;; should be able to do this:
94 (comment
95 (Point2PointJoint.
96 control-a
97 control-b
98 pivot-a
99 pivot-b))
101 ;; but instead we must do this:
102 (println-repl "substuting 6DOF joint for POINT2POINT joint!")
103 (doto
104 (SixDofJoint.
105 control-a
106 control-b
107 pivot-a
108 pivot-b
109 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 :hinge
119 [constraints control-a control-b pivot-a pivot-b rotation]
120 (println-repl "creating HINGE joint")
121 (let [axis
122 (if-let
123 [axis (:axis constraints)]
124 axis
125 Vector3f/UNIT_X)
126 [limit-1 limit-2] (:limit constraints)
127 hinge-axis
128 (.mult
129 rotation
130 (blender-to-jme axis))]
131 (doto
132 (HingeJoint.
133 control-a
134 control-b
135 pivot-a
136 pivot-b
137 hinge-axis
138 hinge-axis)
139 (.setLimit limit-1 limit-2))))
141 (defmethod joint-dispatch :cone
142 [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-repl
150 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
151 (println-repl
152 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
153 (println-repl
154 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
155 (doto
156 (ConeJoint.
157 control-a
158 control-b
159 pivot-a
160 pivot-b
161 rotation
162 rotation)
163 (.setLimit (float limit-xz)
164 (float limit-xy)
165 (float twist)))))
167 (defn connect
168 "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 [constraints
185 (map-vals
186 eval
187 (read-string
188 (meta-data joint "joint")))]
189 ;; A side-effect of creating a joint registers
190 ;; it with both physics objects which in turn
191 ;; will register the joint with the physics system
192 ;; when the simulation is started.
193 (do
194 (println-repl "creating joint between"
195 (.getName obj-a) "and" (.getName obj-b))
196 (joint-dispatch constraints
197 control-a control-b
198 pivot-a pivot-b
199 joint-rotation))
200 (println-repl "could not find joint meta-data!"))))
205 (defn assemble-creature [#^Node pieces joints]
206 (dorun
207 (map
208 (fn [geom]
209 (let [physics-control
210 (RigidBodyControl.
211 (HullCollisionShape.
212 (.getMesh geom))
213 (if-let [mass (meta-data geom "mass")]
214 (do
215 (println-repl
216 "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 (dorun
224 (map
225 (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 (.getChild
257 (.getChild (worm-model) "eyes")
258 "eye"))
262 ;; lower level --- nodes
263 ;; closest-node "parse/compile-x" -> makes organ, which is spatial, fn pair
265 ;; higher level -- organs
266 ;;
268 ;; higher level --- sense/effector
269 ;; these are the functions that provide world i/o, chinese-room style
274 (defn blender-creature
275 "Return a creature with all joints in place."
276 [blender-path]
277 (let [model (load-blender-model blender-path)
278 joints (creature-joints model)]
279 (assemble-creature model joints)))
281 (defn gray-scale [num]
282 (+ num
283 (bit-shift-left num 8)
284 (bit-shift-left num 16)))
286 (defn debug-touch-window
287 "creates function that offers a debug view of sensor data"
288 []
289 (let [vi (view-image)]
290 (fn
291 [[coords sensor-data]]
292 (let [image (points->image coords)]
293 (dorun
294 (for [i (range (count coords))]
295 (.setRGB image ((coords i) 0) ((coords i) 1)
296 (gray-scale (sensor-data i)))))
299 (vi image)))))
301 (defn debug-vision-window
302 "creates function that offers a debug view of sensor data"
303 []
304 (let [vi (view-image)]
305 (fn
306 [[coords sensor-data]]
307 (let [image (points->image coords)]
308 (dorun
309 (for [i (range (count coords))]
310 (.setRGB image ((coords i) 0) ((coords i) 1)
311 (sensor-data i))))
312 (vi image)))))
314 (defn debug-hearing-window
315 "view audio data"
316 [height]
317 (let [vi (view-image)]
318 (fn [[coords sensor-data]]
319 (let [image (BufferedImage. (count coords) height
320 BufferedImage/TYPE_INT_RGB)]
321 (dorun
322 (for [x (range (count coords))]
323 (dorun
324 (for [y (range height)]
325 (let [raw-sensor (sensor-data x)]
326 (.setRGB image x y (gray-scale raw-sensor)))))))
328 (vi image)))))
330 (defn test-creature [thing]
331 (let [x-axis
332 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
333 y-axis
334 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
335 z-axis
336 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)
337 creature (blender-creature thing)
338 touch-nerves (touch creature)
339 touch-debug-windows (map (fn [_] (debug-touch-window)) touch-nerves)
340 [init-vision-fns vision-data] (vision creature)
341 vision-debug (map (fn [_] (debug-vision-window)) vision-data)
342 me (sphere 0.5 :color ColorRGBA/Blue :physical? false)
343 [init-hearing-fns hearing-senses] (hearing creature)
344 hearing-windows (map (fn [_] (debug-hearing-window 50))
345 hearing-senses)
346 bell (AudioNode. (asset-manager)
347 "Sounds/pure.wav" false)
348 prop (proprioception creature)
349 prop-debug (proprioception-debug-window)
351 muscle-fns (enable-muscles creature)
352 ;; dream
354 ]
357 (apply
358 world
359 (with-movement
360 (.getChild creature "worm-21")
361 ["key-r" "key-t"
362 "key-f" "key-g"
363 "key-v" "key-b"]
364 [10 10 10 10 1 1]
365 [(nodify [creature
366 (box 10 2 10 :position (Vector3f. 0 -9 0)
367 :color ColorRGBA/Gray :mass 0)
368 x-axis y-axis z-axis
369 me
370 ])
371 (merge standard-debug-controls
372 {"key-return"
373 (fn [_ value]
374 (if value
375 (do
376 (println-repl "play-sound")
377 (.play bell))))
378 "key-h"
379 (fn [_ value]
380 (if value
381 (do
382 (println-repl "muscle activating!")
383 ((first muscle-fns) 199))))
385 })
386 (fn [world]
387 (light-up-everything world)
388 (enable-debug world)
389 (dorun (map #(% world) init-vision-fns))
390 (dorun (map #(% world) init-hearing-fns))
392 (add-eye world
393 (attach-eye creature (test-eye))
394 (comp (view-image) BufferedImage!))
396 (add-eye world (.getCamera world) no-op)
397 ;;(set-gravity world (Vector3f. 0 0 0))
398 ;;(com.aurellem.capture.Capture/captureVideo
399 ;; world (file-str "/home/r/proj/ai-videos/hand"))
400 ;;(.setTimer world (RatchetTimer. 60))
401 (speed-up world)
402 (set-gravity world (Vector3f. 0 0 0))
403 )
404 (fn [world tpf]
405 ;;(dorun
406 ;; (map #(%1 %2) touch-nerves (repeat (.getRootNode world))))
408 (prop-debug (prop))
410 (dorun
411 (map #(%1 (%2 (.getRootNode world)))
412 touch-debug-windows touch-nerves))
414 (dorun
415 (map #(%1 (%2))
416 vision-debug vision-data))
417 (dorun
418 (map #(%1 (%2)) hearing-windows hearing-senses))
421 ;;(println-repl (vision-data))
422 (.setLocalTranslation me (.getLocation (.getCamera world)))
425 )]
426 ;;(let [timer (atom 0)]
427 ;; (fn [_ _]
428 ;; (swap! timer inc)
429 ;; (if (= (rem @timer 60) 0)
430 ;; (println-repl (float (/ @timer 60))))))
431 ))))
435 ;; the camera will stay in its initial position/rotation with relation
436 ;; to the spatial.
439 (defn follow-test
440 "show a camera that stays in the same relative position to a blue cube."
441 []
442 (let [camera-pos (Vector3f. 0 30 0)
443 rock (box 1 1 1 :color ColorRGBA/Blue
444 :position (Vector3f. 0 10 0)
445 :mass 30
446 )
447 rot (.getWorldRotation rock)
449 table (box 3 1 10 :color ColorRGBA/Gray :mass 0
450 :position (Vector3f. 0 -3 0))]
452 (world
453 (nodify [rock table])
454 standard-debug-controls
455 (fn [world]
456 (let
457 [cam (doto (.clone (.getCamera world))
458 (.setLocation camera-pos)
459 (.lookAt Vector3f/ZERO
460 Vector3f/UNIT_X))]
461 (bind-sense rock cam)
463 (.setTimer world (RatchetTimer. 60))
464 (add-eye world cam (comp (view-image) BufferedImage!))
465 (add-eye world (.getCamera world) no-op))
466 )
467 (fn [_ _] (println-repl rot)))))
471 #+end_src
473 #+results: body-1
474 : #'cortex.silly/follow-test
477 * COMMENT purgatory
478 #+begin_src clojure
480 (defn bullet-trans* []
481 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
482 :position (Vector3f. 5 0 0)
483 :mass 90)
484 obj-b (sphere 0.5 :color ColorRGBA/Blue
485 :position (Vector3f. -5 0 0)
486 :mass 0)
487 control-a (.getControl obj-a RigidBodyControl)
488 control-b (.getControl obj-b RigidBodyControl)
489 move-up? (atom nil)
490 move-down? (atom nil)
491 move-left? (atom nil)
492 move-right? (atom nil)
493 roll-left? (atom nil)
494 roll-right? (atom nil)
495 force 100
496 swivel
497 (.toRotationMatrix
498 (doto (Quaternion.)
499 (.fromAngleAxis (/ Math/PI 2)
500 Vector3f/UNIT_X)))
501 x-move
502 (doto (Matrix3f.)
503 (.fromStartEndVectors Vector3f/UNIT_X
504 (.normalize (Vector3f. 1 1 0))))
506 timer (atom 0)]
507 (doto
508 (ConeJoint.
509 control-a control-b
510 (Vector3f. -8 0 0)
511 (Vector3f. 2 0 0)
512 ;;swivel swivel
513 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
514 x-move Matrix3f/IDENTITY
515 )
516 (.setCollisionBetweenLinkedBodys false)
517 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
518 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
519 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
520 (world (nodify
521 [obj-a obj-b])
522 (merge standard-debug-controls
523 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
524 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
525 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
526 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
527 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
528 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
530 (fn [world]
531 (enable-debug world)
532 (set-gravity world Vector3f/ZERO)
533 )
535 (fn [world _]
537 (if @move-up?
538 (.applyForce control-a
539 (Vector3f. force 0 0)
540 (Vector3f. 0 0 0)))
541 (if @move-down?
542 (.applyForce control-a
543 (Vector3f. (- force) 0 0)
544 (Vector3f. 0 0 0)))
545 (if @move-left?
546 (.applyForce control-a
547 (Vector3f. 0 force 0)
548 (Vector3f. 0 0 0)))
549 (if @move-right?
550 (.applyForce control-a
551 (Vector3f. 0 (- force) 0)
552 (Vector3f. 0 0 0)))
554 (if @roll-left?
555 (.applyForce control-a
556 (Vector3f. 0 0 force)
557 (Vector3f. 0 0 0)))
558 (if @roll-right?
559 (.applyForce control-a
560 (Vector3f. 0 0 (- force))
561 (Vector3f. 0 0 0)))
563 (if (zero? (rem (swap! timer inc) 100))
564 (.attachChild
565 (.getRootNode world)
566 (sphere 0.05 :color ColorRGBA/Yellow
567 :physical? false :position
568 (.getWorldTranslation obj-a)))))
569 )
570 ))
572 (defn test-joint [joint]
573 (let [[origin top bottom floor] (world-setup joint)
574 control (.getControl top RigidBodyControl)
575 move-up? (atom false)
576 move-down? (atom false)
577 move-left? (atom false)
578 move-right? (atom false)
579 roll-left? (atom false)
580 roll-right? (atom false)
581 timer (atom 0)]
583 (world
584 (nodify [top bottom floor origin])
585 (merge standard-debug-controls
586 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
587 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
588 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
589 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
590 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
591 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
593 (fn [world]
594 (light-up-everything world)
595 (enable-debug world)
596 (set-gravity world (Vector3f. 0 0 0))
597 )
599 (fn [world _]
600 (if (zero? (rem (swap! timer inc) 100))
601 (do
602 ;; (println-repl @timer)
603 (.attachChild (.getRootNode world)
604 (sphere 0.05 :color ColorRGBA/Yellow
605 :position (.getWorldTranslation top)
606 :physical? false))
607 (.attachChild (.getRootNode world)
608 (sphere 0.05 :color ColorRGBA/LightGray
609 :position (.getWorldTranslation bottom)
610 :physical? false))))
612 (if @move-up?
613 (.applyTorque control
614 (.mult (.getPhysicsRotation control)
615 (Vector3f. 0 0 10))))
616 (if @move-down?
617 (.applyTorque control
618 (.mult (.getPhysicsRotation control)
619 (Vector3f. 0 0 -10))))
620 (if @move-left?
621 (.applyTorque control
622 (.mult (.getPhysicsRotation control)
623 (Vector3f. 0 10 0))))
624 (if @move-right?
625 (.applyTorque control
626 (.mult (.getPhysicsRotation control)
627 (Vector3f. 0 -10 0))))
628 (if @roll-left?
629 (.applyTorque control
630 (.mult (.getPhysicsRotation control)
631 (Vector3f. -1 0 0))))
632 (if @roll-right?
633 (.applyTorque control
634 (.mult (.getPhysicsRotation control)
635 (Vector3f. 1 0 0))))))))
636 #+end_src
639 * COMMENT generate source
640 #+begin_src clojure :tangle ../src/cortex/silly.clj
641 <<body-1>>
642 #+end_src