view org/test-creature.org @ 90:6d7c17c847a3

saving progress
author Robert McIntyre <rlm@mit.edu>
date Sun, 08 Jan 2012 06:11:58 -0700
parents cd5151b5e7c3
children 2bcc7636cfea
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
9 * Intro
10 So far, I've made the following senses --
11 - Vision
12 - Hearing
13 - Touch
14 - Proprioception
16 And one effector:
17 - Movement
19 However, the code so far has only enabled these senses, but has not
20 actually implemented them. For example, there is still a lot of work
21 to be done for vision. I need to be able to create an /eyeball/ in
22 simulation that can be moved around and see the world from different
23 angles. I also need to determine weather to use log-polar or cartesian
24 for the visual input, and I need to determine how/wether to
25 disceritise the visual input.
27 I also want to be able to visualize both the sensors and the
28 effectors in pretty pictures. This semi-retarted creature will by my
29 first attempt at bringing everything together.
31 * The creature's body
33 Still going to do an eve-like body in blender, but due to problems
34 importing the joints, etc into jMonkeyEngine3, I',m going to do all
35 the connecting here in clojure code, using the names of the individual
36 components and trial and error. Later, I'll maybe make some sort of
37 creature-building modifications to blender that support whatever
38 discreitized senses I'm going to make.
40 #+name: body-1
41 #+begin_src clojure
42 (ns cortex.silly
43 "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)
55 (defn load-bullet []
56 (let [sim (world (Node.) {} no-op no-op)]
57 (.enqueue
58 sim
59 (fn []
60 (.stop sim)))
61 (.start sim)))
63 (defn load-blender-model
64 "Load a .blend file using an asset folder relative path."
65 [^String model]
66 (.loadModel
67 (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-jme
77 "Convert from Blender coordinates to JME coordinates"
78 [#^Vector3f in]
79 (Vector3f. (.getX in)
80 (.getZ in)
81 (- (.getY in))))
83 (defn jme-to-blender
84 "Convert from JME coordinates to Blender coordinates"
85 [#^Vector3f in]
86 (Vector3f. (.getX in)
87 (- (.getZ in))
88 (.getY in)))
90 (defn joint-targets
91 "Return the two closest two objects to the joint object, ordered
92 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 (.collideWith
99 parts
100 (BoundingBox. (.getWorldTranslation joint)
101 radius radius radius)
102 results)
103 (let [targets
104 (distinct
105 (map #(.getGeometry %) results))]
106 (if (>= (count targets) 2)
107 (sort-by
108 #(let [v
109 (jme-to-blender
110 (.mult
111 (.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 world-to-local
121 "Convert the world coordinates into coordinates relative to the
122 object (i.e. local coordinates), taking into account the rotation
123 of object."
124 [#^Spatial object world-coordinate]
125 (let [out (Vector3f.)]
126 (.worldToLocal object world-coordinate out) out))
128 (defmulti joint-dispatch
129 "Translate blender pseudo-joints into real JME joints."
130 (fn [constraints & _]
131 (:type constraints)))
133 (defmethod joint-dispatch :point
134 [constraints control-a control-b pivot-a pivot-b rotation]
135 (println-repl "creating POINT2POINT joint")
136 (Point2PointJoint.
137 control-a
138 control-b
139 pivot-a
140 pivot-b))
142 (defmethod joint-dispatch :hinge
143 [constraints control-a control-b pivot-a pivot-b rotation]
144 (println-repl "creating HINGE joint")
145 (let [axis
146 (if-let
147 [axis (:axis constraints)]
148 axis
149 Vector3f/UNIT_X)
150 [limit-1 limit-2] (:limit constraints)
151 hinge-axis
152 (.mult
153 rotation
154 (blender-to-jme axis))]
155 (doto
156 (HingeJoint.
157 control-a
158 control-b
159 pivot-a
160 pivot-b
161 hinge-axis
162 hinge-axis)
163 (.setLimit limit-1 limit-2))))
165 (defmethod joint-dispatch :cone
166 [constraints control-a control-b pivot-a pivot-b rotation]
167 (let [limit-xz (:limit-xz constraints)
168 limit-xy (:limit-xy constraints)
169 twist (:twist constraints)]
171 (println-repl "creating CONE joint")
172 (println-repl rotation)
173 (println-repl
174 "UNIT_X --> " (.mult rotation (Vector3f. 1 0 0)))
175 (println-repl
176 "UNIT_Y --> " (.mult rotation (Vector3f. 0 1 0)))
177 (println-repl
178 "UNIT_Z --> " (.mult rotation (Vector3f. 0 0 1)))
179 (doto
180 (ConeJoint.
181 control-a
182 control-b
183 pivot-a
184 pivot-b
185 rotation
186 rotation)
187 (.setLimit (float limit-xz)
188 (float limit-xy)
189 (float twist)))))
191 (defn connect
192 "here are some examples:
193 {:type :point}
194 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
195 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
197 {:type :cone :limit-xz 0]
198 :limit-xy 0]
199 :twist 0]} (use XZY rotation mode in blender!)"
200 [#^Node obj-a #^Node obj-b #^Node joint]
201 (let [control-a (.getControl obj-a RigidBodyControl)
202 control-b (.getControl obj-b RigidBodyControl)
203 joint-center (.getWorldTranslation joint)
204 joint-rotation (.toRotationMatrix (.getWorldRotation joint))
205 pivot-a (world-to-local obj-a joint-center)
206 pivot-b (world-to-local obj-b joint-center)]
208 (if-let [constraints
209 (map-vals
210 eval
211 (read-string
212 (meta-data joint "joint")))]
213 ;; A side-effect of creating a joint registers
214 ;; it with both physics objects which in turn
215 ;; will register the joint with the physics system
216 ;; when the simulation is started.
217 (do
218 (println-repl "creating joint between"
219 (.getName obj-a) "and" (.getName obj-b))
220 (joint-dispatch constraints
221 control-a control-b
222 pivot-a pivot-b
223 joint-rotation))
224 (println-repl "could not find joint meta-data!"))))
226 (defn assemble-creature [#^Node pieces joints]
227 (dorun
228 (map
229 (fn [geom]
230 (let [physics-control
231 (RigidBodyControl.
232 (HullCollisionShape.
233 (.getMesh geom))
234 (if-let [mass (meta-data geom "mass")]
235 (do
236 (println-repl
237 "setting" (.getName geom) "mass to" (float mass))
238 (float mass))
239 (float 1)))]
241 (.addControl geom physics-control)))
242 (filter #(isa? (class %) Geometry )
243 (node-seq pieces))))
245 (dorun
246 (map
247 (fn [joint]
248 (let [[obj-a obj-b]
249 (joint-targets pieces joint)]
250 (connect obj-a obj-b joint)))
251 joints))
252 pieces)
254 (defn blender-creature [blender-path]
255 (let [model (load-blender-model blender-path)
256 joints
257 (if-let [joint-node (.getChild model "joints")]
258 (seq (.getChildren joint-node))
259 (do (println-repl "could not find joints node")
260 []))]
261 (assemble-creature model joints)))
263 (def hand "Models/creature1/one.blend")
265 (def worm "Models/creature1/try-again.blend")
267 (def touch "Models/creature1/touch.blend")
269 (defn worm-model [] (load-blender-model worm))
271 (defn x-ray [#^ColorRGBA color]
272 (doto (Material. (asset-manager)
273 "Common/MatDefs/Misc/Unshaded.j3md")
274 (.setColor "Color" color)
275 (-> (.getAdditionalRenderState)
276 (.setDepthTest false))))
278 (defn test-creature [thing]
279 (let [x-axis
280 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
281 y-axis
282 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
283 z-axis
284 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
285 (world
286 (nodify [(blender-creature thing)
287 (box 10 2 10 :position (Vector3f. 0 -9 0)
288 :color ColorRGBA/Gray :mass 0)
289 x-axis y-axis z-axis
290 ])
291 standard-debug-controls
292 (fn [world]
293 (light-up-everything world)
294 (enable-debug world)
295 ;;(com.aurellem.capture.Capture/captureVideo
296 ;; world (file-str "/home/r/proj/ai-videos/hand"))
297 (.setTimer world (NanoTimer.))
298 ;;(set-gravity world (Vector3f. 0 0 0))
299 (speed-up world)
300 )
301 no-op
302 ;;(let [timer (atom 0)]
303 ;; (fn [_ _]
304 ;; (swap! timer inc)
305 ;; (if (= (rem @timer 60) 0)
306 ;; (println-repl (float (/ @timer 60))))))
307 )))
310 (def colorful (.getChild (worm-model) "worm-21"))
312 (def im-data
313 (let [sink (byte-array 3145727)
314 data (.getData (.getImage texture) 0)]
315 (.rewind data)
316 (.get data sink)
317 (vec (seq sink))))
320 (import jme3tools.converters.ImageToAwt)
322 (import ij.ImagePlus)
326 (defn triangle-indices
327 "Get the triangle vertex indices of a given triangle from a given
328 mesh."
329 [#^Mesh mesh triangle-index]
330 (let [indices (int-array 3)]
331 (.getTriangle mesh triangle-index indices)
332 (vec indices)))
334 (defn uv-coord
335 "Get the uv-coordinates of the vertex named by vertex-index"
336 [#^Mesh mesh vertex-index]
337 (let [UV-buffer
338 (.getData
339 (.getBuffer
340 mesh
341 VertexBuffer$Type/TexCoord))]
342 [(.get UV-buffer (* vertex-index 2))
343 (.get UV-buffer (+ 1 (* vertex-index 2)))]))
345 (defn touch-receptor-image [#^Geometry obj]
349 ;; yay there's a converter!
351 (defn uv-image []
352 (let
353 [colorful (.getChild (worm-model) "worm-21")
354 mat (.getMaterial colorful)
355 texture
356 (.getTextureValue
357 (.getTextureParam
358 mat
359 MaterialHelper/TEXTURE_TYPE_DIFFUSE))
360 im (.getImage texture)]
361 (ImagePlus.
362 "UV-map"
363 (ImageToAwt/convert im false false 0))))
365 ;; for each triangle in the mesh,
366 ;; get the normal to the triangle,
367 ;; look at the UV touch map, restricted to that triangle,
368 ;; get the positions of those touch sensors in geometry-relative
369 ;; coordinates.
379 (defrecord LulzLoader [])
380 (defprotocol Lulzable (load-lulz [this]))
381 (extend-type LulzLoader
382 Lulzable
383 (load-lulz [this] (println "the lulz have arrived!")))
385 (defn
389 (defn world-setup [joint]
390 (let [joint-position (Vector3f. 0 0 0)
391 joint-rotation
392 (.toRotationMatrix
393 (.mult
394 (doto (Quaternion.)
395 (.fromAngleAxis
396 (* 1 (/ Math/PI 4))
397 (Vector3f. -1 0 0)))
398 (doto (Quaternion.)
399 (.fromAngleAxis
400 (* 1 (/ Math/PI 2))
401 (Vector3f. 0 0 1)))))
402 top-position (.mult joint-rotation (Vector3f. 8 0 0))
404 origin (doto
405 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
406 :position top-position))
407 top (doto
408 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
409 :position top-position)
411 (.addControl
412 (RigidBodyControl.
413 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
414 bottom (doto
415 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
416 :position (Vector3f. 0 0 0))
417 (.addControl
418 (RigidBodyControl.
419 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
420 table (box 10 2 10 :position (Vector3f. 0 -20 0)
421 :color ColorRGBA/Gray :mass 0)
422 a (.getControl top RigidBodyControl)
423 b (.getControl bottom RigidBodyControl)]
425 (cond
426 (= joint :cone)
428 (doto (ConeJoint.
429 a b
430 (world-to-local top joint-position)
431 (world-to-local bottom joint-position)
432 joint-rotation
433 joint-rotation
434 )
437 (.setLimit (* (/ 10) Math/PI)
438 (* (/ 4) Math/PI)
439 0)))
440 [origin top bottom table]))
442 (defn test-joint [joint]
443 (let [[origin top bottom floor] (world-setup joint)
444 control (.getControl top RigidBodyControl)
445 move-up? (atom false)
446 move-down? (atom false)
447 move-left? (atom false)
448 move-right? (atom false)
449 roll-left? (atom false)
450 roll-right? (atom false)
451 timer (atom 0)]
453 (world
454 (nodify [top bottom floor origin])
455 (merge standard-debug-controls
456 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
457 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
458 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
459 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
460 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
461 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
463 (fn [world]
464 (light-up-everything world)
465 (enable-debug world)
466 (set-gravity world (Vector3f. 0 0 0))
467 )
469 (fn [world _]
470 (if (zero? (rem (swap! timer inc) 100))
471 (do
472 ;; (println-repl @timer)
473 (.attachChild (.getRootNode world)
474 (sphere 0.05 :color ColorRGBA/Yellow
475 :position (.getWorldTranslation top)
476 :physical? false))
477 (.attachChild (.getRootNode world)
478 (sphere 0.05 :color ColorRGBA/LightGray
479 :position (.getWorldTranslation bottom)
480 :physical? false))))
482 (if @move-up?
483 (.applyTorque control
484 (.mult (.getPhysicsRotation control)
485 (Vector3f. 0 0 10))))
486 (if @move-down?
487 (.applyTorque control
488 (.mult (.getPhysicsRotation control)
489 (Vector3f. 0 0 -10))))
490 (if @move-left?
491 (.applyTorque control
492 (.mult (.getPhysicsRotation control)
493 (Vector3f. 0 10 0))))
494 (if @move-right?
495 (.applyTorque control
496 (.mult (.getPhysicsRotation control)
497 (Vector3f. 0 -10 0))))
498 (if @roll-left?
499 (.applyTorque control
500 (.mult (.getPhysicsRotation control)
501 (Vector3f. -1 0 0))))
502 (if @roll-right?
503 (.applyTorque control
504 (.mult (.getPhysicsRotation control)
505 (Vector3f. 1 0 0))))))))
509 #+end_src
511 #+results: body-1
512 : #'cortex.silly/test-joint
515 * COMMENT purgatory
516 #+begin_src clojure
517 (defn bullet-trans []
518 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
519 :position (Vector3f. -10 5 0))
520 obj-b (sphere 0.5 :color ColorRGBA/Blue
521 :position (Vector3f. -10 -5 0)
522 :mass 0)
523 control-a (.getControl obj-a RigidBodyControl)
524 control-b (.getControl obj-b RigidBodyControl)
525 swivel
526 (.toRotationMatrix
527 (doto (Quaternion.)
528 (.fromAngleAxis (/ Math/PI 2)
529 Vector3f/UNIT_X)))]
530 (doto
531 (ConeJoint.
532 control-a control-b
533 (Vector3f. 0 5 0)
534 (Vector3f. 0 -5 0)
535 swivel swivel)
536 (.setLimit (* 0.6 (/ Math/PI 4))
537 (/ Math/PI 4)
538 (* Math/PI 0.8)))
539 (world (nodify
540 [obj-a obj-b])
541 standard-debug-controls
542 enable-debug
543 no-op)))
546 (defn bullet-trans* []
547 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
548 :position (Vector3f. 5 0 0)
549 :mass 90)
550 obj-b (sphere 0.5 :color ColorRGBA/Blue
551 :position (Vector3f. -5 0 0)
552 :mass 0)
553 control-a (.getControl obj-a RigidBodyControl)
554 control-b (.getControl obj-b RigidBodyControl)
555 move-up? (atom nil)
556 move-down? (atom nil)
557 move-left? (atom nil)
558 move-right? (atom nil)
559 roll-left? (atom nil)
560 roll-right? (atom nil)
561 force 100
562 swivel
563 (.toRotationMatrix
564 (doto (Quaternion.)
565 (.fromAngleAxis (/ Math/PI 2)
566 Vector3f/UNIT_X)))
567 x-move
568 (doto (Matrix3f.)
569 (.fromStartEndVectors Vector3f/UNIT_X
570 (.normalize (Vector3f. 1 1 0))))
572 timer (atom 0)]
573 (doto
574 (ConeJoint.
575 control-a control-b
576 (Vector3f. -8 0 0)
577 (Vector3f. 2 0 0)
578 ;;swivel swivel
579 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
580 x-move Matrix3f/IDENTITY
581 )
582 (.setCollisionBetweenLinkedBodys false)
583 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
584 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
585 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
586 (world (nodify
587 [obj-a obj-b])
588 (merge standard-debug-controls
589 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
590 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
591 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
592 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
593 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
594 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
596 (fn [world]
597 (enable-debug world)
598 (set-gravity world Vector3f/ZERO)
599 )
601 (fn [world _]
603 (if @move-up?
604 (.applyForce control-a
605 (Vector3f. force 0 0)
606 (Vector3f. 0 0 0)))
607 (if @move-down?
608 (.applyForce control-a
609 (Vector3f. (- force) 0 0)
610 (Vector3f. 0 0 0)))
611 (if @move-left?
612 (.applyForce control-a
613 (Vector3f. 0 force 0)
614 (Vector3f. 0 0 0)))
615 (if @move-right?
616 (.applyForce control-a
617 (Vector3f. 0 (- force) 0)
618 (Vector3f. 0 0 0)))
620 (if @roll-left?
621 (.applyForce control-a
622 (Vector3f. 0 0 force)
623 (Vector3f. 0 0 0)))
624 (if @roll-right?
625 (.applyForce control-a
626 (Vector3f. 0 0 (- force))
627 (Vector3f. 0 0 0)))
629 (if (zero? (rem (swap! timer inc) 100))
630 (.attachChild
631 (.getRootNode world)
632 (sphere 0.05 :color ColorRGBA/Yellow
633 :physical? false :position
634 (.getWorldTranslation obj-a)))))
635 )
636 ))
640 #+end_src
643 * COMMENT generate source
644 #+begin_src clojure :tangle ../src/cortex/silly.clj
645 <<body-1>>
646 #+end_src