annotate org/sense.org @ 197:16cbce075a0b

reorganizing for website
author Robert McIntyre <rlm@mit.edu>
date Sun, 05 Feb 2012 06:55:41 -0700
parents 22548d48cc85
children fc0bf33bded2
rev   line source
rlm@197 1 #+title: General Sense/Effector Utilities
rlm@151 2 #+author: Robert McIntyre
rlm@151 3 #+email: rlm@mit.edu
rlm@151 4 #+description: sensory utilities
rlm@151 5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
rlm@151 6 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@151 7 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@151 8
rlm@197 9 * Namespace/Imports
rlm@197 10 #+name header
rlm@197 11 #+begin_src clojure
rlm@182 12 (ns cortex.sense
rlm@183 13 "Here are functions useful in the construction of two or more
rlm@183 14 sensors/effectors."
rlm@182 15 {:author "Robert McInytre"}
rlm@182 16 (:use (cortex world util))
rlm@182 17 (:import ij.process.ImageProcessor)
rlm@182 18 (:import jme3tools.converters.ImageToAwt)
rlm@182 19 (:import java.awt.image.BufferedImage)
rlm@182 20 (:import com.jme3.collision.CollisionResults)
rlm@182 21 (:import com.jme3.bounding.BoundingBox)
rlm@182 22 (:import (com.jme3.scene Node Spatial))
rlm@182 23 (:import com.jme3.scene.control.AbstractControl)
rlm@182 24 (:import (com.jme3.math Quaternion Vector3f)))
rlm@197 25 #+end_src
rlm@151 26
rlm@197 27 * Blender Utilities
rlm@197 28 #+name: blender
rlm@197 29 #+begin_src clojure
rlm@181 30 (defn meta-data
rlm@181 31 "Get the meta-data for a node created with blender."
rlm@181 32 [blender-node key]
rlm@151 33 (if-let [data (.getUserData blender-node "properties")]
rlm@151 34 (.findValue data key)
rlm@151 35 nil))
rlm@151 36
rlm@197 37 (defn jme-to-blender
rlm@197 38 "Convert from JME coordinates to Blender coordinates"
rlm@197 39 [#^Vector3f in]
rlm@197 40 (Vector3f. (.getX in)
rlm@197 41 (- (.getZ in))
rlm@197 42 (.getY in)))
rlm@151 43
rlm@197 44 (defn blender-to-jme
rlm@197 45 "Convert from Blender coordinates to JME coordinates"
rlm@197 46 [#^Vector3f in]
rlm@197 47 (Vector3f. (.getX in)
rlm@197 48 (.getZ in)
rlm@197 49 (- (.getY in))))
rlm@197 50 #+end_src
rlm@197 51
rlm@197 52 * Topology Related stuff
rlm@197 53 #+name: topology
rlm@197 54 #+begin_src clojure
rlm@197 55 (defn load-image
rlm@197 56 "Load an image as a BufferedImage using the asset-manager system."
rlm@197 57 [asset-relative-path]
rlm@197 58 (ImageToAwt/convert
rlm@197 59 (.getImage (.loadTexture (asset-manager) asset-relative-path))
rlm@197 60 false false 0))
rlm@151 61
rlm@181 62 (def white 0xFFFFFF)
rlm@181 63
rlm@181 64 (defn white? [rgb]
rlm@181 65 (= (bit-and white rgb) white))
rlm@181 66
rlm@151 67 (defn filter-pixels
rlm@151 68 "List the coordinates of all pixels matching pred, within the bounds
rlm@182 69 provided.
rlm@182 70 bounds -> [x0 y0 width height]"
rlm@151 71 {:author "Dylan Holmes"}
rlm@151 72 ([pred #^BufferedImage image]
rlm@151 73 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
rlm@151 74 ([pred #^BufferedImage image [x0 y0 width height]]
rlm@151 75 ((fn accumulate [x y matches]
rlm@151 76 (cond
rlm@151 77 (>= y (+ height y0)) matches
rlm@151 78 (>= x (+ width x0)) (recur 0 (inc y) matches)
rlm@151 79 (pred (.getRGB image x y))
rlm@151 80 (recur (inc x) y (conj matches [x y]))
rlm@151 81 :else (recur (inc x) y matches)))
rlm@151 82 x0 y0 [])))
rlm@151 83
rlm@151 84 (defn white-coordinates
rlm@151 85 "Coordinates of all the white pixels in a subset of the image."
rlm@151 86 ([#^BufferedImage image bounds]
rlm@181 87 (filter-pixels white? image bounds))
rlm@151 88 ([#^BufferedImage image]
rlm@181 89 (filter-pixels white? image)))
rlm@151 90
rlm@151 91 (defn points->image
rlm@151 92 "Take a sparse collection of points and visuliaze it as a
rlm@151 93 BufferedImage."
rlm@151 94 [points]
rlm@151 95 (if (empty? points)
rlm@151 96 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
rlm@151 97 (let [xs (vec (map first points))
rlm@151 98 ys (vec (map second points))
rlm@151 99 x0 (apply min xs)
rlm@151 100 y0 (apply min ys)
rlm@151 101 width (- (apply max xs) x0)
rlm@151 102 height (- (apply max ys) y0)
rlm@151 103 image (BufferedImage. (inc width) (inc height)
rlm@151 104 BufferedImage/TYPE_INT_RGB)]
rlm@151 105 (dorun
rlm@151 106 (for [x (range (.getWidth image))
rlm@151 107 y (range (.getHeight image))]
rlm@151 108 (.setRGB image x y 0xFF0000)))
rlm@151 109 (dorun
rlm@151 110 (for [index (range (count points))]
rlm@151 111 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
rlm@151 112 image)))
rlm@151 113
rlm@151 114 (defn average [coll]
rlm@151 115 (/ (reduce + coll) (count coll)))
rlm@151 116
rlm@151 117 (defn collapse-1d
rlm@182 118 "One dimensional analogue of collapse."
rlm@151 119 [center line]
rlm@151 120 (let [length (count line)
rlm@151 121 num-above (count (filter (partial < center) line))
rlm@151 122 num-below (- length num-above)]
rlm@151 123 (range (- center num-below)
rlm@151 124 (+ center num-above))))
rlm@151 125
rlm@151 126 (defn collapse
rlm@151 127 "Take a set of pairs of integers and collapse them into a
rlm@182 128 contigous bitmap with no \"holes\"."
rlm@151 129 [points]
rlm@151 130 (if (empty? points) []
rlm@151 131 (let
rlm@151 132 [num-points (count points)
rlm@151 133 center (vector
rlm@151 134 (int (average (map first points)))
rlm@151 135 (int (average (map first points))))
rlm@151 136 flattened
rlm@151 137 (reduce
rlm@151 138 concat
rlm@151 139 (map
rlm@151 140 (fn [column]
rlm@151 141 (map vector
rlm@151 142 (map first column)
rlm@151 143 (collapse-1d (second center)
rlm@151 144 (map second column))))
rlm@151 145 (partition-by first (sort-by first points))))
rlm@151 146 squeezed
rlm@151 147 (reduce
rlm@151 148 concat
rlm@151 149 (map
rlm@151 150 (fn [row]
rlm@151 151 (map vector
rlm@151 152 (collapse-1d (first center)
rlm@151 153 (map first row))
rlm@151 154 (map second row)))
rlm@151 155 (partition-by second (sort-by second flattened))))
rlm@182 156 relocated
rlm@151 157 (let [min-x (apply min (map first squeezed))
rlm@151 158 min-y (apply min (map second squeezed))]
rlm@151 159 (map (fn [[x y]]
rlm@151 160 [(- x min-x)
rlm@151 161 (- y min-y)])
rlm@151 162 squeezed))]
rlm@182 163 relocated)))
rlm@151 164
rlm@197 165 #+end_src
rlm@197 166
rlm@197 167 * Node level stuff
rlm@197 168 #+name: node
rlm@197 169 #+begin_src clojure
rlm@197 170 (defn closest-node
rlm@197 171 "Return the node in creature which is closest to the given node."
rlm@197 172 [#^Node creature #^Node eye]
rlm@197 173 (loop [radius (float 0.01)]
rlm@197 174 (let [results (CollisionResults.)]
rlm@197 175 (.collideWith
rlm@197 176 creature
rlm@197 177 (BoundingBox. (.getWorldTranslation eye)
rlm@197 178 radius radius radius)
rlm@197 179 results)
rlm@197 180 (if-let [target (first results)]
rlm@197 181 (.getGeometry target)
rlm@197 182 (recur (float (* 2 radius)))))))
rlm@197 183
rlm@197 184 (defn bind-sense
rlm@197 185 "Bind the sense to the Spatial such that it will maintain its
rlm@197 186 current position relative to the Spatial no matter how the spatial
rlm@197 187 moves. 'sense can be either a Camera or Listener object."
rlm@197 188 [#^Spatial obj sense]
rlm@197 189 (let [sense-offset (.subtract (.getLocation sense)
rlm@197 190 (.getWorldTranslation obj))
rlm@197 191 initial-sense-rotation (Quaternion. (.getRotation sense))
rlm@197 192 base-anti-rotation (.inverse (.getWorldRotation obj))]
rlm@197 193 (.addControl
rlm@197 194 obj
rlm@197 195 (proxy [AbstractControl] []
rlm@197 196 (controlUpdate [tpf]
rlm@197 197 (let [total-rotation
rlm@197 198 (.mult base-anti-rotation (.getWorldRotation obj))]
rlm@197 199 (.setLocation
rlm@197 200 sense
rlm@197 201 (.add
rlm@197 202 (.mult total-rotation sense-offset)
rlm@197 203 (.getWorldTranslation obj)))
rlm@197 204 (.setRotation
rlm@197 205 sense
rlm@197 206 (.mult total-rotation initial-sense-rotation))))
rlm@197 207 (controlRender [_ _])))))
rlm@197 208
rlm@156 209 (defn world-to-local
rlm@182 210 "Convert the world coordinates into coordinates relative to the
rlm@156 211 object (i.e. local coordinates), taking into account the rotation
rlm@156 212 of object."
rlm@182 213 [#^Spatial object world-coordinate]
rlm@182 214 (.worldToLocal object world-coordinate nil))
rlm@156 215
rlm@156 216 (defn local-to-world
rlm@182 217 "Convert the local coordinates into world relative coordinates"
rlm@182 218 [#^Spatial object local-coordinate]
rlm@182 219 (.localToWorld object local-coordinate nil))
rlm@156 220
rlm@182 221 (defn sense-nodes
rlm@182 222 "For each sense there is a special blender node whose children are
rlm@182 223 considered markers for an instance of a that sense. This function
rlm@182 224 generates functions to find those children, given the name of the
rlm@182 225 special parent node."
rlm@182 226 [parent-name]
rlm@164 227 (fn [#^Node creature]
rlm@164 228 (if-let [sense-node (.getChild creature parent-name)]
rlm@164 229 (seq (.getChildren sense-node))
rlm@164 230 (do (println-repl "could not find" parent-name "node") []))))
rlm@197 231 #+end_src
rlm@164 232
rlm@197 233 * Viewing Senses
rlm@197 234 #+name view-senses
rlm@197 235 #+begin_src clojure
rlm@187 236 (defn view-sense
rlm@197 237 "Take a kernel that produces a BufferedImage from some sense data
rlm@197 238 and return a function which takes a list of sense data, uses the
rlm@197 239 kernem to convert to images, and displays those images, each in
rlm@197 240 its own JFrame."
rlm@187 241 [sense-display-kernel]
rlm@197 242 (let [windows (atom [])]
rlm@187 243 (fn [data]
rlm@187 244 (if (> (count data) (count @windows))
rlm@197 245 (reset!
rlm@197 246 windows (map (fn [_] (view-image)) (range (count data)))))
rlm@187 247 (dorun
rlm@187 248 (map
rlm@188 249 (fn [display datum]
rlm@188 250 (display (sense-display-kernel datum)))
rlm@188 251 @windows data)))))
rlm@187 252
rlm@188 253 (defn gray
rlm@197 254 "Create a gray RGB pixel with R, G, and B set to num. num must be
rlm@197 255 between 0 and 255."
rlm@188 256 [num]
rlm@188 257 (+ num
rlm@188 258 (bit-shift-left num 8)
rlm@188 259 (bit-shift-left num 16)))
rlm@188 260 #+end_src
rlm@187 261
rlm@151 262 * COMMENT generate source
rlm@151 263 #+begin_src clojure :tangle ../src/cortex/sense.clj
rlm@197 264 <<header>>
rlm@197 265 <<blender>>
rlm@197 266 <<topology>>
rlm@197 267 <<node>>
rlm@197 268 <<view-senses>>
rlm@151 269 #+end_src