comparison org/skin.org @ 37:eeba17a4bd54

cleaning up the touch code
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 09:52:34 -0700
parents 97703c7f020e
children 2ce7400825c2
comparison
equal deleted inserted replaced
36:91090f8a4414 37:eeba17a4bd54
1 #+title: SKIN! 1 #+title: Simulated Sense of Touch
2 #+author: Robert McIntyre 2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu 3 #+email: rlm@mit.edu
4 #+description: Simulating touch in JMonkeyEngine 4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.
5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure
5 #+SETUPFILE: ../../aurellem/org/setup.org 6 #+SETUPFILE: ../../aurellem/org/setup.org
6 #+INCLUDE: ../../aurellem/org/level-0.org 7 #+INCLUDE: ../../aurellem/org/level-0.org
7 #+babel: :mkdirp yes :noweb yes 8
8 9 * Touch
9 let's see what checkboxes look like: 10
10 11 My creatures need to be able to feel their environments. The idea here
11 * Skin! 12 is to thousands of small /touch receptors/ along the geometries which
13 make up the creature's body. The number of touch receptors in a given
14 area is determined by how complicated that area is, as determined by
15 the total number of triangles in that region. This way, complicated
16 regions like the hands/face, etc. get more touch receptors than
17 simpler areas of the body.
12 18
13 #+srcname: skin-main 19 #+srcname: skin-main
14 #+begin_src clojure 20 #+begin_src clojure
15 (ns body.skin) 21 (ns cortex.touch
16 (use 'cortex.world) 22 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry
17 (use 'cortex.import) 23 to be outfitted with touch sensors with density proportional to the
18 (use 'clojure.contrib.def) 24 density of triangles along the surface of the Geometry. Enables a
19 (cortex.import/mega-import-jme3) 25 Geometry to know what parts of itself are touching nearby objects."
20 (rlm.rlm-commands/help) 26 {:author "Robert McIntyre"}
21 27 (:use (cortex world util))
22 (import java.util.logging.Level) 28 (:import com.jme3.scene.Geometry)
23 (import java.util.logging.Logger) 29 (:import com.jme3.collision.CollisionResult)
24 (use 'hello.brick-wall) 30 (:import com.jme3.math Triangle Vector3f Ray))
25 31
26 (defn triangles [#^Geometry geom] 32 (defn triangles
33 "Return a sequence of all the Triangles which compose a given
34 Geometry."
35 [#^Geometry geom]
27 (let 36 (let
28 [mesh (.getMesh geom) 37 [mesh (.getMesh geom)
29 triangles (transient [])] 38 triangles (transient [])]
30 (dorun 39 (dorun
31 (for [n (range (.getTriangleCount mesh))] 40 (for [n (range (.getTriangleCount mesh))]
32 (let [tri (Triangle.)] 41 (let [tri (Triangle.)]
33 (.getTriangle mesh n tri) 42 (.getTriangle mesh n tri)
34 (.calculateNormal tri) 43 ;; (.calculateNormal tri)
35 (.calculateCenter tri) 44 ;; (.calculateCenter tri)
36 (conj! triangles tri)))) 45 (conj! triangles tri))))
37 (persistent! triangles))) 46 (persistent! triangles)))
38 47
39 (defn get-ray-origin 48 (defn get-ray-origin
49 "Return the origin which a Ray would have to have to be in the exact
50 center of a particular Triangle in the Geometry in World
51 Coordinates."
40 [geom tri] 52 [geom tri]
41 (let [new (Vector3f.)] 53 (let [new (Vector3f.)]
42 (.calculateCenter tri) 54 (.calculateCenter tri)
43 (.localToWorld geom (.getCenter tri) new) 55 (.localToWorld geom (.getCenter tri) new) new))
44 new))
45 56
46 (defn get-ray-direction 57 (defn get-ray-direction
58 "Return the direction which a Ray would have to have to be in the
59 exact center of a particular Triangle in the Geometry, pointing
60 normal to the Triangle, in coordinates relative to the center of the
61 Triangle."
47 [geom tri] 62 [geom tri]
48 (let [n+c (Vector3f.)] 63 (let [n+c (Vector3f.)]
49 (.calculateNormal tri) 64 (.calculateNormal tri)
50 (.calculateCenter tri) 65 (.calculateCenter tri)
51 (.localToWorld geom (.add (.getCenter tri) (.getNormal tri)) n+c) 66 (.localToWorld
52 (.subtract n+c (get-ray-origin geom tri)) 67 geom
53 )) 68 (.add (.getCenter tri) (.getNormal tri)) n+c)
69 (.subtract n+c (get-ray-origin geom tri))))
70
71 (defn normal-rays
72 "For each Triangle which comprises the Geometry, returns a Ray which
73 is centered on that Triangle, points outward in a normal direction,
74 and extends for =limit= distance."
75 [limit #^Geometry geom]
76 (vec
77 (map
78 (fn [tri]
79 (doto
80 (Ray. (get-ray-origin geom tri)
81 (get-ray-direction geom tri))
82 (.setLimit limit)))
83 (triangles geom))))
84
85 (defn touch-percieve
86 "Augment a Geometry with the sense of touch. Returns a sequence of
87 non-negative integers, one for each triangle, with the value of the
88 integer describing how many objects a ray of length =limit=, normal
89 to the triangle and originating from its center, encountered. The
90 Geometry itself is not counted among the results."
91 [limit geom node]
92 (let [normals (normal-rays limit geom)]
93 (doall
94 (for [ray normals]
95 (do
96 (let [results (CollisionResults.)]
97 (.collideWith node ray results)
98 (let [touch-objects
99 (set (filter #(not (= geom %))
100 (map #(.getGeometry %) results)))]
101 (count touch-objects))))))))
102 #+end_src
103
104
105 * Example
106
107 #+begin_src clojure
108
54 109
55 (defn ray-origin-debug 110 (defn ray-origin-debug
56 [ray color] 111 [ray color]
57 (make-shape 112 (make-shape
58 (assoc base-shape 113 (assoc base-shape
79 134
80 135
81 (defn contact-color [contacts] 136 (defn contact-color [contacts]
82 (case contacts 137 (case contacts
83 0 ColorRGBA/Gray 138 0 ColorRGBA/Gray
84 1 ColorRGBA/Blue 139 1 ColorRGBA/Red
85 2 ColorRGBA/Green 140 2 ColorRGBA/Green
86 3 ColorRGBA/Yellow 141 3 ColorRGBA/Yellow
87 4 ColorRGBA/Orange 142 4 ColorRGBA/Orange
88 5 ColorRGBA/Red 143 5 ColorRGBA/Red
89 6 ColorRGBA/Magenta 144 6 ColorRGBA/Magenta
90 7 ColorRGBA/Pink 145 7 ColorRGBA/Pink
91 8 ColorRGBA/White)) 146 8 ColorRGBA/White))
92
93 (defn normal-rays
94 "returns rays"
95 [limit #^Geometry geom]
96 (vec
97 (map
98 (fn [tri]
99 (doto
100 (Ray. (get-ray-origin geom tri)
101 (get-ray-direction geom tri))
102 (.setLimit limit)))
103 (triangles geom))))
104 147
105 (defn update-ray-debug [node ray contacts] 148 (defn update-ray-debug [node ray contacts]
106 (let [origin (.getChild node 0)] 149 (let [origin (.getChild node 0)]
107 (.setLocalTranslation origin (.getOrigin ray)) 150 (.setLocalTranslation origin (.getOrigin ray))
108 (.setColor (.getMaterial origin) "Color" (contact-color contacts)))) 151 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))
128 (dorun 171 (dorun
129 (for [n (range (count touch-data))] 172 (for [n (range (count touch-data))]
130 (update-ray-debug 173 (update-ray-debug
131 (.getChild debug-node n) (nth rays n) (nth touch-data n)))))) 174 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))
132 175
133 (defn touch-percieve [limit geom node] 176
134 (let [normals (normal-rays limit geom)]
135
136 (doall
137 (for [ray normals]
138 (do
139 (let [results (CollisionResults.)]
140 (.collideWith node ray results)
141 (let [touch-objects (set (filter #(not (= geom %))
142 (map #(.getGeometry %) results)))]
143 ;;(dorun (map #(println-repl (.getName %)) touch-objects))
144 (count touch-objects))))))))
145 177
146 (defn no-logging [] 178 (defn no-logging []
147 (.setLevel (Logger/getLogger "com.jme3") Level/OFF)) 179 (.setLevel (Logger/getLogger "com.jme3") Level/OFF))
148 180
149 (defn set-accuracy [world new-accuracy] 181 (defn set-accuracy [world new-accuracy]
225 (manage-ray-debug-node debug-node b touch-data sensitivity) 257 (manage-ray-debug-node debug-node b touch-data sensitivity)
226 ) 258 )
227 (Thread/sleep 10) 259 (Thread/sleep 10)
228 )))) 260 ))))
229 261
262
230 #+end_src 263 #+end_src
231
232 #+results: skin-main
233 : #'body.skin/test-skin
234
235
236 264
237 265
238 266
239 267
240 268
241 * COMMENT code generation 269 * COMMENT code generation
242 #+begin_src clojure :tangle ../src/body/skin.clj :noweb yes 270 #+begin_src clojure :tangle ../src/cortex/touch.clj :noweb yes
243 <<skin-main>> 271 <<skin-main>>
244 #+end_src 272 #+end_src
245 273
246 274
247 275