view org/test-creature.org @ 84:4f5e2c629e45

going to try to fix cone-joint generating code
author Robert McIntyre <rlm@mit.edu>
date Sat, 07 Jan 2012 01:10:14 -0700
parents 14b604e955ed
children 00ab1f10266f
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 get-subjective-position)
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 connect
121 "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 registers
138 ;; it with both physics objects which in turn
139 ;; will register the joint with the physics system
140 ;; when the simulation is started.
141 (if-let [constraints
142 (map-vals
143 eval
144 (read-string
145 (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 (do
152 (println-repl "creating POINT joint")
153 (Point2PointJoint.
154 control-a
155 control-b
156 pivot-a
157 pivot-b))
158 (= :hinge joint-type)
159 (do
160 (println-repl "creating HINGE joint")
161 (let [axis (if-let
162 [axis (:axis constraints)]
163 axis
164 Vector3f/UNIT_X)
165 [limit-1 limit-2] (:limit constraints)
166 hinge-axis
167 (.mult
168 (.getWorldRotation joint)
169 (blender-to-jme axis))]
170 (doto
171 (HingeJoint.
172 control-a
173 control-b
174 pivot-a
175 pivot-b
176 hinge-axis
177 hinge-axis)
178 (.setLimit limit-1 limit-2))))
179 (= :cone joint-type)
180 (do
181 (let [limit-xz (:limit-xz constraints)
182 limit-xy (:limit-xy constraints)
183 twist (:twist constraints)]
185 (println-repl "creating CONE joint")
186 (let [frame-a
187 (.toRotationMatrix
188 (doto (Quaternion.)
189 (.fromAngleAxis
190 (float
191 (.angleBetween
192 (.normalize pivot-a) Vector3f/UNIT_X))
193 (.normalize
194 (.cross pivot-a
195 Vector3f/UNIT_X)))))
196 ]
197 (println-repl "pivot-a" pivot-a)
198 (println-repl
199 "angle between pivot-a and UNIT_X is"
200 (.angleBetween Vector3f/UNIT_X (.normalize pivot-a)))
201 (println-repl "frame-a:" frame-a)
202 (println-repl
203 "frame-a moves Vector3f/UNIT_X to"
204 (.mult frame-a Vector3f/UNIT_X ))
207 (doto
208 (ConeJoint.
209 control-a
210 control-b
211 pivot-a
212 pivot-b
215 ;; frame-in-A
216 ;;frame-a
217 ;;frame-a
219 (.toRotationMatrix
220 (doto (Quaternion.)
221 (.fromAngles
222 0 0 (* -0.5 (/ Math/PI 2)))))
225 ;; frame-in-B
226 (.toRotationMatrix
227 (doto (Quaternion.)
228 (.fromAngles
229 0 0 (* -0.5 (/ Math/PI 2)))))
232 )
233 (.setLimit (float limit-xz)
234 (float limit-xy)
235 (float twist))))))
236 true
237 (println-repl
238 "joint-type" joint-type "not recognized")))
240 (println-repl "could not find joint meta-data!"))))
243 (defn assemble-creature [#^Node pieces joints]
244 (dorun
245 (map
246 (fn [geom]
247 (let [physics-control
248 (RigidBodyControl.
249 (HullCollisionShape.
250 (.getMesh geom))
251 (if-let [mass (meta-data geom "mass")]
252 (do
253 (println-repl
254 "setting" (.getName geom) "mass to" (float mass))
255 (float mass))
256 (float 1)))]
258 (.addControl geom physics-control)))
259 (filter #(isa? (class %) Geometry )
260 (node-seq pieces))))
262 (dorun
263 (map
264 (fn [joint]
265 (let [[obj-a obj-b]
266 (joint-targets pieces joint)]
267 (connect obj-a obj-b joint)))
268 joints))
269 pieces)
271 (defn blender-creature [blender-path]
272 (let [model (load-blender-model blender-path)
273 joints
274 (if-let [joint-node (.getChild model "joints")]
275 (seq (.getChildren joint-node))
276 (do (println-repl "could not find joints node")
277 []))]
278 (assemble-creature model joints)))
280 (def hand "Models/creature1/one.blend")
282 (def worm "Models/creature1/try-again.blend")
284 (defn x-ray [#^ColorRGBA color]
285 (doto (Material. (asset-manager)
286 "Common/MatDefs/Misc/Unshaded.j3md")
287 (.setColor "Color" color)
288 (-> (.getAdditionalRenderState)
289 (.setDepthTest false))))
291 (defn test-creature [thing]
292 (let [x-axis
293 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
294 y-axis
295 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
296 z-axis
297 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
298 (world
299 (nodify [(blender-creature thing)
300 (box 10 2 10 :position (Vector3f. 0 -9 0)
301 :color ColorRGBA/Gray :mass 0)
302 x-axis y-axis z-axis
303 ])
304 standard-debug-controls
305 (comp light-up-everything enable-debug
306 (fn [world]
307 (.setTimer world (NanoTimer.))
308 (set-gravity world (Vector3f. 0 0 0))
309 (speed-up world)
310 world
311 ))
312 no-op)))
314 (defn world-setup [joint]
315 (let [
317 joint-position (Vector3f. 0 0 0)
318 joint-rotation
319 (.toRotationMatrix
320 (.mult
321 (doto (Quaternion.)
322 (.fromAngleAxis
323 (* 1 (/ Math/PI 4))
324 (Vector3f. 0 0 1)))
325 (.mult
326 (doto (Quaternion.)
327 (.fromAngleAxis
328 (* 2 (/ Math/PI 4))
329 (Vector3f. 0 1 0)))
330 (doto (Quaternion.)
331 (.fromAngleAxis
332 (* 1 (/ Math/PI 2))
333 (Vector3f. 0 0 1))))))
334 top-position (.mult joint-rotation (Vector3f. 8 0 0))
336 origin (doto
337 (sphere 0.1 :physical? false :color ColorRGBA/Cyan
338 :position top-position))
339 top (doto
340 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
341 :position top-position)
343 (.addControl
344 (RigidBodyControl.
345 (CapsuleCollisionShape. 0.5 1.5 1) (float 20))))
346 bottom (doto
347 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
348 :position (Vector3f. 0 0 0))
349 (.addControl
350 (RigidBodyControl.
351 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
352 table (box 10 2 10 :position (Vector3f. 0 -20 0)
353 :color ColorRGBA/Gray :mass 0)
354 a (.getControl top RigidBodyControl)
355 b (.getControl bottom RigidBodyControl)]
357 (cond
358 (= joint :cone)
360 (doto (ConeJoint.
361 a b
362 (get-subjective-position joint-position top)
363 (get-subjective-position joint-position bottom)
364 joint-rotation
365 joint-rotation
366 )
369 (.setLimit (* (/ 10) Math/PI)
370 (* (/ 4) Math/PI)
371 0)))
372 [origin top bottom table]))
376 (defn test-joint [joint]
377 (let [[origin top bottom floor] (world-setup joint)
378 control (.getControl top RigidBodyControl)
379 move-up? (atom false)
380 move-down? (atom false)
381 move-left? (atom false)
382 move-right? (atom false)
383 roll-left? (atom false)
384 roll-right? (atom false)
385 timer (atom 0)]
387 (world
388 (nodify [top bottom floor origin])
389 (merge standard-debug-controls
390 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
391 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
392 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
393 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
394 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
395 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
397 (fn [world]
398 (light-up-everything world)
399 (enable-debug world)
400 (set-gravity world (Vector3f. 0 0 0))
401 )
403 (fn [world _]
404 (if (zero? (rem (swap! timer inc) 100))
405 (do
406 ;; (println-repl @timer)
407 (.attachChild (.getRootNode world)
408 (sphere 0.05 :color ColorRGBA/Yellow
409 :position (.getWorldTranslation top)
410 :physical? false))
411 (.attachChild (.getRootNode world)
412 (sphere 0.05 :color ColorRGBA/LightGray
413 :position (.getWorldTranslation bottom)
414 :physical? false))))
416 (if @move-up?
417 (.applyTorque control
418 (.mult (.getPhysicsRotation control)
419 (Vector3f. 0 0 10))))
420 (if @move-down?
421 (.applyTorque control
422 (.mult (.getPhysicsRotation control)
423 (Vector3f. 0 0 -10))))
424 (if @move-left?
425 (.applyTorque control
426 (.mult (.getPhysicsRotation control)
427 (Vector3f. 0 10 0))))
428 (if @move-right?
429 (.applyTorque control
430 (.mult (.getPhysicsRotation control)
431 (Vector3f. 0 -10 0))))
432 (if @roll-left?
433 (.applyTorque control
434 (.mult (.getPhysicsRotation control)
435 (Vector3f. -1 0 0))))
436 (if @roll-right?
437 (.applyTorque control
438 (.mult (.getPhysicsRotation control)
439 (Vector3f. 1 0 0))))))))
453 ;; please validate these.
455 (defn get-subjective-position
456 "Convert the world coordinates into coordinates relative to
457 object (i.e. local coordinates), taking into account the rotation
458 of object."
459 [#^Vector3f world-coordinates object]
460 ;; I don't know if it's important to take into account the rotation
461 ;; of the object. If it isn't, then remove the multiplication-by-inverse.
462 (.mult (.inverse (.getWorldRotation object))
463 (.subtract world-coordinates (.getWorldTranslation object))))
466 (defn get-subjective-rotation
467 "cf get-subjective-position. Converts a rotation specified relative
468 to the world's axes into a rotation specified in terms of the object's
469 coordinate system."
470 [#^Quaternion world-rotation object]
471 (.mult (.inverse (.getWorldRotation object)) world-rotation))
476 (defn joint-create "Connect objects 1 and 2 using a joint constraint. If
477 only position is specified, creates a point-to-point joint at the
478 given location
479 in world coordinates. etc. etc. for other joints.
480 To ensure consistency, I may alter this function
481 so that it moves obj-1 to be at the apex of the cone.
483 NOTE:
484 In the usual construction method, you create a joint and, if your
485 contraints are consistent, all the objects snap into position and
486 orientation around it, otherwise the systen explodes.
488 This construction method assumes that you have in mind a position and
489 rotation for the joint, and that you have already put your objects
490 at the required distances from that joint so that no snapping needs
491 to occur. The radial distances ('pivot lengths') are therefore just set to be
492 the pre-existing distances between the objects and the joint."
493 [#^Node obj-1
494 #^Node obj-2
495 #^Vector3f joint-position
496 #^Quaternion joint-rotation
497 span-1
498 span-2
499 twist
500 ]
502 (let
503 [body-1 (.getControl obj-1 RigidBodyControl)
504 body-2 (.getControl obj-2 RigidBodyControl)
505 ]
506 (doto (ConeJoint.
507 body-1
508 body-2
509 (get-subjective-position joint-position body-1)
510 (get-subjective-position joint-position body-2)
511 ;; ALIGN X-AXIS OF OBJECT-1 WITH THE CENTRAL AXIS OF THE CONE TO
512 ;;LOWER THE RISK OF INCONSISTENCY
513 ;;(Matrix3f/IDENTITY)
514 (.toRotationMatrix (get-subjective-rotation joint-rotation body-1))
515 (.toRotationMatrix (get-subjective-rotation joint-rotation body-2))
516 )
517 (.setLimit
518 span-1
519 span-2
520 twist))))
527 #+end_src
530 * COMMENT purgatory
531 #+begin_src clojure
532 (defn bullet-trans []
533 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
534 :position (Vector3f. -10 5 0))
535 obj-b (sphere 0.5 :color ColorRGBA/Blue
536 :position (Vector3f. -10 -5 0)
537 :mass 0)
538 control-a (.getControl obj-a RigidBodyControl)
539 control-b (.getControl obj-b RigidBodyControl)
540 swivel
541 (.toRotationMatrix
542 (doto (Quaternion.)
543 (.fromAngleAxis (/ Math/PI 2)
544 Vector3f/UNIT_X)))]
545 (doto
546 (ConeJoint.
547 control-a control-b
548 (Vector3f. 0 5 0)
549 (Vector3f. 0 -5 0)
550 swivel swivel)
551 (.setLimit (* 0.6 (/ Math/PI 4))
552 (/ Math/PI 4)
553 (* Math/PI 0.8)))
554 (world (nodify
555 [obj-a obj-b])
556 standard-debug-controls
557 enable-debug
558 no-op)))
561 (defn bullet-trans* []
562 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
563 :position (Vector3f. 5 0 0)
564 :mass 90)
565 obj-b (sphere 0.5 :color ColorRGBA/Blue
566 :position (Vector3f. -5 0 0)
567 :mass 0)
568 control-a (.getControl obj-a RigidBodyControl)
569 control-b (.getControl obj-b RigidBodyControl)
570 move-up? (atom nil)
571 move-down? (atom nil)
572 move-left? (atom nil)
573 move-right? (atom nil)
574 roll-left? (atom nil)
575 roll-right? (atom nil)
576 force 100
577 swivel
578 (.toRotationMatrix
579 (doto (Quaternion.)
580 (.fromAngleAxis (/ Math/PI 2)
581 Vector3f/UNIT_X)))
582 x-move
583 (doto (Matrix3f.)
584 (.fromStartEndVectors Vector3f/UNIT_X
585 (.normalize (Vector3f. 1 1 0))))
587 timer (atom 0)]
588 (doto
589 (ConeJoint.
590 control-a control-b
591 (Vector3f. -8 0 0)
592 (Vector3f. 2 0 0)
593 ;;swivel swivel
594 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
595 x-move Matrix3f/IDENTITY
596 )
597 (.setCollisionBetweenLinkedBodys false)
598 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
599 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
600 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
601 (world (nodify
602 [obj-a obj-b])
603 (merge standard-debug-controls
604 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
605 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
606 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
607 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
608 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
609 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
611 (fn [world]
612 (enable-debug world)
613 (set-gravity world Vector3f/ZERO)
614 )
616 (fn [world _]
618 (if @move-up?
619 (.applyForce control-a
620 (Vector3f. force 0 0)
621 (Vector3f. 0 0 0)))
622 (if @move-down?
623 (.applyForce control-a
624 (Vector3f. (- force) 0 0)
625 (Vector3f. 0 0 0)))
626 (if @move-left?
627 (.applyForce control-a
628 (Vector3f. 0 force 0)
629 (Vector3f. 0 0 0)))
630 (if @move-right?
631 (.applyForce control-a
632 (Vector3f. 0 (- force) 0)
633 (Vector3f. 0 0 0)))
635 (if @roll-left?
636 (.applyForce control-a
637 (Vector3f. 0 0 force)
638 (Vector3f. 0 0 0)))
639 (if @roll-right?
640 (.applyForce control-a
641 (Vector3f. 0 0 (- force))
642 (Vector3f. 0 0 0)))
644 (if (zero? (rem (swap! timer inc) 100))
645 (.attachChild
646 (.getRootNode world)
647 (sphere 0.05 :color ColorRGBA/Yellow
648 :physical? false :position
649 (.getWorldTranslation obj-a)))))
650 )
651 ))
655 #+end_src
658 * COMMENT generate source
659 #+begin_src clojure :tangle ../src/cortex/silly.clj
660 <<body-1>>
661 #+end_src