comparison org/body.org @ 141:22e193b5c60f

moved with-movement to cortex.body
author Robert McIntyre <rlm@mit.edu>
date Thu, 02 Feb 2012 01:35:21 -0700
parents 22444eb20ecc
children ccd057319c2a
comparison
equal deleted inserted replaced
140:22444eb20ecc 141:22e193b5c60f
104 ;; extract the body's joints 104 ;; extract the body's joints
105 (let [joints (creature-joints creature) 105 (let [joints (creature-joints creature)
106 senses (map (partial joint-proprioception creature) joints)] 106 senses (map (partial joint-proprioception creature) joints)]
107 (fn [] 107 (fn []
108 (map #(%) senses)))) 108 (map #(%) senses))))
109
110 #+end_src
111
112 #+results: proprioception
113 : #'cortex.body/proprioception
114
115 * Motor Control
116 #+name: motor-control
117 #+begin_src clojure
118 (in-ns 'cortex.body)
119
120 ;; surprisingly enough, terristerial creatures only move by using
121 ;; torque applied about their joints. There's not a single straight
122 ;; line of force in the human body at all! (A straight line of force
123 ;; would correspond to some sort of jet or rocket propulseion.)
124
125 (defn vector-motor-control
126 "Create a function that accepts a sequence of Vector3f objects that
127 describe the torque to be applied to each part of the body."
128 [body]
129 (let [nodes (node-seq body)
130 controls (keep #(.getControl % RigidBodyControl) nodes)]
131 (fn [torques]
132 (map #(.applyTorque %1 %2)
133 controls torques))))
134 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
135 #+end_src
136
137 ## note -- might want to add a lower dimensional, discrete version of
138 ## this if it proves useful from a x-modal clustering perspective.
139
140 * Examples
141
142 #+name: test-body
143 #+begin_src clojure
144 (ns cortex.test.body
145 (:use (cortex world util body))
146 (:require cortex.silly)
147 (:import
148 com.jme3.math.Vector3f
149 com.jme3.math.ColorRGBA
150 com.jme3.bullet.joints.Point2PointJoint
151 com.jme3.bullet.control.RigidBodyControl
152 com.jme3.system.NanoTimer))
153
154 (defn worm-segments
155 "Create multiple evenly spaced box segments. They're fabulous!"
156 [segment-length num-segments interstitial-space radius]
157 (letfn [(nth-segment
158 [n]
159 (box segment-length radius radius :mass 0.1
160 :position
161 (Vector3f.
162 (* 2 n (+ interstitial-space segment-length)) 0 0)
163 :name (str "worm-segment" n)
164 :color (ColorRGBA/randomColor)))]
165 (map nth-segment (range num-segments))))
166
167 (defn connect-at-midpoint
168 "Connect two physics objects with a Point2Point joint constraint at
169 the point equidistant from both objects' centers."
170 [segmentA segmentB]
171 (let [centerA (.getWorldTranslation segmentA)
172 centerB (.getWorldTranslation segmentB)
173 midpoint (.mult (.add centerA centerB) (float 0.5))
174 pivotA (.subtract midpoint centerA)
175 pivotB (.subtract midpoint centerB)
176
177 ;; A side-effect of creating a joint registers
178 ;; it with both physics objects which in turn
179 ;; will register the joint with the physics system
180 ;; when the simulation is started.
181 joint (Point2PointJoint.
182 (.getControl segmentA RigidBodyControl)
183 (.getControl segmentB RigidBodyControl)
184 pivotA
185 pivotB)]
186 segmentB))
187
188 (defn eve-worm
189 "Create a worm-like body bound by invisible joint constraints."
190 []
191 (let [segments (worm-segments 0.2 5 0.1 0.1)]
192 (dorun (map (partial apply connect-at-midpoint)
193 (partition 2 1 segments)))
194 (nodify "worm" segments)))
195
196 (defn worm-pattern
197 "This is a simple, mindless motor control pattern that drives the
198 second segment of the worm's body at an offset angle with
199 sinusoidally varying strength."
200 [time]
201 (let [angle (* Math/PI (/ 9 20))
202 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]
203 [Vector3f/ZERO
204 (.mult
205 direction
206 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))
207 Vector3f/ZERO
208 Vector3f/ZERO
209 Vector3f/ZERO]))
210
211 (defn test-motor-control
212 "Testing motor-control:
213 You should see a multi-segmented worm-like object fall onto the
214 table and begin writhing and moving."
215 []
216 (let [worm (eve-worm)
217 time (atom 0)
218 worm-motor-map (vector-motor-control worm)]
219 (world
220 (nodify [worm
221 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
222 :color ColorRGBA/Gray)])
223 standard-debug-controls
224 (fn [world]
225 (enable-debug world)
226 (light-up-everything world)
227 (comment
228 (com.aurellem.capture.Capture/captureVideo
229 world
230 (file-str "/home/r/proj/cortex/tmp/moving-worm")))
231 )
232
233 (fn [_ _]
234 (swap! time inc)
235 (Thread/sleep 20)
236 (dorun (worm-motor-map
237 (worm-pattern @time)))))))
238
239
240
241 (defn join-at-point [obj-a obj-b world-pivot]
242 (cortex.silly/joint-dispatch
243 {:type :point}
244 (.getControl obj-a RigidBodyControl)
245 (.getControl obj-b RigidBodyControl)
246 (cortex.silly/world-to-local obj-a world-pivot)
247 (cortex.silly/world-to-local obj-b world-pivot)
248 nil
249 ))
250
251 (import com.jme3.bullet.collision.PhysicsCollisionObject)
252
253 (defn blab-* []
254 (let [hand (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)
255 :mass 0 :color ColorRGBA/Green)
256 finger (box 0.5 0.2 0.2 :position (Vector3f. 2.4 0 0)
257 :mass 1 :color ColorRGBA/Red)
258 connection-point (Vector3f. 1.2 0 0)
259 root (nodify [hand finger])]
260
261 (join-at-point hand finger (Vector3f. 1.2 0 0))
262
263 (.setCollisionGroup
264 (.getControl hand RigidBodyControl)
265 PhysicsCollisionObject/COLLISION_GROUP_NONE)
266 (world
267 root
268 standard-debug-controls
269 (fn [world]
270 (enable-debug world)
271 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
272 (set-gravity world Vector3f/ZERO)
273 )
274 no-op)))
275 (import java.awt.image.BufferedImage)
276
277 (defn draw-sprite [image sprite x y color ]
278 (dorun
279 (for [[u v] sprite]
280 (.setRGB image (+ u x) (+ v y) color))))
281
282 (defn view-angle
283 "create a debug view of an angle"
284 [color]
285 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)
286 previous (atom [25 25])
287 sprite [[0 0] [0 1]
288 [0 -1] [-1 0] [1 0]]]
289 (fn [angle]
290 (let [angle (float angle)]
291 (let [position
292 [(+ 25 (int (* 20 (Math/cos angle))))
293 (+ 25 (int (* 20(Math/sin angle))))]]
294 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)
295 (draw-sprite image sprite (position 0) (position 1) color)
296 (reset! previous position))
297 image))))
298
299 (defn proprioception-debug-window
300 []
301 (let [yaw (view-angle 0xFF0000)
302 roll (view-angle 0x00FF00)
303 pitch (view-angle 0xFFFFFF)
304 v-yaw (view-image)
305 v-roll (view-image)
306 v-pitch (view-image)
307 ]
308 (fn [prop-data]
309 (dorun
310 (map
311 (fn [[y r p]]
312 (v-yaw (yaw y))
313 (v-roll (roll r))
314 (v-pitch (pitch p)))
315 prop-data)))))
316 (comment
317
318 (defn proprioception-debug-window
319 []
320 (let [time (atom 0)]
321 (fn [prop-data]
322 (if (= 0 (rem (swap! time inc) 40))
323 (println-repl prop-data)))))
324 )
325
326 (comment
327 (dorun
328 (map
329 (comp
330 println-repl
331 (fn [[p y r]]
332 (format
333 "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
334 p y r)))
335 prop-data)))
336
337
338 109
339 (defn tap [obj direction force] 110 (defn tap [obj direction force]
340 (let [control (.getControl obj RigidBodyControl)] 111 (let [control (.getControl obj RigidBodyControl)]
341 (.applyTorque 112 (.applyTorque
342 control 113 control
343 (.mult (.getPhysicsRotation control) 114 (.mult (.getPhysicsRotation control)
344 (.mult (.normalize direction) (float force)))))) 115 (.mult (.normalize direction) (float force))))))
345
346 116
347 117
348 (defn with-movement 118 (defn with-movement
349 [object 119 [object
350 [up down left right roll-up roll-down :as keyboard] 120 [up down left right roll-up roll-down :as keyboard]
391 161
392 [root-node 162 [root-node
393 keymap* 163 keymap*
394 intilization 164 intilization
395 world-loop*])) 165 world-loop*]))
166
167
168 #+end_src
169
170 #+results: proprioception
171 : #'cortex.body/proprioception
172
173 * Motor Control
174 #+name: motor-control
175 #+begin_src clojure
176 (in-ns 'cortex.body)
177
178 ;; surprisingly enough, terristerial creatures only move by using
179 ;; torque applied about their joints. There's not a single straight
180 ;; line of force in the human body at all! (A straight line of force
181 ;; would correspond to some sort of jet or rocket propulseion.)
182
183 (defn vector-motor-control
184 "Create a function that accepts a sequence of Vector3f objects that
185 describe the torque to be applied to each part of the body."
186 [body]
187 (let [nodes (node-seq body)
188 controls (keep #(.getControl % RigidBodyControl) nodes)]
189 (fn [torques]
190 (map #(.applyTorque %1 %2)
191 controls torques))))
192 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
193 #+end_src
194
195 ## note -- might want to add a lower dimensional, discrete version of
196 ## this if it proves useful from a x-modal clustering perspective.
197
198 * Examples
199
200 #+name: test-body
201 #+begin_src clojure
202 (ns cortex.test.body
203 (:use (cortex world util body))
204 (:require cortex.silly)
205 (:import
206 com.jme3.math.Vector3f
207 com.jme3.math.ColorRGBA
208 com.jme3.bullet.joints.Point2PointJoint
209 com.jme3.bullet.control.RigidBodyControl
210 com.jme3.system.NanoTimer))
211
212 (defn worm-segments
213 "Create multiple evenly spaced box segments. They're fabulous!"
214 [segment-length num-segments interstitial-space radius]
215 (letfn [(nth-segment
216 [n]
217 (box segment-length radius radius :mass 0.1
218 :position
219 (Vector3f.
220 (* 2 n (+ interstitial-space segment-length)) 0 0)
221 :name (str "worm-segment" n)
222 :color (ColorRGBA/randomColor)))]
223 (map nth-segment (range num-segments))))
224
225 (defn connect-at-midpoint
226 "Connect two physics objects with a Point2Point joint constraint at
227 the point equidistant from both objects' centers."
228 [segmentA segmentB]
229 (let [centerA (.getWorldTranslation segmentA)
230 centerB (.getWorldTranslation segmentB)
231 midpoint (.mult (.add centerA centerB) (float 0.5))
232 pivotA (.subtract midpoint centerA)
233 pivotB (.subtract midpoint centerB)
234
235 ;; A side-effect of creating a joint registers
236 ;; it with both physics objects which in turn
237 ;; will register the joint with the physics system
238 ;; when the simulation is started.
239 joint (Point2PointJoint.
240 (.getControl segmentA RigidBodyControl)
241 (.getControl segmentB RigidBodyControl)
242 pivotA
243 pivotB)]
244 segmentB))
245
246 (defn eve-worm
247 "Create a worm-like body bound by invisible joint constraints."
248 []
249 (let [segments (worm-segments 0.2 5 0.1 0.1)]
250 (dorun (map (partial apply connect-at-midpoint)
251 (partition 2 1 segments)))
252 (nodify "worm" segments)))
253
254 (defn worm-pattern
255 "This is a simple, mindless motor control pattern that drives the
256 second segment of the worm's body at an offset angle with
257 sinusoidally varying strength."
258 [time]
259 (let [angle (* Math/PI (/ 9 20))
260 direction (Vector3f. 0 (Math/sin angle) (Math/cos angle))]
261 [Vector3f/ZERO
262 (.mult
263 direction
264 (float (* 2 (Math/sin (* Math/PI 2 (/ (rem time 300 ) 300))))))
265 Vector3f/ZERO
266 Vector3f/ZERO
267 Vector3f/ZERO]))
268
269 (defn test-motor-control
270 "Testing motor-control:
271 You should see a multi-segmented worm-like object fall onto the
272 table and begin writhing and moving."
273 []
274 (let [worm (eve-worm)
275 time (atom 0)
276 worm-motor-map (vector-motor-control worm)]
277 (world
278 (nodify [worm
279 (box 10 0.5 10 :position (Vector3f. 0 -5 0) :mass 0
280 :color ColorRGBA/Gray)])
281 standard-debug-controls
282 (fn [world]
283 (enable-debug world)
284 (light-up-everything world)
285 (comment
286 (com.aurellem.capture.Capture/captureVideo
287 world
288 (file-str "/home/r/proj/cortex/tmp/moving-worm")))
289 )
290
291 (fn [_ _]
292 (swap! time inc)
293 (Thread/sleep 20)
294 (dorun (worm-motor-map
295 (worm-pattern @time)))))))
296
297
298
299 (defn join-at-point [obj-a obj-b world-pivot]
300 (cortex.silly/joint-dispatch
301 {:type :point}
302 (.getControl obj-a RigidBodyControl)
303 (.getControl obj-b RigidBodyControl)
304 (cortex.silly/world-to-local obj-a world-pivot)
305 (cortex.silly/world-to-local obj-b world-pivot)
306 nil
307 ))
308
309 (import com.jme3.bullet.collision.PhysicsCollisionObject)
310
311 (defn blab-* []
312 (let [hand (box 0.5 0.2 0.2 :position (Vector3f. 0 0 0)
313 :mass 0 :color ColorRGBA/Green)
314 finger (box 0.5 0.2 0.2 :position (Vector3f. 2.4 0 0)
315 :mass 1 :color ColorRGBA/Red)
316 connection-point (Vector3f. 1.2 0 0)
317 root (nodify [hand finger])]
318
319 (join-at-point hand finger (Vector3f. 1.2 0 0))
320
321 (.setCollisionGroup
322 (.getControl hand RigidBodyControl)
323 PhysicsCollisionObject/COLLISION_GROUP_NONE)
324 (world
325 root
326 standard-debug-controls
327 (fn [world]
328 (enable-debug world)
329 (.setTimer world (com.aurellem.capture.RatchetTimer. 60))
330 (set-gravity world Vector3f/ZERO)
331 )
332 no-op)))
333 (import java.awt.image.BufferedImage)
334
335 (defn draw-sprite [image sprite x y color ]
336 (dorun
337 (for [[u v] sprite]
338 (.setRGB image (+ u x) (+ v y) color))))
339
340 (defn view-angle
341 "create a debug view of an angle"
342 [color]
343 (let [image (BufferedImage. 50 50 BufferedImage/TYPE_INT_RGB)
344 previous (atom [25 25])
345 sprite [[0 0] [0 1]
346 [0 -1] [-1 0] [1 0]]]
347 (fn [angle]
348 (let [angle (float angle)]
349 (let [position
350 [(+ 25 (int (* 20 (Math/cos angle))))
351 (+ 25 (int (* 20(Math/sin angle))))]]
352 (draw-sprite image sprite (@previous 0) (@previous 1) 0x000000)
353 (draw-sprite image sprite (position 0) (position 1) color)
354 (reset! previous position))
355 image))))
356
357 (defn proprioception-debug-window
358 []
359 (let [yaw (view-angle 0xFF0000)
360 roll (view-angle 0x00FF00)
361 pitch (view-angle 0xFFFFFF)
362 v-yaw (view-image)
363 v-roll (view-image)
364 v-pitch (view-image)
365 ]
366 (fn [prop-data]
367 (dorun
368 (map
369 (fn [[y r p]]
370 (v-yaw (yaw y))
371 (v-roll (roll r))
372 (v-pitch (pitch p)))
373 prop-data)))))
374 (comment
375
376 (defn proprioception-debug-window
377 []
378 (let [time (atom 0)]
379 (fn [prop-data]
380 (if (= 0 (rem (swap! time inc) 40))
381 (println-repl prop-data)))))
382 )
383
384 (comment
385 (dorun
386 (map
387 (comp
388 println-repl
389 (fn [[p y r]]
390 (format
391 "pitch: %1.2f\nyaw: %1.2f\nroll: %1.2f\n"
392 p y r)))
393 prop-data)))
394
395
396 396
397 397
398 (defn test-proprioception 398 (defn test-proprioception
399 "Testing proprioception: 399 "Testing proprioception:
400 You should see two foating bars, and a printout of pitch, yaw, and 400 You should see two foating bars, and a printout of pitch, yaw, and