rlm@158
|
1 #+title: Movement!
|
rlm@158
|
2 #+author: Robert McIntyre
|
rlm@158
|
3 #+email: rlm@mit.edu
|
rlm@158
|
4 #+description: muscles for a simulated creature
|
rlm@158
|
5 #+keywords: simulation, jMonkeyEngine3, clojure
|
rlm@158
|
6 #+SETUPFILE: ../../aurellem/org/setup.org
|
rlm@158
|
7 #+INCLUDE: ../../aurellem/org/level-0.org
|
rlm@158
|
8
|
rlm@158
|
9 #+name: movement
|
rlm@158
|
10 #+begin_src clojure
|
rlm@158
|
11 (ns cortex.movement
|
rlm@158
|
12 (:use (cortex world util sense body))
|
rlm@158
|
13 (:import jme3tools.converters.ImageToAwt)
|
rlm@158
|
14 (:import java.awt.image.BufferedImage))
|
rlm@158
|
15
|
rlm@158
|
16 (cortex.import/mega-import-jme3)
|
rlm@158
|
17
|
rlm@158
|
18
|
rlm@158
|
19
|
rlm@158
|
20
|
rlm@158
|
21 ;; here's how motor-control/ proprioception will work: Each muscle is
|
rlm@158
|
22 ;; defined by a 1-D array of numbers (the "motor pool") each of which
|
rlm@158
|
23 ;; represent muscle fibers. A muscle also has a scalar :strength
|
rlm@158
|
24 ;; factor which determines how strong the muscle as a whole is.
|
rlm@158
|
25 ;; The effector function for a muscle takes a number < (count
|
rlm@158
|
26 ;; motor-pool) and that number is said to "activate" all the muscle
|
rlm@158
|
27 ;; fibers whose index is lower than the number. Each fiber will apply
|
rlm@158
|
28 ;; force in proportion to its value in the array. Lower values cause
|
rlm@158
|
29 ;; less force. The lower values can be put at the "beginning" of the
|
rlm@158
|
30 ;; 1-D array to simulate the layout of actual human muscles, which are
|
rlm@158
|
31 ;; capable of more percise movements when exerting less force.
|
rlm@158
|
32
|
rlm@158
|
33 ;; I don't know how to encode proprioception, so for now, just return
|
rlm@158
|
34 ;; a function for each joint that returns a triplet of floats which
|
rlm@158
|
35 ;; represent relative roll, pitch, and yaw. Write display code for
|
rlm@158
|
36 ;; this though.
|
rlm@158
|
37
|
rlm@158
|
38 (defn muscle-fiber-values
|
rlm@158
|
39 "get motor pool strengths"
|
rlm@158
|
40 [#^BufferedImage image]
|
rlm@158
|
41 (vec
|
rlm@158
|
42 (let [width (.getWidth image)]
|
rlm@158
|
43 (for [x (range width)]
|
rlm@158
|
44 (- 255
|
rlm@158
|
45 (bit-and
|
rlm@158
|
46 0x0000FF
|
rlm@158
|
47 (.getRGB image x 0)))))))
|
rlm@158
|
48
|
rlm@158
|
49
|
rlm@158
|
50 (defn creature-muscles
|
rlm@158
|
51 "Return the children of the creature's \"muscles\" node."
|
rlm@158
|
52 [#^Node creature]
|
rlm@158
|
53 (if-let [muscle-node (.getChild creature "muscles")]
|
rlm@158
|
54 (seq (.getChildren muscle-node))
|
rlm@158
|
55 (do (println-repl "could not find muscles node") [])))
|
rlm@158
|
56
|
rlm@158
|
57 (defn single-muscle [#^Node parts #^Node muscle]
|
rlm@158
|
58 (let [target (closest-node parts muscle)
|
rlm@158
|
59 axis
|
rlm@158
|
60 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
|
rlm@158
|
61 strength (meta-data muscle "strength")
|
rlm@158
|
62 image-name (read-string (meta-data muscle "muscle"))
|
rlm@158
|
63 image
|
rlm@158
|
64 (ImageToAwt/convert
|
rlm@158
|
65 (.getImage (.loadTexture (asset-manager) image-name))
|
rlm@158
|
66 false false 0)
|
rlm@158
|
67 fibers (muscle-fiber-values image)
|
rlm@158
|
68 fiber-integral (reductions + fibers)
|
rlm@158
|
69 force-index (vec
|
rlm@158
|
70 (map
|
rlm@158
|
71 #(float (* strength (/ % (last
|
rlm@158
|
72 fiber-integral))))
|
rlm@158
|
73 fiber-integral))
|
rlm@158
|
74 control (.getControl target RigidBodyControl)]
|
rlm@158
|
75 (fn [n]
|
rlm@158
|
76 (let [pool-index (min n (count fibers))]
|
rlm@158
|
77 (.applyTorque control (.mult axis (force-index n)))))))
|
rlm@158
|
78
|
rlm@158
|
79
|
rlm@158
|
80 (defn enable-muscles
|
rlm@158
|
81 "Must be called on a creature after RigidBodyControls have been
|
rlm@158
|
82 created."
|
rlm@158
|
83 [#^Node creature]
|
rlm@158
|
84 (let [muscles (creature-muscles creature)]
|
rlm@158
|
85 (for [muscle muscles]
|
rlm@158
|
86 (single-muscle creature muscle))))
|
rlm@158
|
87
|
rlm@158
|
88
|
rlm@158
|
89 #+end_src
|
rlm@158
|
90
|
rlm@158
|
91
|
rlm@158
|
92
|
rlm@158
|
93
|
rlm@158
|
94
|
rlm@158
|
95 * COMMENT code generation
|
rlm@158
|
96 #+begin_src clojure :tangle ../src/cortex/movement.clj
|
rlm@158
|
97 <<movement>>
|
rlm@158
|
98 #+end_src
|