Mercurial > cortex
view org/skin.org @ 76:5e75b616ca60
going to work on constraints for the joints in the hand.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Wed, 28 Dec 2011 23:12:32 -0700 |
parents | 39e4e1542e4a |
children | e8df6e76c3e5 |
line wrap: on
line source
1 #+title: Simulated Sense of Touch2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: Simulated touch for AI research using JMonkeyEngine and clojure.5 #+keywords: simulation, tactile sense, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org10 * Touch12 My creatures need to be able to feel their environments. The idea here13 is to create thousands of small /touch receptors/ along the geometries14 which make up the creature's body. The number of touch receptors in a15 given area is determined by how complicated that area is, as16 determined by the total number of triangles in that region. This way,17 complicated regions like the hands/face, etc. get more touch receptors18 than simpler areas of the body.20 #+name: skin-main21 #+begin_src clojure22 (ns cortex.touch23 "Simulate the sense of touch in jMonkeyEngine3. Enables any Geometry24 to be outfitted with touch sensors with density proportional to the25 density of triangles along the surface of the Geometry. Enables a26 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 triangles34 "Return a sequence of all the Triangles which compose a given35 Geometry."36 [#^Geometry geom]37 (let38 [mesh (.getMesh geom)39 triangles (transient [])]40 (dorun41 (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-origin50 "Return the origin which a Ray would have to have to be in the exact51 center of a particular Triangle in the Geometry in World52 Coordinates."53 [geom tri]54 (let [new (Vector3f.)]55 (.calculateCenter tri)56 (.localToWorld geom (.getCenter tri) new) new))58 (defn get-ray-direction59 "Return the direction which a Ray would have to have to be in the60 exact center of a particular Triangle in the Geometry, pointing61 normal to the Triangle, in coordinates relative to the center of the62 Triangle."63 [geom tri]64 (let [n+c (Vector3f.)]65 (.calculateNormal tri)66 (.calculateCenter tri)67 (.localToWorld68 geom69 (.add (.getCenter tri) (.getNormal tri)) n+c)70 (.subtract n+c (get-ray-origin geom tri))))72 (defn normal-rays73 "For each Triangle which comprises the Geometry, returns a Ray which74 is centered on that Triangle, points outward in a normal direction,75 and extends for =limit= distance."76 [limit #^Geometry geom]77 (vec78 (map79 (fn [tri]80 (doto81 (Ray. (get-ray-origin geom tri)82 (get-ray-direction geom tri))83 (.setLimit limit)))84 (triangles geom))))86 (defn touch-percieve87 "Augment a Geometry with the sense of touch. Returns a sequence of88 non-negative integers, one for each triangle, with the value of the89 integer describing how many objects a ray of length =limit=, normal90 to the triangle and originating from its center, encountered. The91 Geometry itself is not counted among the results."92 [limit geom node]93 (let [normals (normal-rays limit geom)]94 (doall95 (for [ray normals]96 (do97 (let [results (CollisionResults.)]98 (.collideWith node ray results)99 (let [touch-objects100 (set (filter #(not (= geom %))101 (map #(.getGeometry %) results)))]102 (count touch-objects))))))))103 #+end_src106 * Example108 #+name: touch-test109 #+begin_src clojure110 (ns cortex.test.touch111 (:use (cortex world util touch))112 (:import113 com.jme3.scene.shape.Sphere114 com.jme3.math.ColorRGBA115 com.jme3.math.Vector3f116 com.jme3.material.RenderState$BlendMode117 com.jme3.renderer.queue.RenderQueue$Bucket118 com.jme3.scene.shape.Box119 com.jme3.scene.Node))121 (defn ray-origin-debug122 [ray color]123 (make-shape124 (assoc base-shape125 :shape (Sphere. 5 5 0.05)126 :name "arrow"127 :color color128 :texture false129 :physical? false130 :position131 (.getOrigin ray))))133 (defn ray-debug [ray color]134 (make-shape135 (assoc136 base-shape137 :name "debug-ray"138 :physical? false139 :shape (com.jme3.scene.shape.Line.140 (.getOrigin ray)141 (.add142 (.getOrigin ray)143 (.mult (.getDirection ray)144 (float (.getLimit ray))))))))147 (defn contact-color [contacts]148 (case contacts149 0 ColorRGBA/Gray150 1 ColorRGBA/Red151 2 ColorRGBA/Green152 3 ColorRGBA/Yellow153 4 ColorRGBA/Orange154 5 ColorRGBA/Red155 6 ColorRGBA/Magenta156 7 ColorRGBA/Pink157 8 ColorRGBA/White))159 (defn update-ray-debug [node ray contacts]160 (let [origin (.getChild node 0)]161 (.setLocalTranslation origin (.getOrigin ray))162 (.setColor (.getMaterial origin) "Color" (contact-color contacts))))164 (defn init-node165 [debug-node rays]166 (.detachAllChildren debug-node)167 (dorun168 (for [ray rays]169 (do170 (.attachChild171 debug-node172 (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 (dorun182 (for [n (range (count touch-data))]183 (update-ray-debug184 (.getChild debug-node n) (nth rays n) (nth touch-data n))))))186 (defn transparent-sphere []187 (doto188 (make-shape189 (merge base-shape190 {:position (Vector3f. 0 2 0)191 :name "the blob."192 :material "Common/MatDefs/Misc/Unshaded.j3md"193 :texture "Textures/purpleWisp.png"194 :physical? true195 :mass 70196 :color ColorRGBA/Blue197 :shape (Sphere. 10 10 1)}))198 (-> (.getMaterial)199 (.getAdditionalRenderState)200 (.setBlendMode RenderState$BlendMode/Alpha))201 (.setQueueBucket RenderQueue$Bucket/Transparent)))203 (defn transparent-box []204 (doto205 (make-shape206 (merge base-shape207 {:position (Vector3f. 0 2 0)208 :name "box"209 :material "Common/MatDefs/Misc/Unshaded.j3md"210 :texture "Textures/purpleWisp.png"211 :physical? true212 :mass 70213 :color ColorRGBA/Blue214 :shape (Box. 1 1 1)}))215 (-> (.getMaterial)216 (.getAdditionalRenderState)217 (.setBlendMode RenderState$BlendMode/Alpha))218 (.setQueueBucket RenderQueue$Bucket/Transparent)))220 (defn transparent-floor []221 (doto222 (box 5 0.2 5 :mass 0 :position (Vector3f. 0 -2 0)223 :material "Common/MatDefs/Misc/Unshaded.j3md"224 :texture "Textures/redWisp.png"225 :name "floor")226 (-> (.getMaterial)227 (.getAdditionalRenderState)228 (.setBlendMode RenderState$BlendMode/Alpha))229 (.setQueueBucket RenderQueue$Bucket/Transparent)))231 (defn test-skin232 "Testing touch:233 you should see a ball which responds to the table234 and whatever balls hit it."235 []236 (let [b237 ;;(transparent-box)238 (transparent-sphere)239 ;;(sphere)240 f (transparent-floor)241 debug-node (Node.)242 node (doto (Node.) (.attachChild b) (.attachChild f))243 root-node (doto (Node.) (.attachChild node)244 (.attachChild debug-node))245 ]247 (world248 root-node249 {"key-return" (fire-cannon-ball node)}250 (fn [world]251 ;; (Capture/SimpleCaptureVideo252 ;; world253 ;; (file-str "/home/r/proj/cortex/tmp/blob.avi"))254 ;; (no-logging)255 ;;(enable-debug world)256 ;; (set-accuracy world (/ 1 60))257 )259 (fn [& _]260 (let [sensitivity 0.2261 touch-data (touch-percieve sensitivity b node)]262 (manage-ray-debug-node debug-node b touch-data sensitivity))263 ))))266 #+end_src272 * COMMENT code generation273 #+begin_src clojure :tangle ../src/cortex/touch.clj274 <<skin-main>>275 #+end_src277 #+begin_src clojure :tangle ../src/cortex/test/touch.clj278 <<touch-test>>279 #+end_src