view org/sense-util.org @ 171:15bde60217aa

updated docstring for vision-fn
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 05:02:25 -0700
parents 9e6a30b8c99a
children 0f1c7921d967
line wrap: on
line source
1 #+title: General sense/effector utilities
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: sensory utilities
5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
10 #+name: sense-util
11 #+begin_src clojure
12 (ns cortex.sense)
13 (cortex.import/mega-import-jme3)
14 (import ij.process.ImageProcessor)
15 (import java.awt.image.BufferedImage)
16 (use 'cortex.util)
17 (import jme3tools.converters.ImageToAwt)
19 (defn meta-data [blender-node key]
20 (if-let [data (.getUserData blender-node "properties")]
21 (.findValue data key)
22 nil))
24 (defn closest-node
25 "Return the object in creature which is closest to the given node."
26 ;;dylan"The closest object in creature to the given node."
27 [#^Node creature #^Node eye]
28 (loop [radius (float 0.01)]
29 (let [results (CollisionResults.)]
30 (.collideWith
31 creature
32 (BoundingBox. (.getWorldTranslation eye)
33 radius radius radius)
34 results)
35 (if-let [target (first results)]
36 (.getGeometry target)
37 (recur (float (* 2 radius)))))))
39 (defn bind-sense
40 "Bind the sense to the Spatial such that it will maintain its
41 current position relative to the Spatial no matter how the spatial
42 moves. 'sense can be either a Camera or Listener object."
43 [#^Spatial obj sense]
44 (let [sense-offset (.subtract (.getLocation sense)
45 (.getWorldTranslation obj))
46 initial-sense-rotation (Quaternion. (.getRotation sense))
47 base-anti-rotation (.inverse (.getWorldRotation obj))]
48 (.addControl
49 obj
50 (proxy [AbstractControl] []
51 (controlUpdate [tpf]
52 (let [total-rotation
53 (.mult base-anti-rotation (.getWorldRotation obj))]
54 (.setLocation sense
55 (.add
56 (.mult total-rotation sense-offset)
57 (.getWorldTranslation obj)))
58 (.setRotation sense
59 (.mult total-rotation initial-sense-rotation))))
60 (controlRender [_ _])))))
62 (def white -1)
64 (defn filter-pixels
65 "List the coordinates of all pixels matching pred, within the bounds
66 provided. Bounds -> [x0 y0 width height]"
67 {:author "Dylan Holmes"}
68 ([pred #^BufferedImage image]
69 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
70 ([pred #^BufferedImage image [x0 y0 width height]]
71 ((fn accumulate [x y matches]
72 (cond
73 (>= y (+ height y0)) matches
74 (>= x (+ width x0)) (recur 0 (inc y) matches)
75 (pred (.getRGB image x y))
76 (recur (inc x) y (conj matches [x y]))
77 :else (recur (inc x) y matches)))
78 x0 y0 [])))
80 (defn white-coordinates
81 "Coordinates of all the white pixels in a subset of the image."
82 ([#^BufferedImage image bounds]
83 (filter-pixels #(= % white) image bounds))
84 ([#^BufferedImage image]
85 (filter-pixels #(= % white) image)))
87 (defn points->image
88 "Take a sparse collection of points and visuliaze it as a
89 BufferedImage."
91 ;; TODO maybe parallelize this since it's easy
93 [points]
94 (if (empty? points)
95 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
96 (let [xs (vec (map first points))
97 ys (vec (map second points))
98 x0 (apply min xs)
99 y0 (apply min ys)
100 width (- (apply max xs) x0)
101 height (- (apply max ys) y0)
102 image (BufferedImage. (inc width) (inc height)
103 BufferedImage/TYPE_INT_RGB)]
104 (dorun
105 (for [x (range (.getWidth image))
106 y (range (.getHeight image))]
107 (.setRGB image x y 0xFF0000)))
108 (dorun
109 (for [index (range (count points))]
110 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
112 image)))
114 (defn average [coll]
115 (/ (reduce + coll) (count coll)))
117 (defn collapse-1d
118 "One dimensional analogue of collapse"
119 [center line]
120 (let [length (count line)
121 num-above (count (filter (partial < center) line))
122 num-below (- length num-above)]
123 (range (- center num-below)
124 (+ center num-above))))
126 (defn collapse
127 "Take a set of pairs of integers and collapse them into a
128 contigous bitmap."
129 [points]
130 (if (empty? points) []
131 (let
132 [num-points (count points)
133 center (vector
134 (int (average (map first points)))
135 (int (average (map first points))))
136 flattened
137 (reduce
138 concat
139 (map
140 (fn [column]
141 (map vector
142 (map first column)
143 (collapse-1d (second center)
144 (map second column))))
145 (partition-by first (sort-by first points))))
146 squeezed
147 (reduce
148 concat
149 (map
150 (fn [row]
151 (map vector
152 (collapse-1d (first center)
153 (map first row))
154 (map second row)))
155 (partition-by second (sort-by second flattened))))
156 relocate
157 (let [min-x (apply min (map first squeezed))
158 min-y (apply min (map second squeezed))]
159 (map (fn [[x y]]
160 [(- x min-x)
161 (- y min-y)])
162 squeezed))]
163 relocate)))
165 (defn world-to-local
166 "Convert the world coordinates into coordinates relative to the
167 object (i.e. local coordinates), taking into account the rotation
168 of object."
169 [#^Spatial object world-coordinate]
170 (.worldToLocal object world-coordinate nil))
172 (defn local-to-world
173 "Convert the local coordinates into coordinates into world relative
174 coordinates"
175 [#^Spatial object local-coordinate]
176 (.localToWorld object local-coordinate nil))
179 (defn sense-nodes [parent-name]
180 (fn [#^Node creature]
181 (if-let [sense-node (.getChild creature parent-name)]
182 (seq (.getChildren sense-node))
183 (do (println-repl "could not find" parent-name "node") []))))
185 (defn load-image
186 "Load an image as a BufferedImage using the asset-manager system."
187 [asset-relative-path]
188 (ImageToAwt/convert
189 (.getImage (.loadTexture (asset-manager) asset-relative-path))
190 false false 0))
193 #+end_src
195 #+results: sense-util
196 : #'cortex.sense/meta-data
200 * COMMENT generate source
201 #+begin_src clojure :tangle ../src/cortex/sense.clj
202 <<sense-util>>
203 #+end_src