Mercurial > cortex
comparison org/touch.org @ 249:95a9f6f1cb82
added touch-cube and fixed some problems with touch which it flushed out
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 13 Feb 2012 06:06:02 -0700 |
parents | 267add63b168 |
children | e9bce4f722b1 |
comparison
equal
deleted
inserted
replaced
248:267add63b168 | 249:95a9f6f1cb82 |
---|---|
381 (defn set-ray [#^Ray ray #^Matrix4f transform | 381 (defn set-ray [#^Ray ray #^Matrix4f transform |
382 #^Vector3f origin #^Vector3f tip] | 382 #^Vector3f origin #^Vector3f tip] |
383 ;; Doing everything locally recduces garbage collection by enough to | 383 ;; Doing everything locally recduces garbage collection by enough to |
384 ;; be worth it. | 384 ;; be worth it. |
385 (.mult transform origin (.getOrigin ray)) | 385 (.mult transform origin (.getOrigin ray)) |
386 | |
387 (.mult transform tip (.getDirection ray)) | 386 (.mult transform tip (.getDirection ray)) |
388 (.subtractLocal (.getDirection ray) (.getOrigin ray))) | 387 (.subtractLocal (.getDirection ray) (.getOrigin ray)) |
389 | 388 (.normalizeLocal (.getDirection ray))) |
389 | |
390 (import com.jme3.math.FastMath) | |
391 | |
392 | |
390 (defn touch-kernel | 393 (defn touch-kernel |
391 "Constructs a function which will return tactile sensory data from | 394 "Constructs a function which will return tactile sensory data from |
392 'geo when called from inside a running simulation" | 395 'geo when called from inside a running simulation" |
393 [#^Geometry geo] | 396 [#^Geometry geo] |
394 (if-let | 397 (if-let |
395 [profile (tactile-sensor-profile geo)] | 398 [profile (tactile-sensor-profile geo)] |
396 (let [ray-reference-origins (feeler-origins geo profile) | 399 (let [ray-reference-origins (feeler-origins geo profile) |
397 ray-reference-tips (feeler-tips geo profile) | 400 ray-reference-tips (feeler-tips geo profile) |
398 ray-length (tactile-scale geo) | 401 ray-length (tactile-scale geo) |
399 current-rays (map (fn [_] (Ray.)) ray-reference-origins) | 402 current-rays (map (fn [_] (Ray.)) ray-reference-origins) |
400 topology (touch-topology geo profile)] | 403 topology (touch-topology geo profile) |
404 correction (float (* ray-length -0.2))] | |
405 | |
406 ;; slight tolerance for very close collisions. | |
407 (dorun | |
408 (map (fn [origin tip] | |
409 (.addLocal origin (.mult (.subtract tip origin) | |
410 correction))) | |
411 ray-reference-origins ray-reference-tips)) | |
401 (dorun (map #(.setLimit % ray-length) current-rays)) | 412 (dorun (map #(.setLimit % ray-length) current-rays)) |
402 (fn [node] | 413 (fn [node] |
403 (let [transform (.getWorldMatrix geo)] | 414 (let [transform (.getWorldMatrix geo)] |
404 (dorun | 415 (dorun |
405 (map (fn [ray ref-origin ref-tip] | 416 (map (fn [ray ref-origin ref-tip] |
413 (do | 424 (do |
414 (let [results (CollisionResults.)] | 425 (let [results (CollisionResults.)] |
415 (.collideWith node ray results) | 426 (.collideWith node ray results) |
416 (let [touch-objects | 427 (let [touch-objects |
417 (filter #(not (= geo (.getGeometry %))) | 428 (filter #(not (= geo (.getGeometry %))) |
418 results)] | 429 results) |
430 limit (.getLimit ray)] | |
419 [(if (empty? touch-objects) | 431 [(if (empty? touch-objects) |
420 (.getLimit ray) | 432 limit |
421 (.getDistance (first touch-objects))) | 433 (let [response |
422 (.getLimit ray)]))))))))))) | 434 (apply min (map #(.getDistance %) |
435 touch-objects))] | |
436 (FastMath/clamp | |
437 (float | |
438 (if (> response limit) 0.0 | |
439 (+ response correction))) | |
440 (float 0.0) | |
441 limit))) | |
442 limit]))))))))))) | |
423 | 443 |
424 (defn touch! | 444 (defn touch! |
425 "Endow the creature with the sense of touch. Returns a sequence of | 445 "Endow the creature with the sense of touch. Returns a sequence of |
426 functions, one for each body part with a tactile-sensor-proile, | 446 functions, one for each body part with a tactile-sensor-proile, |
427 each of which when called returns sensory data for that body part." | 447 each of which when called returns sensory data for that body part." |
431 (map touch-kernel | 451 (map touch-kernel |
432 (filter #(isa? (class %) Geometry) | 452 (filter #(isa? (class %) Geometry) |
433 (node-seq creature))))) | 453 (node-seq creature))))) |
434 #+end_src | 454 #+end_src |
435 | 455 |
456 #+results: kernel | |
457 : #'cortex.touch/touch! | |
458 | |
436 * Visualizing Touch | 459 * Visualizing Touch |
460 | |
461 Each feeler is represented in the image as a single pixel. The | |
462 grayscale value of each pixel represents how deep the feeler | |
463 represented by that pixel is inside another object. Black means that | |
464 nothing is touching the feeler, while white means that the feeler is | |
465 completely inside another object, which is presumably flush with the | |
466 surface of the triangle from which the feeler originates. | |
437 | 467 |
438 #+name: visualization | 468 #+name: visualization |
439 #+begin_src clojure | 469 #+begin_src clojure |
440 (in-ns 'cortex.touch) | 470 (in-ns 'cortex.touch) |
441 | 471 |
451 (view-sense | 481 (view-sense |
452 (fn [[coords sensor-data]] | 482 (fn [[coords sensor-data]] |
453 (let [image (points->image coords)] | 483 (let [image (points->image coords)] |
454 (dorun | 484 (dorun |
455 (for [i (range (count coords))] | 485 (for [i (range (count coords))] |
456 (.setRGB image ((coords i) 0) ((coords i) 1) | 486 (do |
457 (apply touch->gray (sensor-data i))))) image)))) | 487 (if (= i 500) (println-repl (sensor-data i))) |
458 #+end_src | 488 |
489 (comment | |
490 (.setRGB image ((coords i) 0) ((coords i) 1) | |
491 (apply touch->gray (sensor-data i))))))) | |
492 image)))) | |
493 #+end_src | |
494 | |
495 #+results: visualization | |
496 : #'cortex.touch/view-touch | |
497 | |
498 * COMMENT Basic Test of Touch | |
499 | |
500 The worm's sense of touch is a bit complicated, so for this basic test | |
501 I'll use a new creature --- a simple cube which has touch sensors | |
502 evenly distributed along each of its sides. | |
503 | |
504 #+begin_src clojure | |
505 (in-ns 'cortex.test.touch) | |
506 | |
507 (defn touch-cube [] | |
508 (load-blender-model "Models/test-touch/touch-cube.blend")) | |
509 #+end_src | |
510 | |
511 #+begin_html | |
512 <br> | |
513 #+end_html | |
514 | |
515 #+begin_html | |
516 <div class="figure"> | |
517 <center> | |
518 <video controls="controls" width="500"> | |
519 <source src="../video/touch-cube.ogg" type="video/ogg" | |
520 preload="none" poster="../images/aurellem-1280x480.png" /> | |
521 </video> | |
522 </center> | |
523 <p>A simple creature with evenly distributed touch sensors.</p> | |
524 </div> | |
525 #+end_html | |
526 | |
527 The tactile-sensor-profile image for this simple creature looks like | |
528 this: | |
529 | |
530 #+attr_html: width=500 | |
531 #+caption: The distribution of feelers along the touch-cube. The colors of the faces are irrelevant; only the white pixels specify feelers. | |
532 [[../images/touch-profile.png]] | |
533 | |
534 #+begin_src clojure | |
535 (in-ns 'cortex.test.touch) | |
536 | |
537 (defn test-basic-touch | |
538 ([] (test-basic-touch false)) | |
539 ([record?] | |
540 (let [the-cube (doto (touch-cube) (body!)) | |
541 touch (touch! the-cube) | |
542 touch-display (view-touch)] | |
543 (world (nodify [the-cube | |
544 (box 10 1 10 :position (Vector3f. 0 -10 0) | |
545 :color ColorRGBA/Gray :mass 0)]) | |
546 | |
547 standard-debug-controls | |
548 | |
549 (fn [world] | |
550 (speed-up world) | |
551 (light-up-everything world)) | |
552 | |
553 (fn [world tpf] | |
554 (touch-display | |
555 (map #(% (.getRootNode world)) touch))))))) | |
556 | |
557 | |
558 #+end_src | |
559 | |
459 * Adding Touch to the Worm | 560 * Adding Touch to the Worm |
460 | 561 |
461 #+name: test-touch | 562 #+name: test-touch |
462 #+begin_src clojure | 563 #+begin_src clojure |
463 (ns cortex.test.touch | 564 (ns cortex.test.touch |