view org/body.org @ 136:47a4d74761f0

fixed some more problems with proprioception
author Robert McIntyre <rlm@mit.edu>
date Wed, 01 Feb 2012 17:39:23 -0700
parents 421cc43441ae
children 39c89ae5c7d0
line wrap: on
line source
1 #+title: The BODY!!!
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulating a body (movement, touch, propioception) in jMonkeyEngine3.
5 #+SETUPFILE: ../../aurellem/org/setup.org
6 #+INCLUDE: ../../aurellem/org/level-0.org
8 * Proprioception
9 #+name: proprioception
10 #+begin_src clojure
11 (ns cortex.body
12 (:use (cortex world util))
13 (:import
14 com.jme3.math.Vector3f
15 com.jme3.math.Quaternion
16 com.jme3.math.Vector2f
17 com.jme3.math.Matrix3f
18 com.jme3.bullet.control.RigidBodyControl
19 com.jme3.collision.CollisionResults
20 com.jme3.bounding.BoundingBox))
22 (import com.jme3.scene.Node)
24 (defn jme-to-blender
25 "Convert from JME coordinates to Blender coordinates"
26 [#^Vector3f in]
27 (Vector3f. (.getX in)
28 (- (.getZ in))
29 (.getY in)))
31 (defn joint-targets
32 "Return the two closest two objects to the joint object, ordered
33 from bottom to top according to the joint's rotation."
34 [#^Node parts #^Node joint]
35 (loop [radius (float 0.01)]
36 (let [results (CollisionResults.)]
37 (.collideWith
38 parts
39 (BoundingBox. (.getWorldTranslation joint)
40 radius radius radius)
41 results)
42 (let [targets
43 (distinct
44 (map #(.getGeometry %) results))]
45 (if (>= (count targets) 2)
46 (sort-by
47 #(let [v
48 (jme-to-blender
49 (.mult
50 (.inverse (.getWorldRotation joint))
51 (.subtract (.getWorldTranslation %)
52 (.getWorldTranslation joint))))]
53 (println-repl (.getName %) ":" v)
54 (.dot (Vector3f. 1 1 1)
55 v))
56 (take 2 targets))
57 (recur (float (* radius 2))))))))
59 (defn creature-joints
60 "Return the children of the creature's \"joints\" node."
61 [#^Node creature]
62 (if-let [joint-node (.getChild creature "joints")]
63 (seq (.getChildren joint-node))
64 (do (println-repl "could not find JOINTS node") [])))
66 (defn joint-proprioception [#^Node parts #^Node joint]
67 (let [[obj-a obj-b] (joint-targets parts joint)
68 joint-rot (.getWorldRotation joint)
69 x (.mult joint-rot Vector3f/UNIT_X)
70 y (.mult joint-rot Vector3f/UNIT_Y)
71 z (.mult joint-rot Vector3f/UNIT_Z)]
72 ;; this function will report proprioceptive information for the
73 ;; joint.
74 (fn []
75 ;; x is the "twist" axis, y and z are the "bend" axes
76 (let [rot-a (.getWorldRotation obj-a)
77 ;;inv-a (.inverse rot-a)
78 rot-b (.getWorldRotation obj-b)
79 ;;relative (.mult rot-b inv-a)
80 basis (doto (Matrix3f.)
81 (.setColumn 0 (.mult rot-a x))
82 (.setColumn 1 (.mult rot-a y))
83 (.setColumn 2 (.mult rot-a z)))
84 rotation-about-joint
85 (doto (Quaternion.)
86 (.fromRotationMatrix
87 (.mult (.invert basis)
88 (.toRotationMatrix rot-b))))
89 [yaw roll pitch]
90 (seq (.toAngles rotation-about-joint nil))]
91 ;;return euler angles of the quaternion around the new basis
92 [yaw roll pitch]
93 ))))
96 (defn proprioception
97 "Create a function that provides proprioceptive information about an
98 entire body."
99 [#^Node creature]
100 ;; extract the body's joints
101 (let [joints (creature-joints creature)
102 senses (map (partial joint-proprioception creature) joints)]
103 (fn []
104 (map #(%) senses))))
106 #+end_src
108 #+results: proprioception
109 : #'cortex.body/proprioception
111 * Motor Control
112 #+name: motor-control
113 #+begin_src clojure
114 (in-ns 'cortex.body)
116 ;; surprisingly enough, terristerial creatures only move by using
117 ;; torque applied about their joints. There's not a single straight
118 ;; line of force in the human body at all! (A straight line of force
119 ;; would correspond to some sort of jet or rocket propulseion.)
121 (defn vector-motor-control
122 "Create a function that accepts a sequence of Vector3f objects that
123 describe the torque to be applied to each part of the body."
124 [body]
125 (let [nodes (node-seq body)
126 controls (keep #(.getControl % RigidBodyControl) nodes)]
127 (fn [torques]
128 (map #(.applyTorque %1 %2)
129 controls torques))))
130 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
131 #+end_src
133 ## note -- might want to add a lower dimensional, discrete version of
134 ## this if it proves useful from a x-modal clustering perspective.
136 * Examples
138 #+name: test-body
139 #+begin_src clojure
140 (ns cortex.test.body
141 (:use (cortex world util body))
142 (:require cortex.silly)
143 (:import
144 com.jme3.math.Vector3f
145 com.jme3.math.ColorRGBA
146 com.jme3.bullet.joints.Point2PointJoint
147 com.jme3.bullet.control.RigidBodyControl
148 com.jme3.system.NanoTimer))
150 (defn worm-segments
151 "Create multiple evenly spaced box segments. They're fabulous!"
152 [segment-length num-segments interstitial-space radius]
153 (letfn [(nth-segment
154 [n]
155 (box segment-length radius radius :mass 0.1
156 :position
157 (Vector3f.
158 (* 2 n (+ interstitial-space segment-length)) 0 0)
159 :name (str "worm-segment" n)
160 :color (ColorRGBA/randomColor)))]
161 (map nth-segment (range num-segments))))
163 (defn connect-at-midpoint
164 "Connect two physics objects with a Point2Point joint constraint at
165 the point equidistant from both objects' centers."
166 [segmentA segmentB]
167 (let [centerA (.getWorldTranslation segmentA)
168 centerB (.getWorldTranslation segmentB)
169 midpoint (.mult (.add centerA centerB) (float 0.5))
170 pivotA (.subtract midpoint centerA)
171 pivotB (.subtract midpoint centerB)
173 ;; A side-effect of creating a joint registers
174 ;; it with both physics objects which in turn
175 ;; will register the joint with the physics system
176 ;; when the simulation is started.
177 joint (Point2PointJoint.
178 (.getControl segmentA RigidBodyControl)
179 (.getControl segmentB RigidBodyControl)
180 pivotA
181 pivotB)]
182 segmentB))
184 (defn eve-worm
185 "Create a worm-like body bound by invisible joint constraints."
186 []
187 (let [segments (worm-segments 0.2 5 0.1 0.1)]
188 (dorun (map (partial apply connect-at-midpoint)
189 (partition 2 1 segments)))
190 (nodify "worm" segments)))
192 (defn worm-pattern
193 "This is a simple, mindless motor control pattern that drives the
194 second segment of the worm's body at an offset angle with
195 sinusoidally varying strength."
196 [time]
197 (let [angle (* Math/PI (/ 9 20))
198 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]
199 [Vector3f/ZERO
200 (.mult
201 direction
202 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))
203 Vector3f/ZERO
204 Vector3f/ZERO
205 Vector3f/ZERO]))
207 (defn test-motor-control
208 "Testing motor-control:
209 You should see a multi-segmented worm-like object fall onto the
210 table and begin writhing and moving."
211 []
212 (let [worm (eve-worm)
213 time (atom 0)
214 worm-motor-map (vector-motor-control worm)]
215 (world
216 (nodify [worm
217 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
218 :color ColorRGBA/Gray)])
219 standard-debug-controls
220 (fn [world]
221 (enable-debug world)
222 (light-up-everything world)
223 (comment
224 (com.aurellem.capture.Capture/captureVideo
225 world
226 (file-str "/home/r/proj/cortex/tmp/moving-worm")))
227 )
229 (fn [_ _]
230 (swap! time inc)
231 (Thread/sleep 20)
232 (dorun (worm-motor-map
233 (worm-pattern @time)))))))
237 (defn join-at-point [obj-a obj-b world-pivot]
238 (cortex.silly/joint-dispatch
239 {:type :point}
240 (.getControl obj-a RigidBodyControl)
241 (.getControl obj-b RigidBodyControl)
242 (cortex.silly/world-to-local obj-a world-pivot)
243 (cortex.silly/world-to-local obj-b world-pivot)
244 nil
245 ))
247 (import com.jme3.bullet.collision.PhysicsCollisionObject)
249 (defn blab-* []
250 (let [hand (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)
251 :mass 0 :color ColorRGBA/Green)
252 finger (box 0.5 0.2 0.2 :position (Vector3f. 2.4 0 0)
253 :mass 1 :color ColorRGBA/Red)
254 connection-point (Vector3f. 1.2 0 0)
255 root (nodify [hand finger])]
257 (join-at-point hand finger (Vector3f. 1.2 0 0))
259 (.setCollisionGroup
260 (.getControl hand RigidBodyControl)
261 PhysicsCollisionObject/COLLISION_GROUP_NONE)
262 (world
263 root
264 standard-debug-controls
265 (fn [world]
266 (enable-debug world)
267 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
268 (set-gravity world Vector3f/ZERO)
269 )
270 no-op)))
271 (import java.awt.image.BufferedImage)
273 (defn draw-sprite [image sprite x y color ]
274 (dorun
275 (for [[u v] sprite]
276 (.setRGB image (+ u x) (+ v y) color))))
278 (defn view-angle
279 "create a debug view of an angle"
280 [color]
281 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)
282 previous (atom [25 25])
283 sprite [[0 0] [0 1]
284 [0 -1] [-1 0] [1 0]]]
285 (fn [angle]
286 (let [angle (float angle)]
287 (let [position
288 [(+ 25 (int (* 20 (Math/cos angle))))
289 (+ 25 (int (* 20(Math/sin angle))))]]
290 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)
291 (draw-sprite image sprite (position 0) (position 1) color)
292 (reset! previous position))
293 image))))
295 (defn proprioception-debug-window
296 []
297 (let [yaw (view-angle 0xFF0000)
298 roll (view-angle 0x00FF00)
299 pitch (view-angle 0xFFFFFF)
300 v-yaw (view-image)
301 v-roll (view-image)
302 v-pitch (view-image)
303 ]
304 (fn [prop-data]
305 (dorun
306 (map
307 (fn [[y r p]]
308 (v-yaw (yaw y))
309 (v-roll (roll r))
310 (v-pitch (pitch p)))
311 prop-data)))))
312 (comment
314 (defn proprioception-debug-window
315 []
316 (let [time (atom 0)]
317 (fn [prop-data]
318 (if (= 0 (rem (swap! time inc) 40))
319 (println-repl prop-data)))))
320 )
322 (comment
323 (dorun
324 (map
325 (comp
326 println-repl
327 (fn [[p y r]]
328 (format
329 "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
330 p y r)))
331 prop-data)))
335 (defn tap [obj direction force]
336 (let [control (.getControl obj RigidBodyControl)]
337 (.applyTorque
338 control
339 (.mult (.getPhysicsRotation control)
340 (.mult (.normalize direction) (float force))))))
344 (defn test-proprioception
345 "Testing proprioception:
346 You should see two foating bars, and a printout of pitch, yaw, and
347 roll. Pressing key-r/key-t should move the blue bar up and down and
348 change only the value of pitch. key-f/key-g moves it side to side
349 and changes yaw. key-v/key-b will spin the blue segment clockwise
350 and counterclockwise, and only affect roll."
351 []
352 (let [hand (box 1 0.2 0.2 :position (Vector3f. 0 2 0)
353 :mass 0 :color ColorRGBA/Green :name "hand")
354 finger (box 1 0.2 0.2 :position (Vector3f. 2.4 2 0)
355 :mass 1 :color ColorRGBA/Red :name "finger")
356 joint-node (box 0.1 0.05 0.05 :color ColorRGBA/Yellow
357 :position (Vector3f. 1.2 2 0)
358 :physical? false)
359 joint (join-at-point hand finger (Vector3f. 1.2 2 0 ))
360 creature (nodify [hand finger joint-node])
361 ;; *******************************************
362 rot (doto (Quaternion.)
363 (.fromAngleAxis (/ Math/PI 4)
364 (Vector3f. 0 0 -1)))
365 hand2 (box 1 0.2 0.2 :position (Vector3f. 0 1.5 -3)
366 :mass 0 :color ColorRGBA/Blue :rotation rot)
367 finger2 (box 1 0.2 0.2 :position (Vector3f. 2.4 1.5 -3)
368 :mass 1 :color ColorRGBA/Magenta :rotation rot)
369 joint-node2 (box 0.1 0.05 0.05 :color ColorRGBA/Gray
370 :position (Vector3f. 1.2 1.5 -3)
371 :physical? false :rotation rot)
372 joint2 (join-at-point hand2 finger2 (Vector3f. 1.2 1.5 -3))
373 creature2 (nodify [hand2 finger2 joint-node2])
374 ;; *******************************************
376 floor (box 10 10 10 :position (Vector3f. 0 -15 0)
377 :mass 0 :color ColorRGBA/Gray)
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)
387 root (nodify [creature creature2 floor])
388 prop (joint-proprioception creature joint-node)
389 prop-view (proprioception-debug-window)]
393 (.setCollisionGroup
394 (.getControl hand RigidBodyControl)
395 PhysicsCollisionObject/COLLISION_GROUP_NONE)
396 (.setCollisionGroup
397 (.getControl hand2 RigidBodyControl)
398 PhysicsCollisionObject/COLLISION_GROUP_NONE)
403 (world
404 root
405 (merge standard-debug-controls
406 {"key-r" (fn [_ pressed?] (reset! move-up? pressed?))
407 "key-t" (fn [_ pressed?] (reset! move-down? pressed?))
408 "key-f" (fn [_ pressed?] (reset! move-left? pressed?))
409 "key-g" (fn [_ pressed?] (reset! move-right? pressed?))
410 "key-v" (fn [_ pressed?] (reset! roll-left? pressed?))
411 "key-b" (fn [_ pressed?] (reset! roll-right? pressed?))})
412 (fn [world]
413 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
414 (set-gravity world (Vector3f. 0 0 0))
415 (light-up-everything world))
416 (fn [_ _]
417 (let [force 10
418 left (Vector3f. 0 1 0)
419 right (Vector3f. 0 -1 0)
420 up (Vector3f. 0 0 1)
421 down (Vector3f. 0 0 -1)
422 roll-left (Vector3f. -1 0 0)
423 roll-right (Vector3f. 1 0 0)]
424 (if @move-up? (do (tap finger up force)
425 (tap finger2 up force)))
426 (if @move-down? (do (tap finger down force)
427 (tap finger2 down force)))
428 (if @move-left? (do (tap finger left force)
429 (tap finger2 left force)))
430 (if @move-right? (do (tap finger right force)
431 (tap finger2 right force)))
432 (if @roll-left? (do (tap finger roll-left (/ force 10))
433 (tap finger2 roll-left (/ force 10))))
434 (if @roll-right? (do (tap finger roll-right (/ force 10))
435 (tap finger2 roll-right (/ force 10)))))
436 (prop-view (list (prop)))))))
438 #+end_src
440 #+results: test-body
441 : #'cortex.test.body/test-proprioception
444 * COMMENT code-limbo
445 #+begin_src clojure
446 ;;(.loadModel
447 ;; (doto (asset-manager)
448 ;; (.registerLoader BlenderModelLoader (into-array String ["blend"])))
449 ;; "Models/person/person.blend")
452 (defn load-blender-model
453 "Load a .blend file using an asset folder relative path."
454 [^String model]
455 (.loadModel
456 (doto (asset-manager)
457 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
458 model))
461 (defn view-model [^String model]
462 (view
463 (.loadModel
464 (doto (asset-manager)
465 (.registerLoader BlenderModelLoader (into-array String ["blend"])))
466 model)))
468 (defn load-blender-scene [^String model]
469 (.loadModel
470 (doto (asset-manager)
471 (.registerLoader BlenderLoader (into-array String ["blend"])))
472 model))
474 (defn worm
475 []
476 (.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml"))
478 (defn oto
479 []
480 (.loadModel (asset-manager) "Models/Oto/Oto.mesh.xml"))
482 (defn sinbad
483 []
484 (.loadModel (asset-manager) "Models/Sinbad/Sinbad.mesh.xml"))
486 (defn worm-blender
487 []
488 (first (seq (.getChildren (load-blender-model
489 "Models/anim2/simple-worm.blend")))))
491 (defn body
492 "given a node with a SkeletonControl, will produce a body sutiable
493 for AI control with movement and proprioception."
494 [node]
495 (let [skeleton-control (.getControl node SkeletonControl)
496 krc (KinematicRagdollControl.)]
497 (comment
498 (dorun
499 (map #(.addBoneName krc %)
500 ["mid2" "tail" "head" "mid1" "mid3" "mid4" "Dummy-Root" ""]
501 ;;"mid2" "mid3" "tail" "head"]
502 )))
503 (.addControl node krc)
504 (.setRagdollMode krc)
505 )
506 node
507 )
508 (defn show-skeleton [node]
509 (let [sd
511 (doto
512 (SkeletonDebugger. "aurellem-skel-debug"
513 (skel node))
514 (.setMaterial (green-x-ray)))]
515 (.attachChild node sd)
516 node))
520 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
522 ;; this could be a good way to give objects special properties like
523 ;; being eyes and the like
525 (.getUserData
526 (.getChild
527 (load-blender-model "Models/property/test.blend") 0)
528 "properties")
530 ;; the properties are saved along with the blender file.
531 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
536 (defn init-debug-skel-node
537 [f debug-node skeleton]
538 (let [bones
539 (map #(.getBone skeleton %)
540 (range (.getBoneCount skeleton)))]
541 (dorun (map #(.setUserControl % true) bones))
542 (dorun (map (fn [b]
543 (println (.getName b)
544 " -- " (f b)))
545 bones))
546 (dorun
547 (map #(.attachChild
548 debug-node
549 (doto
550 (sphere 0.1
551 :position (f %)
552 :physical? false)
553 (.setMaterial (green-x-ray))))
554 bones)))
555 debug-node)
557 (import jme3test.bullet.PhysicsTestHelper)
560 (defn test-zzz [the-worm world value]
561 (if (not value)
562 (let [skeleton (skel the-worm)]
563 (println-repl "enabling bones")
564 (dorun
565 (map
566 #(.setUserControl (.getBone skeleton %) true)
567 (range (.getBoneCount skeleton))))
570 (let [b (.getBone skeleton 2)]
571 (println-repl "moving " (.getName b))
572 (println-repl (.getLocalPosition b))
573 (.setUserTransforms b
574 Vector3f/UNIT_X
575 Quaternion/IDENTITY
576 ;;(doto (Quaternion.)
577 ;; (.fromAngles (/ Math/PI 2)
578 ;; 0
579 ;; 0
581 (Vector3f. 1 1 1))
582 )
584 (println-repl "hi! <3"))))
587 (defn test-ragdoll []
589 (let [the-worm
591 ;;(.loadModel (asset-manager) "Models/anim2/Cube.mesh.xml")
592 (doto (show-skeleton (worm-blender))
593 (.setLocalTranslation (Vector3f. 0 10 0))
594 ;;(worm)
595 ;;(oto)
596 ;;(sinbad)
597 )
598 ]
601 (.start
602 (world
603 (doto (Node.)
604 (.attachChild the-worm))
605 {"key-return" (fire-cannon-ball)
606 "key-space" (partial test-zzz the-worm)
607 }
608 (fn [world]
609 (light-up-everything world)
610 (PhysicsTestHelper/createPhysicsTestWorld
611 (.getRootNode world)
612 (asset-manager)
613 (.getPhysicsSpace
614 (.getState (.getStateManager world) BulletAppState)))
615 (set-gravity world Vector3f/ZERO)
616 ;;(.setTimer world (NanoTimer.))
617 ;;(org.lwjgl.input.Mouse/setGrabbed false)
618 )
619 no-op
620 )
623 )))
626 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
627 ;;; here is the ragdoll stuff
629 (def worm-mesh (.getMesh (.getChild (worm-blender) 0)))
630 (def mesh worm-mesh)
632 (.getFloatBuffer mesh VertexBuffer$Type/Position)
633 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
634 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
637 (defn position [index]
638 (.get
639 (.getFloatBuffer worm-mesh VertexBuffer$Type/Position)
640 index))
642 (defn bones [index]
643 (.get
644 (.getData (.getBuffer mesh VertexBuffer$Type/BoneIndex))
645 index))
647 (defn bone-weights [index]
648 (.get
649 (.getFloatBuffer mesh VertexBuffer$Type/BoneWeight)
650 index))
654 (defn vertex-bones [vertex]
655 (vec (map (comp int bones) (range (* vertex 4) (+ (* vertex 4) 4)))))
657 (defn vertex-weights [vertex]
658 (vec (map (comp float bone-weights) (range (* vertex 4) (+ (* vertex 4) 4)))))
660 (defn vertex-position [index]
661 (let [offset (* index 3)]
662 (Vector3f. (position offset)
663 (position (inc offset))
664 (position (inc(inc offset))))))
666 (def vertex-info (juxt vertex-position vertex-bones vertex-weights))
668 (defn bone-control-color [index]
669 (get {[1 0 0 0] ColorRGBA/Red
670 [1 2 0 0] ColorRGBA/Magenta
671 [2 0 0 0] ColorRGBA/Blue}
672 (vertex-bones index)
673 ColorRGBA/White))
675 (defn influence-color [index bone-num]
676 (get
677 {(float 0) ColorRGBA/Blue
678 (float 0.5) ColorRGBA/Green
679 (float 1) ColorRGBA/Red}
680 ;; find the weight of the desired bone
681 ((zipmap (vertex-bones index)(vertex-weights index))
682 bone-num)
683 ColorRGBA/Blue))
685 (def worm-vertices (set (map vertex-info (range 60))))
688 (defn test-info []
689 (let [points (Node.)]
690 (dorun
691 (map #(.attachChild points %)
692 (map #(sphere 0.01
693 :position (vertex-position %)
694 :color (influence-color % 1)
695 :physical? false)
696 (range 60))))
697 (view points)))
700 (defrecord JointControl [joint physics-space]
701 PhysicsControl
702 (setPhysicsSpace [this space]
703 (dosync
704 (ref-set (:physics-space this) space))
705 (.addJoint space (:joint this)))
706 (update [this tpf])
707 (setSpatial [this spatial])
708 (render [this rm vp])
709 (getPhysicsSpace [this] (deref (:physics-space this)))
710 (isEnabled [this] true)
711 (setEnabled [this state]))
713 (defn add-joint
714 "Add a joint to a particular object. When the object is added to the
715 PhysicsSpace of a simulation, the joint will also be added"
716 [object joint]
717 (let [control (JointControl. joint (ref nil))]
718 (.addControl object control))
719 object)
722 (defn hinge-world
723 []
724 (let [sphere1 (sphere)
725 sphere2 (sphere 1 :position (Vector3f. 3 3 3))
726 joint (Point2PointJoint.
727 (.getControl sphere1 RigidBodyControl)
728 (.getControl sphere2 RigidBodyControl)
729 Vector3f/ZERO (Vector3f. 3 3 3))]
730 (add-joint sphere1 joint)
731 (doto (Node. "hinge-world")
732 (.attachChild sphere1)
733 (.attachChild sphere2))))
736 (defn test-joint []
737 (view (hinge-world)))
739 ;; (defn copier-gen []
740 ;; (let [count (atom 0)]
741 ;; (fn [in]
742 ;; (swap! count inc)
743 ;; (clojure.contrib.duck-streams/copy
744 ;; in (File. (str "/home/r/tmp/mao-test/clojure-images/"
745 ;; ;;/home/r/tmp/mao-test/clojure-images
746 ;; (format "%08d.png" @count)))))))
747 ;; (defn decrease-framerate []
748 ;; (map
749 ;; (copier-gen)
750 ;; (sort
751 ;; (map first
752 ;; (partition
753 ;; 4
754 ;; (filter #(re-matches #".*.png$" (.getCanonicalPath %))
755 ;; (file-seq
756 ;; (file-str
757 ;; "/home/r/media/anime/mao-temp/images"))))))))
761 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
763 (defn proprioception
764 "Create a proprioception map that reports the rotations of the
765 various limbs of the creature's body"
766 [creature]
767 [#^Node creature]
768 (let [
769 nodes (node-seq creature)
770 joints
771 (map
772 :joint
773 (filter
774 #(isa? (class %) JointControl)
775 (reduce
776 concat
777 (map (fn [node]
778 (map (fn [num] (.getControl node num))
779 (range (.getNumControls node))))
780 nodes))))]
781 (fn []
782 (reduce concat (map relative-positions (list (first joints)))))))
785 (defn skel [node]
786 (doto
787 (.getSkeleton
788 (.getControl node SkeletonControl))
789 ;; this is necessary to force the skeleton to have accurate world
790 ;; transforms before it is rendered to the screen.
791 (.resetAndUpdate)))
793 (defn green-x-ray []
794 (doto (Material. (asset-manager)
795 "Common/MatDefs/Misc/Unshaded.j3md")
796 (.setColor "Color" ColorRGBA/Green)
797 (-> (.getAdditionalRenderState)
798 (.setDepthTest false))))
800 (defn test-worm []
801 (.start
802 (world
803 (doto (Node.)
804 ;;(.attachChild (point-worm))
805 (.attachChild (load-blender-model
806 "Models/anim2/joint-worm.blend"))
808 (.attachChild (box 10 1 10
809 :position (Vector3f. 0 -2 0) :mass 0
810 :color (ColorRGBA/Gray))))
811 {
812 "key-space" (fire-cannon-ball)
813 }
814 (fn [world]
815 (enable-debug world)
816 (light-up-everything world)
817 ;;(.setTimer world (NanoTimer.))
818 )
819 no-op)))
823 ;; defunct movement stuff
824 (defn torque-controls [control]
825 (let [torques
826 (concat
827 (map #(Vector3f. 0 (Math/sin %) (Math/cos %))
828 (range 0 (* Math/PI 2) (/ (* Math/PI 2) 20)))
829 [Vector3f/UNIT_X])]
830 (map (fn [torque-axis]
831 (fn [torque]
832 (.applyTorque
833 control
834 (.mult (.mult (.getPhysicsRotation control)
835 torque-axis)
836 (float
837 (* (.getMass control) torque))))))
838 torques)))
840 (defn motor-map
841 "Take a creature and generate a function that will enable fine
842 grained control over all the creature's limbs."
843 [#^Node creature]
844 (let [controls (keep #(.getControl % RigidBodyControl)
845 (node-seq creature))
846 limb-controls (reduce concat (map torque-controls controls))
847 body-control (partial map #(%1 %2) limb-controls)]
848 body-control))
850 (defn test-motor-map
851 "see how torque works."
852 []
853 (let [finger (box 3 0.5 0.5 :position (Vector3f. 0 2 0)
854 :mass 1 :color ColorRGBA/Green)
855 motor-map (motor-map finger)]
856 (world
857 (nodify [finger
858 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
859 :color ColorRGBA/Gray)])
860 standard-debug-controls
861 (fn [world]
862 (set-gravity world Vector3f/ZERO)
863 (light-up-everything world)
864 (.setTimer world (NanoTimer.)))
865 (fn [_ _]
866 (dorun (motor-map [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]))))))
867 #+end_src
875 * COMMENT generate Source
876 #+begin_src clojure :tangle ../src/cortex/body.clj
877 <<proprioception>>
878 <<motor-control>>
879 #+end_src
881 #+begin_src clojure :tangle ../src/cortex/test/body.clj
882 <<test-body>>
883 #+end_src