comparison org/touch.org @ 178:6fba17a74a57

refactored touch
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 07:05:54 -0700
parents 5af4ebe72b97
children 11bd5f0625ad
comparison
equal deleted inserted replaced
177:5af4ebe72b97 178:6fba17a74a57
3 #+email: rlm@mit.edu 3 #+email: rlm@mit.edu
4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure. 4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.
5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure 5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org 6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org 7 #+INCLUDE: ../../aurellem/org/level-0.org
8
9 8
10 * Touch 9 * Touch
11 10
12 My creatures need to be able to feel their environments. The idea here 11 My creatures need to be able to feel their environments. The idea here
13 is to create thousands of small /touch receptors/ along the geometries 12 is to create thousands of small /touch receptors/ along the geometries
24 to be outfitted with touch sensors with density proportional to the 23 to be outfitted with touch sensors with density proportional to the
25 density of triangles along the surface of the Geometry. Enables a 24 density of triangles along the surface of the Geometry. Enables a
26 Geometry to know what parts of itself are touching nearby objects." 25 Geometry to know what parts of itself are touching nearby objects."
27 {:author "Robert McIntyre"} 26 {:author "Robert McIntyre"}
28 (:use (cortex world util sense)) 27 (:use (cortex world util sense))
28 (:use clojure.contrib.def)
29 (:import com.jme3.scene.Geometry) 29 (:import com.jme3.scene.Geometry)
30 (:import com.jme3.collision.CollisionResults) 30 (:import com.jme3.collision.CollisionResults)
31 (:import jme3tools.converters.ImageToAwt) 31 (:import jme3tools.converters.ImageToAwt)
32 (:import (com.jme3.math Triangle Vector3f Ray))) 32 (:import (com.jme3.math Triangle Vector3f Ray)))
33 33
34 (use 'clojure.contrib.def)
35 (cortex.import/mega-import-jme3) 34 (cortex.import/mega-import-jme3)
36 35
37 (defn triangles 36 (defn triangles
38 "Return a sequence of all the Triangles which compose a given 37 "Return a sequence of all the Triangles which compose a given
39 Geometry." 38 Geometry."
73 (.subtract n+c (get-ray-origin geom tri)))) 72 (.subtract n+c (get-ray-origin geom tri))))
74 73
75 ;; Every Mesh has many triangles, each with its own index. 74 ;; Every Mesh has many triangles, each with its own index.
76 ;; Every vertex has its own index as well. 75 ;; Every vertex has its own index as well.
77 76
78 (defn tactile-sensor-image 77 (defn tactile-sensor-profile
79 "Return the touch-sensor distribution image in BufferedImage format, 78 "Return the touch-sensor distribution image in BufferedImage format,
80 or nil if it does not exist." 79 or nil if it does not exist."
81 [#^Geometry obj] 80 [#^Geometry obj]
82 (if-let [image-path (meta-data obj "touch")] 81 (if-let [image-path (meta-data obj "touch")]
83 (ImageToAwt/convert 82 (load-image image-path)))
84 (.getImage
85 (.loadTexture
86 (asset-manager)
87 image-path))
88 false false 0)))
89
90
91 83
92 (defn triangle 84 (defn triangle
93 "Get the triangle specified by triangle-index from the mesh within 85 "Get the triangle specified by triangle-index from the mesh within
94 bounds." 86 bounds."
95 [#^Mesh mesh triangle-index] 87 [#^Mesh mesh triangle-index]
197 (get point 1 0) 189 (get point 1 0)
198 (get point 2 0)))) 190 (get point 2 0))))
199 (take 3 points)))) 191 (take 3 points))))
200 192
201 (defn convex-bounds 193 (defn convex-bounds
202 ;;dylan 194 "Returns the smallest square containing the given vertices, as a
203 "Returns the smallest square containing the given 195 vector of integers [left top width height]."
204 vertices, as a vector of integers [left top width height]."
205 ;; "Dimensions of the smallest integer bounding square of the list of
206 ;; 2D verticies in the form: [x y width height]."
207 [uv-verts] 196 [uv-verts]
208 (let [xs (map first uv-verts) 197 (let [xs (map first uv-verts)
209 ys (map second uv-verts) 198 ys (map second uv-verts)
210 x0 (Math/floor (apply min xs)) 199 x0 (Math/floor (apply min xs))
211 y0 (Math/floor (apply min ys)) 200 y0 (Math/floor (apply min ys))
212 x1 (Math/ceil (apply max xs)) 201 x1 (Math/ceil (apply max xs))
213 y1 (Math/ceil (apply max ys))] 202 y1 (Math/ceil (apply max ys))]
214 [x0 y0 (- x1 x0) (- y1 y0)])) 203 [x0 y0 (- x1 x0) (- y1 y0)]))
215 204
216 (defn sensors-in-triangle 205 (defn sensors-in-triangle
217 ;;dylan 206 "Locate the touch sensors in the triangle, returning a map of their
218 "Locate the touch sensors in the triangle, returning a map of their UV and geometry-relative coordinates." 207 UV and geometry-relative coordinates."
219 ;;"Find the locations of the touch sensors within a triangle in both
220 ;; UV and gemoetry relative coordinates."
221 [image mesh tri-index] 208 [image mesh tri-index]
222 (let [width (.getWidth image) 209 (let [width (.getWidth image)
223 height (.getHeight image) 210 height (.getHeight image)
224 UV-vertex-coords (triangle-UV-coord mesh width height tri-index) 211 UV-vertex-coords (triangle-UV-coord mesh width height tri-index)
225 bounds (convex-bounds UV-vertex-coords) 212 bounds (convex-bounds UV-vertex-coords)
236 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0))) 223 (map (fn [[u v]] (.mult UV->geometry (Vector3f. u v 0)))
237 UV-sensor-coords)] 224 UV-sensor-coords)]
238 {:UV UV-sensor-coords :geometry geometry-sensor-coords})) 225 {:UV UV-sensor-coords :geometry geometry-sensor-coords}))
239 226
240 (defn-memo locate-feelers 227 (defn-memo locate-feelers
241 "Search the geometry's tactile UV image for touch sensors, returning 228 "Search the geometry's tactile UV profile for touch sensors,
242 their positions in geometry-relative coordinates." 229 returning their positions in geometry-relative coordinates."
243 [#^Geometry geo] 230 [#^Geometry geo]
244 (let [mesh (.getMesh geo) 231 (let [mesh (.getMesh geo)
245 num-triangles (.getTriangleCount mesh)] 232 num-triangles (.getTriangleCount mesh)]
246 (if-let [image (tactile-sensor-image geo)] 233 (if-let [image (tactile-sensor-profile geo)]
247 (map 234 (map
248 (partial sensors-in-triangle image mesh) 235 (partial sensors-in-triangle image mesh)
249 (range num-triangles)) 236 (range num-triangles))
250 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil})))) 237 (repeat (.getTriangleCount mesh) {:UV nil :geometry nil}))))
251 238
252 (defn-memo touch-topology [#^Gemoetry geo] 239 (defn-memo touch-topology
240 "Return a sequence of vectors of the form [x y] describing the
241 \"topology\" of the tactile sensors. Points that are close together
242 in the touch-topology are generally close together in the simulation."
243 [#^Gemoetry geo]
253 (vec (collapse (reduce concat (map :UV (locate-feelers geo)))))) 244 (vec (collapse (reduce concat (map :UV (locate-feelers geo))))))
254 245
255 (defn-memo feeler-coordinates [#^Geometry geo] 246 (defn-memo feeler-coordinates
247 "The location of the touch sensors in world-space coordinates."
248 [#^Geometry geo]
256 (vec (map :geometry (locate-feelers geo)))) 249 (vec (map :geometry (locate-feelers geo))))
257 250
258 (defn enable-touch [#^Geometry geo] 251 (defn touch-fn
252 "Returns a function which returns tactile sensory data when called
253 inside a running simulation."
254 [#^Geometry geo]
259 (let [feeler-coords (feeler-coordinates geo) 255 (let [feeler-coords (feeler-coordinates geo)
260 tris (triangles geo) 256 tris (triangles geo)
261 limit 0.1 257 limit 0.1
262 ;;results (CollisionResults.) 258 ;;results (CollisionResults.)
263 ] 259 ]
292 (rem 288 (rem
293 (int 289 (int
294 (* 255 (/ (.getDistance 290 (* 255 (/ (.getDistance
295 (first touch-objects)) limit))) 291 (first touch-objects)) limit)))
296 256)))))))))))))) 292 256))))))))))))))
297
298 293
299 (defn touch [#^Node pieces] 294 (defn touch!
300 (filter (comp not nil?) 295 "Endow the creature with the sense of touch. Returns a sequence of
301 (map enable-touch 296 functions, one for each body part with a tactile-sensor-proile,
302 (filter #(isa? (class %) Geometry) 297 each of which when called returns sensory data for that body part."
303 (node-seq pieces))))) 298 [#^Node creature]
299 (filter
300 (comp not nil?)
301 (map touch-fn
302 (filter #(isa? (class %) Geometry)
303 (node-seq creature)))))
304 304
305 305
306 #+end_src 306 #+end_src
307 307
308 308