view org/test-creature.org @ 81:10f495560c59

correcting problem with joints
author Robert McIntyre <rlm@mit.edu>
date Thu, 05 Jan 2012 21:31:34 -0700
parents 7af5ef686539
children 6b4ca076285e
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 (defn load-blender-model
54 "Load a .blend file using an asset folder relative path."
55 [^String model]
56 (.loadModel
57 (doto (asset-manager)
58 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
59 model))
61 (defn meta-data [blender-node key]
62 (if-let [data (.getUserData blender-node "properties")]
63 (.findValue data key)
64 nil))
66 (defn blender-to-jme
67 "Convert from Blender coordinates to JME coordinates"
68 [#^Vector3f in]
69 (Vector3f. (.getX in)
70 (.getZ in)
71 (- (.getY in))))
73 (defn jme-to-blender
74 "Convert from JME coordinates to Blender coordinates"
75 [#^Vector3f in]
76 (Vector3f. (.getX in)
77 (- (.getZ in))
78 (.getY in)))
80 (defn joint-targets
81 "Return the two closest two objects to the joint object, ordered
82 from bottom to top according to the joint's rotation."
83 [#^Node parts #^Node joint]
84 ;;(println (meta-data joint "joint"))
85 (.getWorldRotation joint)
86 (loop [radius (float 0.01)]
87 (let [results (CollisionResults.)]
88 (.collideWith
89 parts
90 (BoundingBox. (.getWorldTranslation joint)
91 radius radius radius)
92 results)
93 (let [targets
94 (distinct
95 (map #(.getGeometry %) results))]
96 (if (>= (count targets) 2)
97 (sort-by
98 #(let [v
99 (jme-to-blender
100 (.mult
101 (.inverse (.getWorldRotation joint))
102 (.subtract (.getWorldTranslation %)
103 (.getWorldTranslation joint))))]
104 (println-repl (.getName %) ":" v)
105 (.dot (Vector3f. 1 1 1)
106 v))
107 (take 2 targets))
108 (recur (float (* radius 2))))))))
110 (defn connect
111 "here are some examples:
112 {:type :point}
113 {:type :hinge :limit [0 (/ Math/PI 2)] :axis (Vector3f. 0 1 0)}
114 (:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
116 {:type :cone :limit-xz 0]
117 :limit-xy 0]
118 :twist 0]} (use XZY rotation mode in blender!)"
119 [#^Node obj-a #^Node obj-b #^Node joint]
120 (let [center-a (.getWorldTranslation obj-a)
121 center-b (.getWorldTranslation obj-b)
122 joint-center (.getWorldTranslation joint)
123 pivot-a (.subtract joint-center center-a)
124 pivot-b (.subtract joint-center center-b)
125 control-a (.getControl obj-a RigidBodyControl)
126 control-b (.getControl obj-b RigidBodyControl)]
127 ;; A side-effect of creating a joint registers
128 ;; it with both physics objects which in turn
129 ;; will register the joint with the physics system
130 ;; when the simulation is started.
131 (if-let [constraints
132 (map-vals
133 eval
134 (read-string
135 (meta-data joint "joint")))]
137 (let [joint-type (:type constraints)]
138 (println-repl "creating joint between"
139 (.getName obj-a) "and" (.getName obj-b))
140 (cond (= :point joint-type)
141 (do
142 (println-repl "creating POINT joint")
143 (Point2PointJoint.
144 control-a
145 control-b
146 pivot-a
147 pivot-b))
148 (= :hinge joint-type)
149 (do
150 (println-repl "creating HINGE joint")
151 (let [axis (if-let
152 [axis (:axis constraints)]
153 axis
154 Vector3f/UNIT_X)
155 [limit-1 limit-2] (:limit constraints)
156 hinge-axis
157 (.mult
158 (.getWorldRotation joint)
159 (blender-to-jme axis))]
160 (doto
161 (HingeJoint.
162 control-a
163 control-b
164 pivot-a
165 pivot-b
166 hinge-axis
167 hinge-axis)
168 (.setLimit limit-1 limit-2))))
169 (= :cone joint-type)
170 (do
171 (let [limit-xz (:limit-xz constraints)
172 limit-xy (:limit-xy constraints)
173 twist (:twist constraints)]
175 (println-repl "creating CONE joint")
176 (let [vector-1
177 (.mult (.getWorldRotation joint)
178 Vector3f/UNIT_X)
179 vector-2
180 (.normalize
181 (.subtract
182 (.getWorldTranslation joint)
183 (.getWorldTranslation obj-a)))
184 ]
185 (println-repl
186 "vector-1 :" vector-1)
187 (println-repl
188 "vector-2 :" vector-2)
192 (doto
193 (ConeJoint.
194 control-a
195 control-b
196 pivot-a
197 pivot-b
199 ;;(doto (Matrix3f.)
200 ;; (.fromStartEndVectors
201 ;; Vector3f/UNIT_X
202 ;; (.normalize
203 ;; (.subtract
204 ;; (.getWorldTranslation joint)
205 ;; (.getWorldTranslation obj-a)))))
208 (.toRotationMatrix
209 (.getWorldRotation joint))
213 (.toRotationMatrix
214 (.fromAngleAxis
215 (Quaternion.)
216 (.angleBetween Vector3f/UNIT_X pivot-a)
217 (.cross Vector3f/UNIT_X pivot-a)))
222 ;; (doto (Matrix3f.)
223 ;; (.fromStartEndVectors
224 ;; Vector3f/UNIT_X
225 ;; (.normalize
226 ;; vector-1)))
228 ;; (doto (Matrix3f.)
229 ;; (.fromStartEndVectors
230 ;; Vector3f/UNIT_X
231 ;; vector-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!"))))
242 (defn assemble-creature [#^Node pieces joints]
243 (dorun
244 (map
245 (fn [geom]
246 (let [physics-control
247 (RigidBodyControl.
248 (HullCollisionShape.
249 (.getMesh geom))
250 (if-let [mass (meta-data geom "mass")]
251 (do
252 (println-repl
253 "setting" (.getName geom) "mass to" (float mass))
254 (float mass))
255 (float 1)))]
257 (.addControl geom physics-control)))
258 (filter #(isa? (class %) Geometry )
259 (node-seq pieces))))
261 (dorun
262 (map
263 (fn [joint]
264 (let [[obj-a obj-b]
265 (joint-targets pieces joint)]
266 (connect obj-a obj-b joint)))
267 joints))
268 pieces)
270 (defn blender-creature [blender-path]
271 (let [model (load-blender-model blender-path)
272 joints
273 (if-let [joint-node (.getChild model "joints")]
274 (seq (.getChildren joint-node))
275 (do (println-repl "could not find joints node")
276 []))]
277 (assemble-creature model joints)))
279 (def hand "Models/creature1/one.blend")
281 (def worm "Models/creature1/try-again.blend")
283 (defn x-ray [#^ColorRGBA color]
284 (doto (Material. (asset-manager)
285 "Common/MatDefs/Misc/Unshaded.j3md")
286 (.setColor "Color" color)
287 (-> (.getAdditionalRenderState)
288 (.setDepthTest false))))
290 (defn test-creature [thing]
291 (let [x-axis
292 (box 1 0.01 0.01 :physical? false :color ColorRGBA/Red)
293 y-axis
294 (box 0.01 1 0.01 :physical? false :color ColorRGBA/Green)
295 z-axis
296 (box 0.01 0.01 1 :physical? false :color ColorRGBA/Blue)]
297 (world
298 (nodify [(blender-creature thing)
299 (box 10 2 10 :position (Vector3f. 0 -9 0)
300 :color ColorRGBA/Gray :mass 0)
301 x-axis y-axis z-axis
302 ])
303 standard-debug-controls
304 (comp light-up-everything enable-debug
305 (fn [world]
306 (.setTimer world (NanoTimer.))
307 (set-gravity world (Vector3f. 0 0 0))
308 (speed-up world)
309 world
310 ))
311 no-op)))
313 (defn world-setup [joint]
314 (let [top (doto
315 (sphere 0.1 :physical? false :color ColorRGBA/Yellow
316 :position (Vector3f. 0 7 0))
317 (.addControl
318 (RigidBodyControl.
319 (CapsuleCollisionShape. 0.5 1.5 1) (float 15))))
320 bottom (doto
321 (sphere 0.1 :physical? false :color ColorRGBA/DarkGray
322 :position (Vector3f. 0 -1 0))
323 (.addControl
324 (RigidBodyControl.
325 (CapsuleCollisionShape. 0.5 1.5 1) (float 0))))
326 table (box 10 2 10 :position (Vector3f. 0 -6 0)
327 :color ColorRGBA/Gray :mass 0)
328 a (.getControl top RigidBodyControl)
329 b (.getControl bottom RigidBodyControl)]
330 (cond
331 (= joint :point)
332 (doto
333 (Point2PointJoint. a b
334 (Vector3f. 0 -2 0)
335 (Vector3f. 0 2 0))
336 (.setCollisionBetweenLinkedBodys false))
337 (= joint :hinge)
338 (doto
339 (HingeJoint.
340 a b
341 (Vector3f. 0 -2 0)
342 (Vector3f. 0 2 0)
343 (Vector3f. 0 0 1)
344 (Vector3f. 0 0 1)
346 )
347 (.setCollisionBetweenLinkedBodys false)
348 ;;(.setLimit (- Math/PI) Math/PI)
349 )
350 (= joint :cone)
351 ;; note to self -- jbullet does NOT implement cone joints
352 ;; correctly. You must use plain ol' bullet for this to work.
353 ;; It's faster anyway, so whatever.
355 (doto (ConeJoint.
356 a b
357 (Vector3f. 0 -5 0)
358 (Vector3f. 0 2 0)
360 (doto (Matrix3f.)
361 (.fromStartEndVectors Vector3f/UNIT_X
362 Vector3f/UNIT_Y))
363 (doto (Matrix3f.)
364 (.fromStartEndVectors Vector3f/UNIT_X
365 (.normalize
366 (Vector3f. 0 0 -1))))
367 )
368 ;;(.setAngularOnly true)
370 (.setCollisionBetweenLinkedBodys false)
371 (.setLimit (* 1 (/ Math/PI 4))
372 (* 1 (/ Math/PI 2))
373 (* 0 (/ Math/PI 4)))
375 )
376 (= joint :six)
377 (doto
378 (SixDofJoint.
379 a b
380 (Vector3f. 0 -2 0)
381 (Vector3f. 0 2 0)
382 ;;(doto (Matrix3f.)
383 ;; (.fromStartEndVectors Vector3f/UNIT_X
384 ;; Vector3f/UNIT_Y))
385 ;;(doto (Matrix3f.)
386 ;; (.fromStartEndVectors Vector3f/UNIT_X
387 ;; Vector3f/UNIT_Y))
388 true)
389 (.setCollisionBetweenLinkedBodys false)
390 (.setAngularLowerLimit (Vector3f. 0
391 (- (/ Math/PI 2))
392 0))
394 (.setAngularUpperLimit (Vector3f. 0
395 (/ Math/PI 2)
396 0))
397 (.setLinearLowerLimit (Vector3f. 0 0 0))
398 (.setLinearUpperLimit (Vector3f. 0 0 0))
400 )
406 )
408 [top bottom table]))
411 (defn test-joint [joint]
412 (let [[top bottom floor] (world-setup joint)
413 control (.getControl top RigidBodyControl)
414 move-up? (atom false)
415 move-down? (atom false)
416 move-left? (atom false)
417 move-right? (atom false)
418 roll-left? (atom false)
419 roll-right? (atom false)
420 timer (atom 0)]
422 (world
423 (nodify [top bottom floor])
424 (merge standard-debug-controls
425 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
426 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
427 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
428 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
429 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
430 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
432 (fn [world]
433 (light-up-everything world)
434 (enable-debug world)
435 (set-gravity world (Vector3f. 0 0 0))
436 )
438 (fn [world _]
439 (if (zero? (rem (swap! timer inc) 100))
440 (do
441 ;; (println-repl @timer)
442 (.attachChild (.getRootNode world)
443 (sphere 0.05 :color ColorRGBA/Yellow
444 :position (.getWorldTranslation top)
445 :physical? false))))
446 (if @move-up?
447 (.applyTorque control
448 (.mult (.getPhysicsRotation control)
449 (Vector3f. 0 0 10))))
450 (if @move-down?
451 (.applyTorque control
452 (.mult (.getPhysicsRotation control)
453 (Vector3f. 0 0 -10))))
454 (if @move-left?
455 (.applyTorque control
456 (.mult (.getPhysicsRotation control)
457 (Vector3f. 0 10 0))))
458 (if @move-right?
459 (.applyTorque control
460 (.mult (.getPhysicsRotation control)
461 (Vector3f. 0 -10 0))))
462 (if @roll-left?
463 (.applyTorque control
464 (.mult (.getPhysicsRotation control)
465 (Vector3f. -1 0 0))))
466 (if @roll-right?
467 (.applyTorque control
468 (.mult (.getPhysicsRotation control)
469 (Vector3f. 1 0 0))))))))
470 #+end_src
473 * COMMENT purgatory
474 #+begin_src clojure
475 (defn bullet-trans []
476 (let [obj-a (sphere 0.5 :color ColorRGBA/Red
477 :position (Vector3f. -10 5 0))
478 obj-b (sphere 0.5 :color ColorRGBA/Blue
479 :position (Vector3f. -10 -5 0)
480 :mass 0)
481 control-a (.getControl obj-a RigidBodyControl)
482 control-b (.getControl obj-b RigidBodyControl)
483 swivel
484 (.toRotationMatrix
485 (doto (Quaternion.)
486 (.fromAngleAxis (/ Math/PI 2)
487 Vector3f/UNIT_X)))]
488 (doto
489 (ConeJoint.
490 control-a control-b
491 (Vector3f. 0 5 0)
492 (Vector3f. 0 -5 0)
493 swivel swivel)
494 (.setLimit (* 0.6 (/ Math/PI 4))
495 (/ Math/PI 4)
496 (* Math/PI 0.8)))
497 (world (nodify
498 [obj-a obj-b])
499 standard-debug-controls
500 enable-debug
501 no-op)))
504 (defn bullet-trans* []
505 (let [obj-a (box 1.5 0.5 0.5 :color ColorRGBA/Red
506 :position (Vector3f. 5 0 0)
507 :mass 90)
508 obj-b (sphere 0.5 :color ColorRGBA/Blue
509 :position (Vector3f. -5 0 0)
510 :mass 0)
511 control-a (.getControl obj-a RigidBodyControl)
512 control-b (.getControl obj-b RigidBodyControl)
513 move-up? (atom nil)
514 move-down? (atom nil)
515 move-left? (atom nil)
516 move-right? (atom nil)
517 roll-left? (atom nil)
518 roll-right? (atom nil)
519 force 100
520 swivel
521 (.toRotationMatrix
522 (doto (Quaternion.)
523 (.fromAngleAxis (/ Math/PI 2)
524 Vector3f/UNIT_X)))
525 x-move
526 (doto (Matrix3f.)
527 (.fromStartEndVectors Vector3f/UNIT_X
528 (.normalize (Vector3f. 1 1 0))))
530 timer (atom 0)]
531 (doto
532 (ConeJoint.
533 control-a control-b
534 (Vector3f. -8 0 0)
535 (Vector3f. 2 0 0)
536 ;;swivel swivel
537 ;;Matrix3f/IDENTITY Matrix3f/IDENTITY
538 x-move Matrix3f/IDENTITY
539 )
540 (.setCollisionBetweenLinkedBodys false)
541 (.setLimit (* 1 (/ Math/PI 4)) ;; twist
542 (* 1 (/ Math/PI 4)) ;; swing span in X-Y plane
543 (* 0 (/ Math/PI 4)))) ;; swing span in Y-Z plane
544 (world (nodify
545 [obj-a obj-b])
546 (merge standard-debug-controls
547 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
548 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
549 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
550 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
551 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
552 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
554 (fn [world]
555 (enable-debug world)
556 (set-gravity world Vector3f/ZERO)
557 )
559 (fn [world _]
561 (if @move-up?
562 (.applyForce control-a
563 (Vector3f. force 0 0)
564 (Vector3f. 0 0 0)))
565 (if @move-down?
566 (.applyForce control-a
567 (Vector3f. (- force) 0 0)
568 (Vector3f. 0 0 0)))
569 (if @move-left?
570 (.applyForce control-a
571 (Vector3f. 0 force 0)
572 (Vector3f. 0 0 0)))
573 (if @move-right?
574 (.applyForce control-a
575 (Vector3f. 0 (- force) 0)
576 (Vector3f. 0 0 0)))
578 (if @roll-left?
579 (.applyForce control-a
580 (Vector3f. 0 0 force)
581 (Vector3f. 0 0 0)))
582 (if @roll-right?
583 (.applyForce control-a
584 (Vector3f. 0 0 (- force))
585 (Vector3f. 0 0 0)))
587 (if (zero? (rem (swap! timer inc) 100))
588 (.attachChild
589 (.getRootNode world)
590 (sphere 0.05 :color ColorRGBA/Yellow
591 :physical? false :position
592 (.getWorldTranslation obj-a)))))
593 )
594 ))
598 #+end_src
601 * COMMENT generate source
602 #+begin_src clojure :tangle ../src/cortex/silly.clj
603 <<body-1>>
604 #+end_src