rlm@437
|
1 * Appendix: =CORTEX= User Guide
|
rlm@437
|
2
|
rlm@486
|
3 Those who write a thesis should endeavor to make their code not only
|
rlm@486
|
4 accessable, but actually useable, as a way to pay back the community
|
rlm@486
|
5 that made the thesis possible in the first place. This thesis would
|
rlm@486
|
6 not be possible without Free Software such as jMonkeyEngine3,
|
rlm@486
|
7 Blender, clojure, emacs, ffmpeg, and many other tools. That is why I
|
rlm@486
|
8 have included this user guide, in the hope that someone else might
|
rlm@486
|
9 find =CORTEX= useful.
|
rlm@437
|
10
|
rlm@486
|
11 ** Obtaining =CORTEX=
|
rlm@437
|
12
|
rlm@486
|
13 You can get cortex from its mercurial repository at
|
rlm@486
|
14 http://hg.bortreb.com/cortex. You may also download =CORTEX=
|
rlm@486
|
15 releases at http://aurellem.org/cortex/releases/. As a condition of
|
rlm@486
|
16 making this thesis, I have also provided Professor Winston the
|
rlm@486
|
17 =CORTEX= source, and he knows how to run the demos and get started.
|
rlm@486
|
18 You may also email me at =cortex@aurellem.org= and I may help where
|
rlm@486
|
19 I can.
|
rlm@486
|
20
|
rlm@486
|
21 ** Running =CORTEX=
|
rlm@486
|
22
|
rlm@486
|
23 =CORTEX= comes with README and INSTALL files that will guide you
|
rlm@486
|
24 through installation and running the test suite. In particular you
|
rlm@486
|
25 should look at test =cortex.test= which contains test suites that
|
rlm@486
|
26 run through all senses and multiple creatures.
|
rlm@486
|
27
|
rlm@486
|
28 ** Creating creatures
|
rlm@486
|
29
|
rlm@486
|
30 Creatures are created using /Blender/, a free 3D modeling program.
|
rlm@486
|
31 You will need Blender version 2.6 when using the =CORTEX= included
|
rlm@486
|
32 in this thesis. You create a =CORTEX= creature in a similiar manner
|
rlm@486
|
33 to modeling anything in Blender, except that you also create
|
rlm@486
|
34 several trees of empty nodes which define the creature's senses.
|
rlm@486
|
35
|
rlm@486
|
36 *** Mass
|
rlm@486
|
37
|
rlm@486
|
38 To give an object mass in =CORTEX=, add a ``mass'' metadata label
|
rlm@486
|
39 to the object with the mass in jMonkeyEngine units. Note that
|
rlm@486
|
40 setting the mass to 0 causes the object to be immovable.
|
rlm@486
|
41
|
rlm@486
|
42 *** Joints
|
rlm@486
|
43
|
rlm@486
|
44 Joints are created by creating an empty node named =joints= and
|
rlm@486
|
45 then creating any number of empty child nodes to represent your
|
rlm@486
|
46 creature's joints. The joint will automatically connect the
|
rlm@486
|
47 closest two physical objects. It will help to set the empty node's
|
rlm@486
|
48 display mode to ``Arrows'' so that you can clearly see the
|
rlm@486
|
49 direction of the axes.
|
rlm@486
|
50
|
rlm@486
|
51 Joint nodes should have the following metadata under the ``joint''
|
rlm@486
|
52 label:
|
rlm@486
|
53
|
rlm@486
|
54 #+BEGIN_SRC clojure
|
rlm@486
|
55 ;; ONE OF the following, under the label "joint":
|
rlm@486
|
56 {:type :point}
|
rlm@486
|
57
|
rlm@486
|
58 ;; OR
|
rlm@486
|
59
|
rlm@486
|
60 {:type :hinge
|
rlm@486
|
61 :limit [<limit-low> <limit-high>]
|
rlm@486
|
62 :axis (Vector3f. <x> <y> <z>)}
|
rlm@486
|
63 ;;(:axis defaults to (Vector3f. 1 0 0) if not provided for hinge joints)
|
rlm@486
|
64
|
rlm@486
|
65 ;; OR
|
rlm@486
|
66
|
rlm@486
|
67 {:type :cone
|
rlm@486
|
68 :limit-xz <lim-xz>
|
rlm@486
|
69 :limit-xy <lim-xy>
|
rlm@486
|
70 :twist <lim-twist>} ;(use XZY rotation mode in blender!)
|
rlm@486
|
71 #+END_SRC
|
rlm@486
|
72
|
rlm@486
|
73 *** Eyes
|
rlm@486
|
74
|
rlm@486
|
75 Eyes are created by creating an empty node named =eyes= and then
|
rlm@486
|
76 creating any number of empty child nodes to represent your
|
rlm@486
|
77 creature's eyes.
|
rlm@486
|
78
|
rlm@486
|
79 Eye nodes should have the following metadata under the ``eye''
|
rlm@486
|
80 label:
|
rlm@486
|
81
|
rlm@486
|
82 #+BEGIN_SRC clojure
|
rlm@486
|
83 {:red <red-retina-definition>
|
rlm@486
|
84 :blue <blue-retina-definition>
|
rlm@486
|
85 :green <green-retina-definition>
|
rlm@486
|
86 :all <all-retina-definition>
|
rlm@486
|
87 (<0xrrggbb> <custom-retina-image>)...
|
rlm@486
|
88 }
|
rlm@486
|
89 #+END_SRC
|
rlm@486
|
90
|
rlm@486
|
91 Any of the color channels may be omitted. You may also include
|
rlm@486
|
92 your own color selectors, and in fact :red is equivalent to
|
rlm@486
|
93 0xFF0000 and so forth. The eye will be placed at the same position
|
rlm@486
|
94 as the empty node and will bind to the neatest physical object.
|
rlm@486
|
95 The eye will point outward from the X-axis of the node, and ``up''
|
rlm@486
|
96 will be in the direction of the X-axis of the node. It will help
|
rlm@486
|
97 to set the empty node's display mode to ``Arrows'' so that you can
|
rlm@486
|
98 clearly see the direction of the axes.
|
rlm@486
|
99
|
rlm@486
|
100 Each retina file should contain white pixels whever you want to be
|
rlm@486
|
101 sensitive to your chosen color. If you want the entire field of
|
rlm@486
|
102 view, specify :all of 0xFFFFFF and a retinal map that is entirely
|
rlm@486
|
103 white.
|
rlm@486
|
104
|
rlm@486
|
105 Here is a sample retinal map:
|
rlm@486
|
106
|
rlm@486
|
107 #+caption: An example retinal profile image. White pixels are
|
rlm@486
|
108 #+caption: photo-sensitive elements. The distribution of white
|
rlm@486
|
109 #+caption: pixels is denser in the middle and falls off at the
|
rlm@486
|
110 #+caption: edges and is inspired by the human retina.
|
rlm@486
|
111 #+name: retina
|
rlm@486
|
112 #+ATTR_LaTeX: :width 7cm :placement [H]
|
rlm@486
|
113 [[./images/retina-small.png]]
|
rlm@486
|
114
|
rlm@486
|
115 *** Hearing
|
rlm@486
|
116
|
rlm@486
|
117 Ears are created by creating an empty node named =ears= and then
|
rlm@486
|
118 creating any number of empty child nodes to represent your
|
rlm@486
|
119 creature's ears.
|
rlm@486
|
120
|
rlm@486
|
121 Ear nodes do not require any metadata.
|
rlm@486
|
122
|
rlm@486
|
123 The ear will bind to and follow the closest physical node.
|
rlm@486
|
124
|
rlm@486
|
125 *** Touch
|
rlm@486
|
126
|
rlm@486
|
127 Touch is handled similarly to mass. To make a particular object
|
rlm@486
|
128 touch sensitive, add metadata of the following form under the
|
rlm@486
|
129 object's ``touch'' metadata field:
|
rlm@486
|
130
|
rlm@486
|
131 #+BEGIN_EXAMPLE
|
rlm@486
|
132 <touch-UV-map-file-name>
|
rlm@486
|
133 #+END_EXAMPLE
|
rlm@486
|
134
|
rlm@486
|
135 You may also include an optional ``scale'' metadata number to
|
rlm@486
|
136 specifiy the length of the touch feelers. The default is $0.1$,
|
rlm@486
|
137 and this is generally sufficient.
|
rlm@486
|
138
|
rlm@486
|
139 The touch UV should contain white pixels for each touch sensor.
|
rlm@486
|
140
|
rlm@486
|
141 Here is an example touch-uv map that approximates a human finger,
|
rlm@486
|
142 and its corresponding model.
|
rlm@486
|
143
|
rlm@486
|
144 #+caption: This is the tactile-sensor-profile for the upper segment
|
rlm@486
|
145 #+caption: of a fingertip. It defines regions of high touch sensitivity
|
rlm@486
|
146 #+caption: (where there are many white pixels) and regions of low
|
rlm@486
|
147 #+caption: sensitivity (where white pixels are sparse).
|
rlm@486
|
148 #+name: guide-fingertip-UV
|
rlm@486
|
149 #+ATTR_LaTeX: :width 9cm :placement [H]
|
rlm@486
|
150 [[./images/finger-UV.png]]
|
rlm@486
|
151
|
rlm@486
|
152 #+caption: The fingertip UV-image form above applied to a simple
|
rlm@486
|
153 #+caption: model of a fingertip.
|
rlm@486
|
154 #+name: guide-fingertip
|
rlm@486
|
155 #+ATTR_LaTeX: :width 9cm :placement [H]
|
rlm@486
|
156 [[./images/finger-2.png]]
|
rlm@486
|
157
|
rlm@486
|
158 *** Propriocepotion
|
rlm@486
|
159
|
rlm@486
|
160 Proprioception is tied to each joint node -- nothing special must
|
rlm@486
|
161 be done in a blender model to enable proprioception other than
|
rlm@486
|
162 creating joint nodes.
|
rlm@486
|
163
|
rlm@486
|
164 *** Muscles
|
rlm@486
|
165
|
rlm@486
|
166 Muscles are created by creating an empty node named =muscles= and
|
rlm@486
|
167 then creating any number of empty child nodes to represent your
|
rlm@486
|
168 creature's muscles.
|
rlm@486
|
169
|
rlm@486
|
170
|
rlm@486
|
171 Muscle nodes should have the following metadata under the
|
rlm@486
|
172 ``muscle'' label:
|
rlm@486
|
173
|
rlm@486
|
174 #+BEGIN_EXAMPLE
|
rlm@486
|
175 <muscle-profile-file-name>
|
rlm@486
|
176 #+END_EXAMPLE
|
rlm@486
|
177
|
rlm@486
|
178 Muscles should also have a ``strength'' metadata entry describing
|
rlm@486
|
179 the muscle's total strength at full activation.
|
rlm@486
|
180
|
rlm@486
|
181 Muscle profiles are simple images that contain the relative amount
|
rlm@486
|
182 of muscle power in each simulated alpha motor neuron. The width of
|
rlm@486
|
183 the image is the total size of the motor pool, and the redness of
|
rlm@486
|
184 each neuron is the relative power of that motor pool.
|
rlm@486
|
185
|
rlm@486
|
186 While the profile image can have any dimensions, only the first
|
rlm@486
|
187 line of pixels is used to define the muscle. Here is a sample
|
rlm@486
|
188 muscle profile image that defines a human-like muscle.
|
rlm@486
|
189
|
rlm@486
|
190 #+caption: A muscle profile image that describes the strengths
|
rlm@486
|
191 #+caption: of each motor neuron in a muscle. White is weakest
|
rlm@486
|
192 #+caption: and dark red is strongest. This particular pattern
|
rlm@486
|
193 #+caption: has weaker motor neurons at the beginning, just
|
rlm@486
|
194 #+caption: like human muscle.
|
rlm@486
|
195 #+name: muscle-recruit
|
rlm@486
|
196 #+ATTR_LaTeX: :width 7cm :placement [H]
|
rlm@486
|
197 [[./images/basic-muscle.png]]
|
rlm@486
|
198
|
rlm@486
|
199 Muscles twist the nearest physical object about the muscle node's
|
rlm@486
|
200 Z-axis. I recommend using the ``Single Arrow'' display mode for
|
rlm@486
|
201 muscles and using the right hand rule to determine which way the
|
rlm@486
|
202 muscle will twist. To make a segment that can twist in multiple
|
rlm@486
|
203 directions, create multiple, differently aligned muscles.
|
rlm@486
|
204
|
rlm@486
|
205 ** =CORTEX= API
|
rlm@486
|
206
|
rlm@486
|
207 These are the some functions exposed by =CORTEX= for creating
|
rlm@486
|
208 worlds and simulating creatures. These are in addition to
|
rlm@486
|
209 jMonkeyEngine3's extensive library, which is documented elsewhere.
|
rlm@486
|
210
|
rlm@486
|
211 *** Simulation
|
rlm@486
|
212 - =(world root-node key-map setup-fn update-fn)= :: create
|
rlm@486
|
213 a simulation.
|
rlm@486
|
214 - /root-node/ :: a =com.jme3.scene.Node= object which
|
rlm@486
|
215 contains all of the objects that should be in the
|
rlm@486
|
216 simulation.
|
rlm@486
|
217
|
rlm@486
|
218 - /key-map/ :: a map from strings describing keys to
|
rlm@486
|
219 functions that should be executed whenever that key is
|
rlm@486
|
220 pressed. the functions should take a SimpleApplication
|
rlm@486
|
221 object and a boolean value. The SimpleApplication is the
|
rlm@486
|
222 current simulation that is running, and the boolean is true
|
rlm@486
|
223 if the key is being pressed, and false if it is being
|
rlm@486
|
224 released. As an example,
|
rlm@486
|
225 #+BEGIN_SRC clojure
|
rlm@486
|
226 {"key-j" (fn [game value] (if value (println "key j pressed")))}
|
rlm@486
|
227 #+END_SRC
|
rlm@486
|
228 is a valid key-map which will cause the simulation to print
|
rlm@486
|
229 a message whenever the 'j' key on the keyboard is pressed.
|
rlm@486
|
230
|
rlm@486
|
231 - /setup-fn/ :: a function that takes a =SimpleApplication=
|
rlm@486
|
232 object. It is called once when initializing the simulation.
|
rlm@486
|
233 Use it to create things like lights, change the gravity,
|
rlm@486
|
234 initialize debug nodes, etc.
|
rlm@486
|
235
|
rlm@486
|
236 - /update-fn/ :: this function takes a =SimpleApplication=
|
rlm@486
|
237 object and a float and is called every frame of the
|
rlm@486
|
238 simulation. The float tells how many seconds is has been
|
rlm@486
|
239 since the last frame was rendered, according to whatever
|
rlm@486
|
240 clock jme is currently using. The default is to use IsoTimer
|
rlm@486
|
241 which will result in this value always being the same.
|
rlm@486
|
242
|
rlm@486
|
243 - =(position-camera world position rotation)= :: set the position
|
rlm@486
|
244 of the simulation's main camera.
|
rlm@487
|
245
|
rlm@486
|
246 - =(enable-debug world)= :: turn on debug wireframes for each
|
rlm@486
|
247 simulated object.
|
rlm@487
|
248
|
rlm@486
|
249 - =(set-gravity world gravity)= :: set the gravity of a running
|
rlm@486
|
250 simulation.
|
rlm@487
|
251
|
rlm@486
|
252 - =(box length width height & {options})= :: create a box in the
|
rlm@486
|
253 simulation. Options is a hash map specifying texture, mass,
|
rlm@486
|
254 etc. Possible options are =:name=, =:color=, =:mass=,
|
rlm@486
|
255 =:friction=, =:texture=, =:material=, =:position=,
|
rlm@486
|
256 =:rotation=, =:shape=, and =:physical?=.
|
rlm@487
|
257
|
rlm@486
|
258 - =(sphere radius & {options})= :: create a sphere in the simulation.
|
rlm@486
|
259 Options are the same as in =box=.
|
rlm@487
|
260
|
rlm@486
|
261 - =(load-blender-model file-name)= :: create a node structure
|
rlm@486
|
262 representing that described in a blender file.
|
rlm@487
|
263
|
rlm@486
|
264 - =(light-up-everything world)= :: distribute a standard compliment
|
rlm@486
|
265 of lights throught the simulation. Should be adequate for most
|
rlm@486
|
266 purposes.
|
rlm@487
|
267
|
rlm@486
|
268 - =(node-seq node)= :: return a recursuve list of the node's
|
rlm@486
|
269 children.
|
rlm@487
|
270
|
rlm@486
|
271 - =(nodify name children)= :: construct a node given a node-name and
|
rlm@486
|
272 desired children.
|
rlm@487
|
273
|
rlm@486
|
274 - =(add-element world element)= :: add an object to a running world
|
rlm@486
|
275 simulation.
|
rlm@487
|
276
|
rlm@486
|
277 - =(set-accuracy world accuracy)= :: change the accuracy of the
|
rlm@486
|
278 world's physics simulator.
|
rlm@487
|
279
|
rlm@486
|
280 - =(asset-manager)= :: get an /AssetManager/, a jMonkeyEngine
|
rlm@486
|
281 construct that is useful for loading textures and is required
|
rlm@486
|
282 for smooth interaction with jMonkeyEngine library functions.
|
rlm@487
|
283
|
rlm@487
|
284 - =(load-bullet)= :: unpack native libraries and initialize
|
rlm@487
|
285 blender. This function is required before other world building
|
rlm@487
|
286 functions are called.
|
rlm@486
|
287
|
rlm@486
|
288
|
rlm@486
|
289 *** Creature Manipulation / Import
|
rlm@486
|
290
|
rlm@486
|
291 - =(body! creature)= :: give the creature a physical body.
|
rlm@487
|
292
|
rlm@486
|
293 - =(vision! creature)= :: give the creature a sense of vision.
|
rlm@486
|
294 Returns a list of functions which will each, when called
|
rlm@486
|
295 during a simulation, return the vision data for the channel of
|
rlm@486
|
296 one of the eyes. The functions are ordered depending on the
|
rlm@486
|
297 alphabetical order of the names of the eye nodes in the
|
rlm@486
|
298 blender file. The data returned by the functions is a vector
|
rlm@486
|
299 containing the eye's /topology/, a vector of coordinates, and
|
rlm@486
|
300 the eye's /data/, a vector of RGB values filtered by the eye's
|
rlm@486
|
301 sensitivity.
|
rlm@487
|
302
|
rlm@486
|
303 - =(hearing! creature)= :: give the creature a sense of hearing.
|
rlm@486
|
304 Returns a list of functions, one for each ear, that when
|
rlm@486
|
305 called will return a frame's worth of hearing data for that
|
rlm@486
|
306 ear. The functions are ordered depending on the alphabetical
|
rlm@486
|
307 order of the names of the ear nodes in the blender file. The
|
rlm@486
|
308 data returned by the functions is an array PCM encoded wav
|
rlm@486
|
309 data.
|
rlm@487
|
310
|
rlm@486
|
311 - =(touch! creature)= :: give the creature a sense of touch. Returns
|
rlm@486
|
312 a single function that must be called with the /root node/ of
|
rlm@486
|
313 the world, and which will return a vector of /touch-data/
|
rlm@486
|
314 one entry for each touch sensitive component, each entry of
|
rlm@486
|
315 which contains a /topology/ that specifies the distribution of
|
rlm@486
|
316 touch sensors, and the /data/, which is a vector of
|
rlm@486
|
317 =[activation, length]= pairs for each touch hair.
|
rlm@487
|
318
|
rlm@486
|
319 - =(proprioception! creature)= :: give the creature the sense of
|
rlm@486
|
320 proprioception. Returns a list of functions, one for each
|
rlm@486
|
321 joint, that when called during a running simulation will
|
rlm@486
|
322 report the =[headnig, pitch, roll]= of the joint.
|
rlm@487
|
323
|
rlm@486
|
324 - =(movement! creature)= :: give the creature the power of movement.
|
rlm@486
|
325 Creates a list of functions, one for each muscle, that when
|
rlm@486
|
326 called with an integer, will set the recruitment of that
|
rlm@486
|
327 muscle to that integer, and will report the current power
|
rlm@486
|
328 being exerted by the muscle. Order of muscles is determined by
|
rlm@486
|
329 the alphabetical sort order of the names of the muscle nodes.
|
rlm@486
|
330
|
rlm@486
|
331 *** Visualization/Debug
|
rlm@486
|
332
|
rlm@486
|
333 - =(view-vision)= :: create a function that when called with a list
|
rlm@486
|
334 of visual data returned from the functions made by =vision!=,
|
rlm@486
|
335 will display that visual data on the screen.
|
rlm@487
|
336
|
rlm@486
|
337 - =(view-hearing)= :: same as =view-vision= but for hearing.
|
rlm@487
|
338
|
rlm@486
|
339 - =(view-touch)= :: same as =view-vision= but for touch.
|
rlm@487
|
340
|
rlm@486
|
341 - =(view-proprioception)= :: same as =view-vision= but for
|
rlm@486
|
342 proprioception.
|
rlm@487
|
343
|
rlm@486
|
344 - =(view-movement)= :: same as =view-vision= but for
|
rlm@486
|
345 proprioception.
|
rlm@487
|
346
|
rlm@486
|
347 - =(view anything)= :: =view= is a polymorphic function that allows
|
rlm@486
|
348 you to inspect almost anything you could reasonably expect to
|
rlm@486
|
349 be able to ``see'' in =CORTEX=.
|
rlm@487
|
350
|
rlm@486
|
351 - =(text anything)= :: =text= is a polymorphic function that allows
|
rlm@486
|
352 you to convert practically anything into a text string.
|
rlm@487
|
353
|
rlm@486
|
354 - =(println-repl anything)= :: print messages to clojure's repl
|
rlm@486
|
355 instead of the simulation's terminal window.
|
rlm@486
|
356
|
rlm@486
|
357 - =(mega-import-jme3)= :: for experimenting at the REPL. This
|
rlm@486
|
358 function will import all jMonkeyEngine3 classes for immediate
|
rlm@486
|
359 use.
|
rlm@487
|
360
|
rlm@487
|
361 - =(display-dialated-time world timer)= :: Shows the time as it is
|
rlm@487
|
362 flowing in the simulation on a HUD display.
|
rlm@487
|
363
|
rlm@487
|
364
|
rlm@487
|
365
|