changeset 183:446b115bddc2

renamed sense-util.org to sense.org.
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 07:49:46 -0700
parents f2552d61e8df
children bdca0daa3778
files org/sense-util.org sense.org
diffstat 2 files changed, 223 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/org/sense-util.org	Sat Feb 04 07:44:48 2012 -0700
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,227 +0,0 @@
     1.4 -#+title: General sense/effector utilities
     1.5 -#+author: Robert McIntyre
     1.6 -#+email: rlm@mit.edu
     1.7 -#+description: sensory utilities
     1.8 -#+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
     1.9 -#+SETUPFILE: ../../aurellem/org/setup.org
    1.10 -#+INCLUDE: ../../aurellem/org/level-0.org
    1.11 -
    1.12 -#+name: sense-util
    1.13 -#+begin_src clojure 
    1.14 -(ns cortex.sense
    1.15 -  "Here are functions usefull in the construction of two or more
    1.16 -  senses/effectors."
    1.17 -  {:author "Robert McInytre"}
    1.18 -  (:use (cortex world util))
    1.19 -  (:import ij.process.ImageProcessor)
    1.20 -  (:import jme3tools.converters.ImageToAwt)
    1.21 -  (:import java.awt.image.BufferedImage)
    1.22 -  (:import com.jme3.collision.CollisionResults)
    1.23 -  (:import com.jme3.bounding.BoundingBox)
    1.24 -  (:import (com.jme3.scene Node Spatial))
    1.25 -  (:import com.jme3.scene.control.AbstractControl)
    1.26 -  (:import (com.jme3.math Quaternion Vector3f)))
    1.27 -
    1.28 -(defn meta-data
    1.29 -  "Get the meta-data for a node created with blender."
    1.30 -  [blender-node key]
    1.31 -  (if-let [data (.getUserData blender-node "properties")]
    1.32 -    (.findValue data key)
    1.33 -    nil))
    1.34 -
    1.35 -(defn closest-node
    1.36 -  "Return the node in creature which is closest to the given node."
    1.37 -  [#^Node creature #^Node eye]
    1.38 -  (loop [radius (float 0.01)]
    1.39 -    (let [results (CollisionResults.)]
    1.40 -      (.collideWith
    1.41 -       creature
    1.42 -       (BoundingBox. (.getWorldTranslation eye)
    1.43 -                     radius radius radius)
    1.44 -       results)
    1.45 -      (if-let [target (first results)]
    1.46 -        (.getGeometry target)
    1.47 -        (recur (float (* 2 radius)))))))
    1.48 -
    1.49 -(defn bind-sense
    1.50 -  "Bind the sense to the Spatial such that it will maintain its
    1.51 -   current position relative to the Spatial no matter how the spatial
    1.52 -   moves. 'sense can be either a Camera or Listener object."
    1.53 -  [#^Spatial obj sense]
    1.54 -  (let [sense-offset (.subtract (.getLocation sense)
    1.55 -                                (.getWorldTranslation obj))
    1.56 -        initial-sense-rotation (Quaternion. (.getRotation sense))
    1.57 -        base-anti-rotation (.inverse (.getWorldRotation obj))]
    1.58 -    (.addControl
    1.59 -     obj
    1.60 -     (proxy [AbstractControl] []
    1.61 -       (controlUpdate [tpf]
    1.62 -         (let [total-rotation
    1.63 -               (.mult base-anti-rotation (.getWorldRotation obj))]
    1.64 -           (.setLocation
    1.65 -            sense
    1.66 -            (.add
    1.67 -             (.mult total-rotation sense-offset)
    1.68 -             (.getWorldTranslation obj)))
    1.69 -           (.setRotation
    1.70 -            sense
    1.71 -            (.mult total-rotation initial-sense-rotation))))
    1.72 -       (controlRender [_ _])))))
    1.73 -
    1.74 -(def white 0xFFFFFF)
    1.75 -
    1.76 -(defn white? [rgb]
    1.77 -  (= (bit-and white rgb) white))
    1.78 -
    1.79 -(defn filter-pixels
    1.80 -  "List the coordinates of all pixels matching pred, within the bounds
    1.81 -   provided.
    1.82 -   bounds -> [x0 y0 width height]"
    1.83 -  {:author "Dylan Holmes"}
    1.84 -  ([pred #^BufferedImage image]
    1.85 -     (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
    1.86 -  ([pred #^BufferedImage image [x0 y0 width height]]
    1.87 -     ((fn accumulate [x y matches]
    1.88 -        (cond
    1.89 -         (>= y (+ height y0)) matches
    1.90 -         (>= x (+ width x0)) (recur 0 (inc y) matches)
    1.91 -         (pred (.getRGB image x y))
    1.92 -         (recur (inc x) y (conj matches [x y]))
    1.93 -         :else (recur (inc x) y matches)))
    1.94 -      x0 y0 [])))
    1.95 -
    1.96 -(defn white-coordinates
    1.97 -  "Coordinates of all the white pixels in a subset of the image."
    1.98 -  ([#^BufferedImage image bounds]
    1.99 -     (filter-pixels white? image bounds))
   1.100 -  ([#^BufferedImage image]
   1.101 -     (filter-pixels white? image)))
   1.102 -
   1.103 -(defn points->image
   1.104 -  "Take a sparse collection of points and visuliaze it as a
   1.105 -   BufferedImage."
   1.106 -  [points]
   1.107 -  (if (empty? points)
   1.108 -    (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
   1.109 -    (let [xs (vec (map first points))
   1.110 -          ys (vec (map second points))
   1.111 -          x0 (apply min xs)
   1.112 -          y0 (apply min ys)
   1.113 -          width (- (apply max xs) x0)
   1.114 -          height (- (apply max ys) y0)
   1.115 -          image (BufferedImage. (inc width) (inc height)
   1.116 -                                BufferedImage/TYPE_INT_RGB)]
   1.117 -      (dorun
   1.118 -       (for [x (range (.getWidth image))
   1.119 -             y (range (.getHeight image))]
   1.120 -         (.setRGB image x y 0xFF0000)))
   1.121 -      (dorun 
   1.122 -       (for [index (range (count points))]
   1.123 -         (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
   1.124 -      image)))
   1.125 -
   1.126 -(defn average [coll]
   1.127 -  (/ (reduce + coll) (count coll)))
   1.128 -
   1.129 -(defn collapse-1d
   1.130 -  "One dimensional analogue of collapse."
   1.131 -  [center line]
   1.132 -  (let [length (count line)
   1.133 -        num-above (count (filter (partial < center) line))
   1.134 -        num-below (- length num-above)]
   1.135 -    (range (- center num-below)
   1.136 -           (+ center num-above))))
   1.137 -
   1.138 -(defn collapse
   1.139 -  "Take a set of pairs of integers and collapse them into a
   1.140 -   contigous bitmap with no \"holes\"."
   1.141 -  [points]
   1.142 -  (if (empty? points) []
   1.143 -      (let
   1.144 -          [num-points (count points)
   1.145 -           center (vector
   1.146 -                   (int (average (map first points)))
   1.147 -                   (int (average (map first points))))
   1.148 -           flattened
   1.149 -           (reduce
   1.150 -            concat 
   1.151 -            (map
   1.152 -             (fn [column]
   1.153 -               (map vector
   1.154 -                    (map first column)
   1.155 -                    (collapse-1d (second center)
   1.156 -                                 (map second column))))
   1.157 -             (partition-by first (sort-by first points))))
   1.158 -           squeezed
   1.159 -           (reduce
   1.160 -            concat 
   1.161 -            (map
   1.162 -             (fn [row]
   1.163 -               (map vector
   1.164 -                    (collapse-1d (first center)
   1.165 -                                 (map first row))
   1.166 -                    (map second row)))
   1.167 -             (partition-by second (sort-by second flattened))))
   1.168 -           relocated
   1.169 -           (let [min-x (apply min (map first squeezed))
   1.170 -                 min-y (apply min (map second squeezed))]
   1.171 -             (map (fn [[x y]]
   1.172 -                    [(- x min-x)
   1.173 -                     (- y min-y)])
   1.174 -                  squeezed))]
   1.175 -        relocated)))
   1.176 -
   1.177 -(defn world-to-local
   1.178 -  "Convert the world coordinates into coordinates relative to the 
   1.179 -   object (i.e. local coordinates), taking into account the rotation
   1.180 -   of object."
   1.181 -  [#^Spatial object world-coordinate]
   1.182 -  (.worldToLocal object world-coordinate nil))
   1.183 -
   1.184 -(defn local-to-world
   1.185 -  "Convert the local coordinates into world relative coordinates"
   1.186 -  [#^Spatial object local-coordinate]
   1.187 -  (.localToWorld object local-coordinate nil))
   1.188 -
   1.189 -(defn sense-nodes
   1.190 -  "For each sense there is a special blender node whose children are
   1.191 -   considered markers for an instance of a that sense. This function
   1.192 -   generates functions to find those children, given the name of the
   1.193 -   special parent node."
   1.194 -  [parent-name]
   1.195 -  (fn [#^Node creature]
   1.196 -    (if-let [sense-node (.getChild creature parent-name)]
   1.197 -      (seq (.getChildren sense-node))
   1.198 -      (do (println-repl "could not find" parent-name "node") []))))
   1.199 -
   1.200 -(defn load-image
   1.201 -  "Load an image as a BufferedImage using the asset-manager system." 
   1.202 -  [asset-relative-path]
   1.203 -  (ImageToAwt/convert
   1.204 -   (.getImage (.loadTexture (asset-manager) asset-relative-path))
   1.205 -   false false 0))
   1.206 -
   1.207 -(defn jme-to-blender
   1.208 -  "Convert from JME coordinates to Blender coordinates"
   1.209 -  [#^Vector3f in]
   1.210 -  (Vector3f. (.getX in)
   1.211 -             (- (.getZ in))
   1.212 -             (.getY in)))
   1.213 -
   1.214 -(defn blender-to-jme
   1.215 -  "Convert from Blender coordinates to JME coordinates"
   1.216 -  [#^Vector3f in]
   1.217 -  (Vector3f. (.getX in)
   1.218 -             (.getZ in)
   1.219 -             (- (.getY in))))
   1.220 -#+end_src
   1.221 -
   1.222 -#+results: sense-util
   1.223 -: #'cortex.sense/meta-data
   1.224 -
   1.225 -
   1.226 -
   1.227 -* COMMENT generate source
   1.228 -#+begin_src clojure :tangle ../src/cortex/sense.clj
   1.229 -<<sense-util>>
   1.230 -#+end_src
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/sense.org	Sat Feb 04 07:49:46 2012 -0700
     2.3 @@ -0,0 +1,223 @@
     2.4 +#+title: General sense/effector utilities
     2.5 +#+author: Robert McIntyre
     2.6 +#+email: rlm@mit.edu
     2.7 +#+description: sensory utilities
     2.8 +#+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
     2.9 +#+SETUPFILE: ../../aurellem/org/setup.org
    2.10 +#+INCLUDE: ../../aurellem/org/level-0.org
    2.11 +
    2.12 +#+name: sense
    2.13 +#+begin_src clojure 
    2.14 +(ns cortex.sense
    2.15 +  "Here are functions useful in the construction of two or more
    2.16 +   sensors/effectors."
    2.17 +  {:author "Robert McInytre"}
    2.18 +  (:use (cortex world util))
    2.19 +  (:import ij.process.ImageProcessor)
    2.20 +  (:import jme3tools.converters.ImageToAwt)
    2.21 +  (:import java.awt.image.BufferedImage)
    2.22 +  (:import com.jme3.collision.CollisionResults)
    2.23 +  (:import com.jme3.bounding.BoundingBox)
    2.24 +  (:import (com.jme3.scene Node Spatial))
    2.25 +  (:import com.jme3.scene.control.AbstractControl)
    2.26 +  (:import (com.jme3.math Quaternion Vector3f)))
    2.27 +
    2.28 +(defn meta-data
    2.29 +  "Get the meta-data for a node created with blender."
    2.30 +  [blender-node key]
    2.31 +  (if-let [data (.getUserData blender-node "properties")]
    2.32 +    (.findValue data key)
    2.33 +    nil))
    2.34 +
    2.35 +(defn closest-node
    2.36 +  "Return the node in creature which is closest to the given node."
    2.37 +  [#^Node creature #^Node eye]
    2.38 +  (loop [radius (float 0.01)]
    2.39 +    (let [results (CollisionResults.)]
    2.40 +      (.collideWith
    2.41 +       creature
    2.42 +       (BoundingBox. (.getWorldTranslation eye)
    2.43 +                     radius radius radius)
    2.44 +       results)
    2.45 +      (if-let [target (first results)]
    2.46 +        (.getGeometry target)
    2.47 +        (recur (float (* 2 radius)))))))
    2.48 +
    2.49 +(defn bind-sense
    2.50 +  "Bind the sense to the Spatial such that it will maintain its
    2.51 +   current position relative to the Spatial no matter how the spatial
    2.52 +   moves. 'sense can be either a Camera or Listener object."
    2.53 +  [#^Spatial obj sense]
    2.54 +  (let [sense-offset (.subtract (.getLocation sense)
    2.55 +                                (.getWorldTranslation obj))
    2.56 +        initial-sense-rotation (Quaternion. (.getRotation sense))
    2.57 +        base-anti-rotation (.inverse (.getWorldRotation obj))]
    2.58 +    (.addControl
    2.59 +     obj
    2.60 +     (proxy [AbstractControl] []
    2.61 +       (controlUpdate [tpf]
    2.62 +         (let [total-rotation
    2.63 +               (.mult base-anti-rotation (.getWorldRotation obj))]
    2.64 +           (.setLocation
    2.65 +            sense
    2.66 +            (.add
    2.67 +             (.mult total-rotation sense-offset)
    2.68 +             (.getWorldTranslation obj)))
    2.69 +           (.setRotation
    2.70 +            sense
    2.71 +            (.mult total-rotation initial-sense-rotation))))
    2.72 +       (controlRender [_ _])))))
    2.73 +
    2.74 +(def white 0xFFFFFF)
    2.75 +
    2.76 +(defn white? [rgb]
    2.77 +  (= (bit-and white rgb) white))
    2.78 +
    2.79 +(defn filter-pixels
    2.80 +  "List the coordinates of all pixels matching pred, within the bounds
    2.81 +   provided.
    2.82 +   bounds -> [x0 y0 width height]"
    2.83 +  {:author "Dylan Holmes"}
    2.84 +  ([pred #^BufferedImage image]
    2.85 +     (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
    2.86 +  ([pred #^BufferedImage image [x0 y0 width height]]
    2.87 +     ((fn accumulate [x y matches]
    2.88 +        (cond
    2.89 +         (>= y (+ height y0)) matches
    2.90 +         (>= x (+ width x0)) (recur 0 (inc y) matches)
    2.91 +         (pred (.getRGB image x y))
    2.92 +         (recur (inc x) y (conj matches [x y]))
    2.93 +         :else (recur (inc x) y matches)))
    2.94 +      x0 y0 [])))
    2.95 +
    2.96 +(defn white-coordinates
    2.97 +  "Coordinates of all the white pixels in a subset of the image."
    2.98 +  ([#^BufferedImage image bounds]
    2.99 +     (filter-pixels white? image bounds))
   2.100 +  ([#^BufferedImage image]
   2.101 +     (filter-pixels white? image)))
   2.102 +
   2.103 +(defn points->image
   2.104 +  "Take a sparse collection of points and visuliaze it as a
   2.105 +   BufferedImage."
   2.106 +  [points]
   2.107 +  (if (empty? points)
   2.108 +    (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
   2.109 +    (let [xs (vec (map first points))
   2.110 +          ys (vec (map second points))
   2.111 +          x0 (apply min xs)
   2.112 +          y0 (apply min ys)
   2.113 +          width (- (apply max xs) x0)
   2.114 +          height (- (apply max ys) y0)
   2.115 +          image (BufferedImage. (inc width) (inc height)
   2.116 +                                BufferedImage/TYPE_INT_RGB)]
   2.117 +      (dorun
   2.118 +       (for [x (range (.getWidth image))
   2.119 +             y (range (.getHeight image))]
   2.120 +         (.setRGB image x y 0xFF0000)))
   2.121 +      (dorun 
   2.122 +       (for [index (range (count points))]
   2.123 +         (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
   2.124 +      image)))
   2.125 +
   2.126 +(defn average [coll]
   2.127 +  (/ (reduce + coll) (count coll)))
   2.128 +
   2.129 +(defn collapse-1d
   2.130 +  "One dimensional analogue of collapse."
   2.131 +  [center line]
   2.132 +  (let [length (count line)
   2.133 +        num-above (count (filter (partial < center) line))
   2.134 +        num-below (- length num-above)]
   2.135 +    (range (- center num-below)
   2.136 +           (+ center num-above))))
   2.137 +
   2.138 +(defn collapse
   2.139 +  "Take a set of pairs of integers and collapse them into a
   2.140 +   contigous bitmap with no \"holes\"."
   2.141 +  [points]
   2.142 +  (if (empty? points) []
   2.143 +      (let
   2.144 +          [num-points (count points)
   2.145 +           center (vector
   2.146 +                   (int (average (map first points)))
   2.147 +                   (int (average (map first points))))
   2.148 +           flattened
   2.149 +           (reduce
   2.150 +            concat 
   2.151 +            (map
   2.152 +             (fn [column]
   2.153 +               (map vector
   2.154 +                    (map first column)
   2.155 +                    (collapse-1d (second center)
   2.156 +                                 (map second column))))
   2.157 +             (partition-by first (sort-by first points))))
   2.158 +           squeezed
   2.159 +           (reduce
   2.160 +            concat 
   2.161 +            (map
   2.162 +             (fn [row]
   2.163 +               (map vector
   2.164 +                    (collapse-1d (first center)
   2.165 +                                 (map first row))
   2.166 +                    (map second row)))
   2.167 +             (partition-by second (sort-by second flattened))))
   2.168 +           relocated
   2.169 +           (let [min-x (apply min (map first squeezed))
   2.170 +                 min-y (apply min (map second squeezed))]
   2.171 +             (map (fn [[x y]]
   2.172 +                    [(- x min-x)
   2.173 +                     (- y min-y)])
   2.174 +                  squeezed))]
   2.175 +        relocated)))
   2.176 +
   2.177 +(defn world-to-local
   2.178 +  "Convert the world coordinates into coordinates relative to the 
   2.179 +   object (i.e. local coordinates), taking into account the rotation
   2.180 +   of object."
   2.181 +  [#^Spatial object world-coordinate]
   2.182 +  (.worldToLocal object world-coordinate nil))
   2.183 +
   2.184 +(defn local-to-world
   2.185 +  "Convert the local coordinates into world relative coordinates"
   2.186 +  [#^Spatial object local-coordinate]
   2.187 +  (.localToWorld object local-coordinate nil))
   2.188 +
   2.189 +(defn sense-nodes
   2.190 +  "For each sense there is a special blender node whose children are
   2.191 +   considered markers for an instance of a that sense. This function
   2.192 +   generates functions to find those children, given the name of the
   2.193 +   special parent node."
   2.194 +  [parent-name]
   2.195 +  (fn [#^Node creature]
   2.196 +    (if-let [sense-node (.getChild creature parent-name)]
   2.197 +      (seq (.getChildren sense-node))
   2.198 +      (do (println-repl "could not find" parent-name "node") []))))
   2.199 +
   2.200 +(defn load-image
   2.201 +  "Load an image as a BufferedImage using the asset-manager system." 
   2.202 +  [asset-relative-path]
   2.203 +  (ImageToAwt/convert
   2.204 +   (.getImage (.loadTexture (asset-manager) asset-relative-path))
   2.205 +   false false 0))
   2.206 +
   2.207 +(defn jme-to-blender
   2.208 +  "Convert from JME coordinates to Blender coordinates"
   2.209 +  [#^Vector3f in]
   2.210 +  (Vector3f. (.getX in)
   2.211 +             (- (.getZ in))
   2.212 +             (.getY in)))
   2.213 +
   2.214 +(defn blender-to-jme
   2.215 +  "Convert from Blender coordinates to JME coordinates"
   2.216 +  [#^Vector3f in]
   2.217 +  (Vector3f. (.getX in)
   2.218 +             (.getZ in)
   2.219 +             (- (.getY in))))
   2.220 +#+end_src
   2.221 +
   2.222 +
   2.223 +* COMMENT generate source
   2.224 +#+begin_src clojure :tangle ../src/cortex/sense.clj
   2.225 +<<sense>>
   2.226 +#+end_src