view org/skin.org @ 39:2ce7400825c2

further cleanup on touch
author Robert McIntyre <rlm@mit.edu>
date Thu, 03 Nov 2011 10:03:22 -0700
parents eeba17a4bd54
children bc93abad23ee
line wrap: on
line source
1 #+title: Simulated Sense of Touch
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.
5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
10 * Touch
12 My creatures need to be able to feel their environments. The idea here
13 is to thousands of small /touch receptors/ along the geometries which
14 make up the creature's body. The number of touch receptors in a given
15 area is determined by how complicated that area is, as determined by
16 the total number of triangles in that region. This way, complicated
17 regions like the hands/face, etc. get more touch receptors than
18 simpler areas of the body.
20 #+srcname: skin-main
21 #+begin_src clojure
22 (ns cortex.touch
23 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry
24 to be outfitted with touch sensors with density proportional to the
25 density of triangles along the surface of the Geometry. Enables a
26 Geometry to know what parts of itself are touching nearby objects."
27 {:author "Robert McIntyre"}
28 (:use (cortex world util))
29 (:import com.jme3.scene.Geometry)
30 (:import com.jme3.collision.CollisionResults)
31 (:import (com.jme3.math Triangle Vector3f Ray)))
33 (defn triangles
34 "Return a sequence of all the Triangles which compose a given
35 Geometry."
36 [#^Geometry geom]
37 (let
38 [mesh (.getMesh geom)
39 triangles (transient [])]
40 (dorun
41 (for [n (range (.getTriangleCount mesh))]
42 (let [tri (Triangle.)]
43 (.getTriangle mesh n tri)
44 ;; (.calculateNormal tri)
45 ;; (.calculateCenter tri)
46 (conj! triangles tri))))
47 (persistent! triangles)))
49 (defn get-ray-origin
50 "Return the origin which a Ray would have to have to be in the exact
51 center of a particular Triangle in the Geometry in World
52 Coordinates."
53 [geom tri]
54 (let [new (Vector3f.)]
55 (.calculateCenter tri)
56 (.localToWorld geom (.getCenter tri) new) new))
58 (defn get-ray-direction
59 "Return the direction which a Ray would have to have to be in the
60 exact center of a particular Triangle in the Geometry, pointing
61 normal to the Triangle, in coordinates relative to the center of the
62 Triangle."
63 [geom tri]
64 (let [n+c (Vector3f.)]
65 (.calculateNormal tri)
66 (.calculateCenter tri)
67 (.localToWorld
68 geom
69 (.add (.getCenter tri) (.getNormal tri)) n+c)
70 (.subtract n+c (get-ray-origin geom tri))))
72 (defn normal-rays
73 "For each Triangle which comprises the Geometry, returns a Ray which
74 is centered on that Triangle, points outward in a normal direction,
75 and extends for =limit= distance."
76 [limit #^Geometry geom]
77 (vec
78 (map
79 (fn [tri]
80 (doto
81 (Ray. (get-ray-origin geom tri)
82 (get-ray-direction geom tri))
83 (.setLimit limit)))
84 (triangles geom))))
86 (defn touch-percieve
87 "Augment a Geometry with the sense of touch. Returns a sequence of
88 non-negative integers, one for each triangle, with the value of the
89 integer describing how many objects a ray of length =limit=, normal
90 to the triangle and originating from its center, encountered. The
91 Geometry itself is not counted among the results."
92 [limit geom node]
93 (let [normals (normal-rays limit geom)]
94 (doall
95 (for [ray normals]
96 (do
97 (let [results (CollisionResults.)]
98 (.collideWith node ray results)
99 (let [touch-objects
100 (set (filter #(not (= geom %))
101 (map #(.getGeometry %) results)))]
102 (count touch-objects))))))))
103 #+end_src
106 * Example
108 #+srcname: touch-test
109 #+begin_src clojure
110 (ns test.touch
111 (:use (cortex world util touch)))
113 (cortex.import/mega-import-jme3)
115 (import java.util.logging.Level)
116 (import java.util.logging.Logger)
117 (use 'hello.brick-wall)
120 (defn ray-origin-debug
121 [ray color]
122 (make-shape
123 (assoc base-shape
124 :shape (Sphere. 5 5 0.05)
125 :name "arrow"
126 :color color
127 :texture false
128 :physical? false
129 :position
130 (.getOrigin ray))))
132 (defn ray-debug [ray color]
133 (make-shape
134 (assoc
135 base-shape
136 :name "debug-ray"
137 :physical? false
138 :shape (com.jme3.scene.shape.Line.
139 (.getOrigin ray)
140 (.add
141 (.getOrigin ray)
142 (.mult (.getDirection ray)
143 (float (.getLimit ray))))))))
146 (defn contact-color [contacts]
147 (case contacts
148 0 ColorRGBA/Gray
149 1 ColorRGBA/Red
150 2 ColorRGBA/Green
151 3 ColorRGBA/Yellow
152 4 ColorRGBA/Orange
153 5 ColorRGBA/Red
154 6 ColorRGBA/Magenta
155 7 ColorRGBA/Pink
156 8 ColorRGBA/White))
158 (defn update-ray-debug [node ray contacts]
159 (let [origin (.getChild node 0)]
160 (.setLocalTranslation origin (.getOrigin ray))
161 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))
163 (defn init-node
164 [debug-node rays]
165 (println-repl "Init touch debug node.")
166 (.detachAllChildren debug-node)
167 (dorun
168 (for [ray rays]
169 (do
170 (.attachChild
171 debug-node
172 (doto (Node.)
173 (.attachChild (ray-origin-debug ray ColorRGBA/Gray))
174 (.attachChild (ray-debug ray ColorRGBA/Gray))
175 ))))))
177 (defn manage-ray-debug-node [debug-node geom touch-data limit]
178 (let [rays (normal-rays limit geom)]
179 (if (not= (count (.getChildren debug-node)) (count touch-data))
180 (init-node debug-node rays))
181 (dorun
182 (for [n (range (count touch-data))]
183 (update-ray-debug
184 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))
188 (defn no-logging []
189 (.setLevel (Logger/getLogger "com.jme3") Level/OFF))
191 (defn set-accuracy [world new-accuracy]
192 (let [physics-manager (.getState (.getStateManager world) BulletAppState)]
193 (.setAccuracy (.getPhysicsSpace physics-manager) (float new-accuracy))))
195 (defn transparent-sphere []
196 (doto
197 (make-shape
198 (merge base-shape
199 {:position (Vector3f. 0 2 0)
200 :name "the blob."
201 :material "Common/MatDefs/Misc/Unshaded.j3md"
202 :texture "Textures/purpleWisp.png"
203 :physical? true
204 :mass 70
205 :color ColorRGBA/Blue
206 :shape (Sphere. 10 10 1)}))
207 (-> (.getMaterial)
208 (.getAdditionalRenderState)
209 (.setBlendMode RenderState$BlendMode/Alpha))
210 (.setQueueBucket RenderQueue$Bucket/Transparent)))
212 (defn transparent-box []
213 (doto
214 (make-shape
215 (merge base-shape
216 {:position (Vector3f. 0 2 0)
217 :name "box"
218 :material "Common/MatDefs/Misc/Unshaded.j3md"
219 :texture "Textures/purpleWisp.png"
220 :physical? true
221 :mass 70
222 :color ColorRGBA/Blue
223 :shape (Box. 1 1 1)}))
224 (-> (.getMaterial)
225 (.getAdditionalRenderState)
226 (.setBlendMode RenderState$BlendMode/Alpha))
227 (.setQueueBucket RenderQueue$Bucket/Transparent)))
229 (defn transparent-floor []
230 (doto
231 (box 5 0.2 5 :mass 0 :position (Vector3f. 0 -2 0)
232 :material "Common/MatDefs/Misc/Unshaded.j3md"
233 :texture "Textures/redWisp.png"
234 :name "floor")
235 (-> (.getMaterial)
236 (.getAdditionalRenderState)
237 (.setBlendMode RenderState$BlendMode/Alpha))
238 (.setQueueBucket RenderQueue$Bucket/Transparent)))
240 (defn test-skin []
241 (let [b
242 ;;(transparent-box)
243 (transparent-sphere)
244 ;;(sphere)
245 f (transparent-floor)
246 debug-node (Node.)
247 node (doto (Node.) (.attachChild b) (.attachChild f))
248 root-node (doto (Node.) (.attachChild node)
249 (.attachChild debug-node))
250 ]
252 (world
253 root-node
254 {"key-return" (fire-cannon-ball node)}
255 (fn [world]
256 ;; (Capture/SimpleCaptureVideo
257 ;; world
258 ;; (file-str "/home/r/proj/cortex/tmp/blob.avi"))
259 ;; (no-logging)
260 ;;(enable-debug world)
261 ;; (set-accuracy world (/ 1 60))
262 )
264 (fn [& _]
265 (let [sensitivity 0.2
266 touch-data (touch-percieve sensitivity b node)]
267 (manage-ray-debug-node debug-node b touch-data sensitivity)
268 )
269 (Thread/sleep 10)
270 ))))
273 #+end_src
279 * COMMENT code generation
280 #+begin_src clojure :tangle ../src/cortex/touch.clj
281 <<skin-main>>
282 #+end_src
284 #+begin_src clojure :tangle ../src/test/touch.clj
285 <<touch-test>>
286 #+end_src