Mercurial > cortex
comparison thesis/cortex.org @ 475:3ec428e096e5
most of the way to getting touch integrated.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 28 Mar 2014 21:48:53 -0400 |
parents | 57c7d5aec8d5 |
children | 5a15611fbb9f |
comparison
equal
deleted
inserted
replaced
474:57c7d5aec8d5 | 475:3ec428e096e5 |
---|---|
25 #+caption: | 25 #+caption: |
26 #+caption: | 26 #+caption: |
27 #+caption: | 27 #+caption: |
28 #+name: name | 28 #+name: name |
29 #+begin_listing clojure | 29 #+begin_listing clojure |
30 #+BEGIN_SRC clojure | |
31 #+END_SRC | |
30 #+end_listing | 32 #+end_listing |
31 | 33 |
32 #+caption: | 34 #+caption: |
33 #+caption: | 35 #+caption: |
34 #+caption: | 36 #+caption: |
1584 simulate touch, I use jMonkeyEngine's physics system to execute | 1586 simulate touch, I use jMonkeyEngine's physics system to execute |
1585 many small collision detections, one for each feeler. The placement | 1587 many small collision detections, one for each feeler. The placement |
1586 of the feelers is determined by a UV-mapped image which shows where | 1588 of the feelers is determined by a UV-mapped image which shows where |
1587 each feeler should be on the 3D surface of the body. | 1589 each feeler should be on the 3D surface of the body. |
1588 | 1590 |
1589 *** Defining Touch Meta-Data in Blender | 1591 *** COMMENT Defining Touch Meta-Data in Blender |
1590 | 1592 |
1591 Each geometry can have a single UV map which describes the | 1593 Each geometry can have a single UV map which describes the |
1592 position of the feelers which will constitute its sense of touch. | 1594 position of the feelers which will constitute its sense of touch. |
1593 This image path is stored under the ``touch'' key. The image itself | 1595 This image path is stored under the ``touch'' key. The image itself |
1594 is black and white, with black meaning a feeler length of 0 (no | 1596 is black and white, with black meaning a feeler length of 0 (no |
1595 feeler is present) and white meaning a feeler length of =scale=, | 1597 feeler is present) and white meaning a feeler length of =scale=, |
1596 which is a float stored under the key "scale". | 1598 which is a float stored under the key "scale". |
1597 | 1599 |
1598 #+name: meta-data | 1600 #+caption: Touch does not use empty nodes, to store metadata, |
1599 #+begin_src clojure | 1601 #+caption: because the metadata of each solid part of a |
1602 #+caption: creature's body is sufficient. | |
1603 #+name: touch-meta-data | |
1604 #+begin_listing clojure | |
1600 (defn tactile-sensor-profile | 1605 (defn tactile-sensor-profile |
1601 "Return the touch-sensor distribution image in BufferedImage format, | 1606 "Return the touch-sensor distribution image in BufferedImage format, |
1602 or nil if it does not exist." | 1607 or nil if it does not exist." |
1603 [#^Geometry obj] | 1608 [#^Geometry obj] |
1604 (if-let [image-path (meta-data obj "touch")] | 1609 (if-let [image-path (meta-data obj "touch")] |
1608 "Return the length of each feeler. Default scale is 0.01 | 1613 "Return the length of each feeler. Default scale is 0.01 |
1609 jMonkeyEngine units." | 1614 jMonkeyEngine units." |
1610 [#^Geometry obj] | 1615 [#^Geometry obj] |
1611 (if-let [scale (meta-data obj "scale")] | 1616 (if-let [scale (meta-data obj "scale")] |
1612 scale 0.1)) | 1617 scale 0.1)) |
1613 #+end_src | 1618 #+end_listing |
1614 | 1619 |
1615 Here is an example of a UV-map which specifies the position of touch | 1620 Here is an example of a UV-map which specifies the position of |
1616 sensors along the surface of the upper segment of the worm. | 1621 touch sensors along the surface of the upper segment of a fingertip. |
1617 | 1622 |
1618 #+attr_html: width=755 | 1623 |
1619 #+caption: This is the tactile-sensor-profile for the upper segment of the worm. It defines regions of high touch sensitivity (where there are many white pixels) and regions of low sensitivity (where white pixels are sparse). | 1624 #+caption: This is the tactile-sensor-profile for the upper segment |
1625 #+caption: of a fingertip. It defines regions of high touch sensitivity | |
1626 #+caption: (where there are many white pixels) and regions of low | |
1627 #+caption: sensitivity (where white pixels are sparse). | |
1628 #+name: fimgertip-UV | |
1629 #+ATTR_LaTeX: :width 10cm | |
1620 [[../images/finger-UV.png]] | 1630 [[../images/finger-UV.png]] |
1621 | 1631 |
1622 *** Implementation Summary | 1632 *** COMMENT Implementation Summary |
1623 | 1633 |
1624 To simulate touch there are three conceptual steps. For each solid | 1634 To simulate touch there are three conceptual steps. For each solid |
1625 object in the creature, you first have to get UV image and scale | 1635 object in the creature, you first have to get UV image and scale |
1626 parameter which define the position and length of the feelers. | 1636 parameter which define the position and length of the feelers. |
1627 Then, you use the triangles which comprise the mesh and the UV | 1637 Then, you use the triangles which comprise the mesh and the UV |
1634 Extracting the meta-data has already been described. The third | 1644 Extracting the meta-data has already been described. The third |
1635 step, physics collision detection, is handled in =touch-kernel=. | 1645 step, physics collision detection, is handled in =touch-kernel=. |
1636 Translating the positions and orientations of the feelers from the | 1646 Translating the positions and orientations of the feelers from the |
1637 UV-map to world-space is itself a three-step process. | 1647 UV-map to world-space is itself a three-step process. |
1638 | 1648 |
1639 - Find the triangles which make up the mesh in pixel-space and in | 1649 - Find the triangles which make up the mesh in pixel-space and in |
1640 world-space. =triangles= =pixel-triangles=. | 1650 world-space. (=triangles= =pixel-triangles=). |
1641 | 1651 |
1642 - Find the coordinates of each feeler in world-space. These are the | 1652 - Find the coordinates of each feeler in world-space. These are |
1643 origins of the feelers. =feeler-origins=. | 1653 the origins of the feelers. (=feeler-origins=). |
1644 | 1654 |
1645 - Calculate the normals of the triangles in world space, and add | 1655 - Calculate the normals of the triangles in world space, and add |
1646 them to each of the origins of the feelers. These are the | 1656 them to each of the origins of the feelers. These are the |
1647 normalized coordinates of the tips of the feelers. =feeler-tips=. | 1657 normalized coordinates of the tips of the feelers. |
1648 | 1658 (=feeler-tips=). |
1649 *** Triangle Math | 1659 |
1650 | 1660 *** COMMENT Triangle Math |
1651 The rigid objects which make up a creature have an underlying | 1661 |
1652 =Geometry=, which is a =Mesh= plus a =Material= and other important | 1662 The rigid objects which make up a creature have an underlying |
1653 data involved with displaying the object. | 1663 =Geometry=, which is a =Mesh= plus a =Material= and other |
1654 | 1664 important data involved with displaying the object. |
1655 A =Mesh= is composed of =Triangles=, and each =Triangle= has three | 1665 |
1656 vertices which have coordinates in world space and UV space. | 1666 A =Mesh= is composed of =Triangles=, and each =Triangle= has three |
1657 | 1667 vertices which have coordinates in world space and UV space. |
1658 Here, =triangles= gets all the world-space triangles which comprise a | 1668 |
1659 mesh, while =pixel-triangles= gets those same triangles expressed in | 1669 Here, =triangles= gets all the world-space triangles which |
1660 pixel coordinates (which are UV coordinates scaled to fit the height | 1670 comprise a mesh, while =pixel-triangles= gets those same triangles |
1661 and width of the UV image). | 1671 expressed in pixel coordinates (which are UV coordinates scaled to |
1662 | 1672 fit the height and width of the UV image). |
1663 #+name: triangles-2 | 1673 |
1664 #+begin_src clojure | 1674 #+caption: Programs to extract triangles from a geometry and get |
1665 (in-ns 'cortex.touch) | 1675 #+caption: their verticies in both world and UV-coordinates. |
1676 #+name: get-triangles | |
1677 #+begin_listing clojure | |
1666 (defn triangle | 1678 (defn triangle |
1667 "Get the triangle specified by triangle-index from the mesh." | 1679 "Get the triangle specified by triangle-index from the mesh." |
1668 [#^Geometry geo triangle-index] | 1680 [#^Geometry geo triangle-index] |
1669 (triangle-seq | 1681 (triangle-seq |
1670 (let [scratch (Triangle.)] | 1682 (let [scratch (Triangle.)] |
1682 [#^Mesh mesh triangle-index] | 1694 [#^Mesh mesh triangle-index] |
1683 (let [indices (int-array 3)] | 1695 (let [indices (int-array 3)] |
1684 (.getTriangle mesh triangle-index indices) | 1696 (.getTriangle mesh triangle-index indices) |
1685 (vec indices))) | 1697 (vec indices))) |
1686 | 1698 |
1687 (defn vertex-UV-coord | 1699 (defn vertex-UV-coord |
1688 "Get the UV-coordinates of the vertex named by vertex-index" | 1700 "Get the UV-coordinates of the vertex named by vertex-index" |
1689 [#^Mesh mesh vertex-index] | 1701 [#^Mesh mesh vertex-index] |
1690 (let [UV-buffer | 1702 (let [UV-buffer |
1691 (.getData | 1703 (.getData |
1692 (.getBuffer | 1704 (.getBuffer |
1709 [#^Geometry geo image] | 1721 [#^Geometry geo image] |
1710 (let [height (.getHeight image) | 1722 (let [height (.getHeight image) |
1711 width (.getWidth image)] | 1723 width (.getWidth image)] |
1712 (map (partial pixel-triangle geo image) | 1724 (map (partial pixel-triangle geo image) |
1713 (range (.getTriangleCount (.getMesh geo)))))) | 1725 (range (.getTriangleCount (.getMesh geo)))))) |
1714 #+end_src | 1726 #+end_listing |
1715 | 1727 |
1716 *** The Affine Transform from one Triangle to Another | 1728 *** The Affine Transform from one Triangle to Another |
1717 | 1729 |
1718 =pixel-triangles= gives us the mesh triangles expressed in pixel | 1730 =pixel-triangles= gives us the mesh triangles expressed in pixel |
1719 coordinates and =triangles= gives us the mesh triangles expressed in | 1731 coordinates and =triangles= gives us the mesh triangles expressed |
1720 world coordinates. The tactile-sensor-profile gives the position of | 1732 in world coordinates. The tactile-sensor-profile gives the |
1721 each feeler in pixel-space. In order to convert pixel-space | 1733 position of each feeler in pixel-space. In order to convert |
1722 coordinates into world-space coordinates we need something that takes | 1734 pixel-space coordinates into world-space coordinates we need |
1723 coordinates on the surface of one triangle and gives the corresponding | 1735 something that takes coordinates on the surface of one triangle |
1724 coordinates on the surface of another triangle. | 1736 and gives the corresponding coordinates on the surface of another |
1725 | 1737 triangle. |
1726 Triangles are [[http://mathworld.wolfram.com/AffineTransformation.html ][affine]], which means any triangle can be transformed into | 1738 |
1727 any other by a combination of translation, scaling, and | 1739 Triangles are [[http://mathworld.wolfram.com/AffineTransformation.html ][affine]], which means any triangle can be transformed |
1728 rotation. The affine transformation from one triangle to another | 1740 into any other by a combination of translation, scaling, and |
1729 is readily computable if the triangle is expressed in terms of a $4x4$ | 1741 rotation. The affine transformation from one triangle to another |
1730 matrix. | 1742 is readily computable if the triangle is expressed in terms of a |
1731 | 1743 $4x4$ matrix. |
1732 \begin{bmatrix} | 1744 |
1733 x_1 & x_2 & x_3 & n_x \\ | 1745 \begin{bmatrix} |
1734 y_1 & y_2 & y_3 & n_y \\ | 1746 x_1 & x_2 & x_3 & n_x \\ |
1735 z_1 & z_2 & z_3 & n_z \\ | 1747 y_1 & y_2 & y_3 & n_y \\ |
1736 1 & 1 & 1 & 1 | 1748 z_1 & z_2 & z_3 & n_z \\ |
1737 \end{bmatrix} | 1749 1 & 1 & 1 & 1 |
1738 | 1750 \end{bmatrix} |
1739 Here, the first three columns of the matrix are the vertices of the | 1751 |
1740 triangle. The last column is the right-handed unit normal of the | 1752 Here, the first three columns of the matrix are the vertices of |
1741 triangle. | 1753 the triangle. The last column is the right-handed unit normal of |
1742 | 1754 the triangle. |
1743 With two triangles $T_{1}$ and $T_{2}$ each expressed as a matrix like | 1755 |
1744 above, the affine transform from $T_{1}$ to $T_{2}$ is | 1756 With two triangles $T_{1}$ and $T_{2}$ each expressed as a matrix |
1745 | 1757 like above, the affine transform from $T_{1}$ to $T_{2}$ is |
1746 $T_{2}T_{1}^{-1}$ | 1758 |
1747 | 1759 $T_{2}T_{1}^{-1}$ |
1748 The clojure code below recapitulates the formulas above, using | 1760 |
1749 jMonkeyEngine's =Matrix4f= objects, which can describe any affine | 1761 The clojure code below recapitulates the formulas above, using |
1750 transformation. | 1762 jMonkeyEngine's =Matrix4f= objects, which can describe any affine |
1751 | 1763 transformation. |
1752 #+name: triangles-3 | 1764 |
1753 #+begin_src clojure | 1765 #+caption: Program to interpert triangles as affine transforms. |
1754 (in-ns 'cortex.touch) | 1766 #+name: triangle-affine |
1755 | 1767 #+begin_listing clojure |
1768 #+BEGIN_SRC clojure | |
1756 (defn triangle->matrix4f | 1769 (defn triangle->matrix4f |
1757 "Converts the triangle into a 4x4 matrix: The first three columns | 1770 "Converts the triangle into a 4x4 matrix: The first three columns |
1758 contain the vertices of the triangle; the last contains the unit | 1771 contain the vertices of the triangle; the last contains the unit |
1759 normal of the triangle. The bottom row is filled with 1s." | 1772 normal of the triangle. The bottom row is filled with 1s." |
1760 [#^Triangle t] | 1773 [#^Triangle t] |
1775 triangle." | 1788 triangle." |
1776 [#^Triangle tri-1 #^Triangle tri-2] | 1789 [#^Triangle tri-1 #^Triangle tri-2] |
1777 (.mult | 1790 (.mult |
1778 (triangle->matrix4f tri-2) | 1791 (triangle->matrix4f tri-2) |
1779 (.invert (triangle->matrix4f tri-1)))) | 1792 (.invert (triangle->matrix4f tri-1)))) |
1780 #+end_src | 1793 #+END_SRC |
1781 | 1794 #+end_listing |
1782 *** Triangle Boundaries | 1795 |
1796 *** COMMENT Triangle Boundaries | |
1783 | 1797 |
1784 For efficiency's sake I will divide the tactile-profile image into | 1798 For efficiency's sake I will divide the tactile-profile image into |
1785 small squares which inscribe each pixel-triangle, then extract the | 1799 small squares which inscribe each pixel-triangle, then extract the |
1786 points which lie inside the triangle and map them to 3D-space using | 1800 points which lie inside the triangle and map them to 3D-space using |
1787 =triangle-transform= above. To do this I need a function, | 1801 =triangle-transform= above. To do this I need a function, |
1789 triangle. | 1803 triangle. |
1790 | 1804 |
1791 =inside-triangle?= determines whether a point is inside a triangle | 1805 =inside-triangle?= determines whether a point is inside a triangle |
1792 in 2D pixel-space. | 1806 in 2D pixel-space. |
1793 | 1807 |
1794 #+name: triangles-4 | 1808 #+caption: Program to efficiently determine point includion |
1795 #+begin_src clojure | 1809 #+caption: in a triangle. |
1810 #+name: in-triangle | |
1811 #+begin_listing clojure | |
1812 #+BEGIN_SRC clojure | |
1796 (defn convex-bounds | 1813 (defn convex-bounds |
1797 "Returns the smallest square containing the given vertices, as a | 1814 "Returns the smallest square containing the given vertices, as a |
1798 vector of integers [left top width height]." | 1815 vector of integers [left top width height]." |
1799 [verts] | 1816 [verts] |
1800 (let [xs (map first verts) | 1817 (let [xs (map first verts) |
1822 (let [[vert-1 vert-2 vert-3] [(.get1 tri) (.get2 tri) (.get3 tri)]] | 1839 (let [[vert-1 vert-2 vert-3] [(.get1 tri) (.get2 tri) (.get3 tri)]] |
1823 (and | 1840 (and |
1824 (same-side? vert-1 vert-2 vert-3 p) | 1841 (same-side? vert-1 vert-2 vert-3 p) |
1825 (same-side? vert-2 vert-3 vert-1 p) | 1842 (same-side? vert-2 vert-3 vert-1 p) |
1826 (same-side? vert-3 vert-1 vert-2 p)))) | 1843 (same-side? vert-3 vert-1 vert-2 p)))) |
1827 #+end_src | 1844 #+END_SRC |
1828 | 1845 #+end_listing |
1829 *** Feeler Coordinates | 1846 |
1830 | 1847 *** COMMENT Feeler Coordinates |
1831 The triangle-related functions above make short work of calculating | 1848 |
1832 the positions and orientations of each feeler in world-space. | 1849 The triangle-related functions above make short work of |
1833 | 1850 calculating the positions and orientations of each feeler in |
1834 #+name: sensors | 1851 world-space. |
1835 #+begin_src clojure | 1852 |
1836 (in-ns 'cortex.touch) | 1853 #+caption: Program to get the coordinates of ``feelers '' in |
1837 | 1854 #+caption: both world and UV-coordinates. |
1855 #+name: feeler-coordinates | |
1856 #+begin_listing clojure | |
1857 #+BEGIN_SRC clojure | |
1838 (defn feeler-pixel-coords | 1858 (defn feeler-pixel-coords |
1839 "Returns the coordinates of the feelers in pixel space in lists, one | 1859 "Returns the coordinates of the feelers in pixel space in lists, one |
1840 list for each triangle, ordered in the same way as (triangles) and | 1860 list for each triangle, ordered in the same way as (triangles) and |
1841 (pixel-triangles)." | 1861 (pixel-triangles)." |
1842 [#^Geometry geo image] | 1862 [#^Geometry geo image] |
1860 (pixel-triangles geo image) | 1880 (pixel-triangles geo image) |
1861 (triangles geo))] | 1881 (triangles geo))] |
1862 (map (fn [transform coords] | 1882 (map (fn [transform coords] |
1863 (map #(.mult transform (->vector3f %)) coords)) | 1883 (map #(.mult transform (->vector3f %)) coords)) |
1864 transforms (feeler-pixel-coords geo image)))) | 1884 transforms (feeler-pixel-coords geo image)))) |
1865 | 1885 #+END_SRC |
1886 #+end_listing | |
1887 | |
1888 #+caption: Program to get the position of the base and tip of | |
1889 #+caption: each ``feeler'' | |
1890 #+name: feeler-tips | |
1891 #+begin_listing clojure | |
1892 #+BEGIN_SRC clojure | |
1866 (defn feeler-origins | 1893 (defn feeler-origins |
1867 "The world space coordinates of the root of each feeler." | 1894 "The world space coordinates of the root of each feeler." |
1868 [#^Geometry geo image] | 1895 [#^Geometry geo image] |
1869 (reduce concat (feeler-world-coords geo image))) | 1896 (reduce concat (feeler-world-coords geo image))) |
1870 | 1897 |
1882 (mapcat (fn [origins normal] | 1909 (mapcat (fn [origins normal] |
1883 (map #(.add % normal) origins)) | 1910 (map #(.add % normal) origins)) |
1884 world-coords normals))) | 1911 world-coords normals))) |
1885 | 1912 |
1886 (defn touch-topology | 1913 (defn touch-topology |
1887 "touch-topology? is not a function." | |
1888 [#^Geometry geo image] | 1914 [#^Geometry geo image] |
1889 (collapse (reduce concat (feeler-pixel-coords geo image)))) | 1915 (collapse (reduce concat (feeler-pixel-coords geo image)))) |
1890 #+end_src | 1916 #+END_SRC |
1891 *** Simulated Touch | 1917 #+end_listing |
1892 | 1918 |
1893 =touch-kernel= generates functions to be called from within a | 1919 *** COMMENT Simulated Touch |
1894 simulation that perform the necessary physics collisions to collect | 1920 |
1895 tactile data, and =touch!= recursively applies it to every node in | 1921 Now that the functions to construct feelers are complete, |
1896 the creature. | 1922 =touch-kernel= generates functions to be called from within a |
1897 | 1923 simulation that perform the necessary physics collisions to |
1898 #+name: kernel | 1924 collect tactile data, and =touch!= recursively applies it to every |
1899 #+begin_src clojure | 1925 node in the creature. |
1900 (in-ns 'cortex.touch) | 1926 |
1901 | 1927 #+caption: Efficient program to transform a ray from |
1928 #+caption: one position to another. | |
1929 #+name: set-ray | |
1930 #+begin_listing clojure | |
1931 #+BEGIN_SRC clojure | |
1902 (defn set-ray [#^Ray ray #^Matrix4f transform | 1932 (defn set-ray [#^Ray ray #^Matrix4f transform |
1903 #^Vector3f origin #^Vector3f tip] | 1933 #^Vector3f origin #^Vector3f tip] |
1904 ;; Doing everything locally reduces garbage collection by enough to | 1934 ;; Doing everything locally reduces garbage collection by enough to |
1905 ;; be worth it. | 1935 ;; be worth it. |
1906 (.mult transform origin (.getOrigin ray)) | 1936 (.mult transform origin (.getOrigin ray)) |
1907 (.mult transform tip (.getDirection ray)) | 1937 (.mult transform tip (.getDirection ray)) |
1908 (.subtractLocal (.getDirection ray) (.getOrigin ray)) | 1938 (.subtractLocal (.getDirection ray) (.getOrigin ray)) |
1909 (.normalizeLocal (.getDirection ray))) | 1939 (.normalizeLocal (.getDirection ray))) |
1910 | 1940 #+END_SRC |
1911 (import com.jme3.math.FastMath) | 1941 #+end_listing |
1912 | 1942 |
1943 #+caption: This is the core of touch in =CORTEX= each feeler | |
1944 #+caption: follows the object it is bound to, reporting any | |
1945 #+caption: collisions that may happen. | |
1946 #+name: touch-kernel | |
1947 #+begin_listing clojure | |
1948 #+BEGIN_SRC clojure | |
1913 (defn touch-kernel | 1949 (defn touch-kernel |
1914 "Constructs a function which will return tactile sensory data from | 1950 "Constructs a function which will return tactile sensory data from |
1915 'geo when called from inside a running simulation" | 1951 'geo when called from inside a running simulation" |
1916 [#^Geometry geo] | 1952 [#^Geometry geo] |
1917 (if-let | 1953 (if-let |
1920 ray-reference-tips (feeler-tips geo profile) | 1956 ray-reference-tips (feeler-tips geo profile) |
1921 ray-length (tactile-scale geo) | 1957 ray-length (tactile-scale geo) |
1922 current-rays (map (fn [_] (Ray.)) ray-reference-origins) | 1958 current-rays (map (fn [_] (Ray.)) ray-reference-origins) |
1923 topology (touch-topology geo profile) | 1959 topology (touch-topology geo profile) |
1924 correction (float (* ray-length -0.2))] | 1960 correction (float (* ray-length -0.2))] |
1925 | |
1926 ;; slight tolerance for very close collisions. | 1961 ;; slight tolerance for very close collisions. |
1927 (dorun | 1962 (dorun |
1928 (map (fn [origin tip] | 1963 (map (fn [origin tip] |
1929 (.addLocal origin (.mult (.subtract tip origin) | 1964 (.addLocal origin (.mult (.subtract tip origin) |
1930 correction))) | 1965 correction))) |
1958 (if (> response limit) (float 0.0) | 1993 (if (> response limit) (float 0.0) |
1959 (+ response correction))) | 1994 (+ response correction))) |
1960 (float 0.0) | 1995 (float 0.0) |
1961 limit))) | 1996 limit))) |
1962 limit]))))))))))) | 1997 limit]))))))))))) |
1963 | 1998 #+END_SRC |
1999 #+end_listing | |
2000 | |
2001 Armed with the =touch!= function, =CORTEX= becomes capable of | |
2002 giving creatures a sense of touch. A simple test is to create a | |
2003 cube that is outfitted with a uniform distrubition of touch | |
2004 sensors. It can feel the ground and any balls that it touches. | |
2005 | |
2006 #+caption: =CORTEX= interface for creating touch in a simulated | |
2007 #+caption: creature. | |
2008 #+name: touch | |
2009 #+begin_listing clojure | |
2010 #+BEGIN_SRC clojure | |
1964 (defn touch! | 2011 (defn touch! |
1965 "Endow the creature with the sense of touch. Returns a sequence of | 2012 "Endow the creature with the sense of touch. Returns a sequence of |
1966 functions, one for each body part with a tactile-sensor-profile, | 2013 functions, one for each body part with a tactile-sensor-profile, |
1967 each of which when called returns sensory data for that body part." | 2014 each of which when called returns sensory data for that body part." |
1968 [#^Node creature] | 2015 [#^Node creature] |
1969 (filter | 2016 (filter |
1970 (comp not nil?) | 2017 (comp not nil?) |
1971 (map touch-kernel | 2018 (map touch-kernel |
1972 (filter #(isa? (class %) Geometry) | 2019 (filter #(isa? (class %) Geometry) |
1973 (node-seq creature))))) | 2020 (node-seq creature))))) |
1974 #+end_src | 2021 #+END_SRC |
1975 | 2022 #+end_listing |
1976 | 2023 |
1977 Armed with the =touch!= function, =CORTEX= becomes capable of giving | 2024 The tactile-sensor-profile image for the touch cube is a simple |
1978 creatures a sense of touch. A simple test is to create a cube that is | 2025 cross with a unifom distribution of touch sensors: |
1979 outfitted with a uniform distrubition of touch sensors. It can feel | 2026 |
1980 the ground and any balls that it touches. | 2027 #+caption: The touch profile for the touch-cube. Each pure white |
1981 | 2028 #+caption: pixel defines a touch sensitive feeler. |
1982 # insert touch cube image; UV map | 2029 #+name: touch-cube-uv-map |
1983 # insert video | 2030 #+ATTR_LaTeX: :width 10cm |
2031 [[./images/touch-profile.png]] | |
2032 | |
2033 #+caption: The touch cube reacts to canonballs. The black, red, | |
2034 #+caption: and white cross on the right is a visual display of | |
2035 #+caption: the creature's touch. White means that it is feeling | |
2036 #+caption: something strongly, black is not feeling anything, | |
2037 #+caption: and gray is in-between. The cube can feel both the | |
2038 #+caption: floor and the ball. Notice that when the ball causes | |
2039 #+caption: the cube to tip, that the bottom face can still feel | |
2040 #+caption: part of the ground. | |
2041 #+name: touch-cube-uv-map | |
2042 #+ATTR_LaTeX: :width 15cm | |
2043 [[./images/touch-cube.png]] | |
1984 | 2044 |
1985 ** Proprioception is the sense that makes everything ``real'' | 2045 ** Proprioception is the sense that makes everything ``real'' |
1986 | 2046 |
1987 ** Muscles are both effectors and sensors | 2047 ** Muscles are both effectors and sensors |
1988 | 2048 |