comparison thesis/cortex.org @ 481:6e68720e1c13

add muscles. so STRONG right now.
author Robert McIntyre <rlm@mit.edu>
date Fri, 28 Mar 2014 23:30:39 -0400
parents ad76b8b05517
children 074eadc919fe
comparison
equal deleted inserted replaced
480:ad76b8b05517 481:6e68720e1c13
2182 #+caption: pitch, and White is roll. 2182 #+caption: pitch, and White is roll.
2183 #+name: proprio 2183 #+name: proprio
2184 #+ATTR_LaTeX: :width 11cm 2184 #+ATTR_LaTeX: :width 11cm
2185 [[./images/proprio.png]] 2185 [[./images/proprio.png]]
2186 2186
2187 ** Muscles are both effectors and sensors 2187 ** COMMENT Muscles are both effectors and sensors
2188
2189 Surprisingly enough, terrestrial creatures only move by using
2190 torque applied about their joints. There's not a single straight
2191 line of force in the human body at all! (A straight line of force
2192 would correspond to some sort of jet or rocket propulsion.)
2193
2194 In humans, muscles are composed of muscle fibers which can contract
2195 to exert force. The muscle fibers which compose a muscle are
2196 partitioned into discrete groups which are each controlled by a
2197 single alpha motor neuron. A single alpha motor neuron might
2198 control as little as three or as many as one thousand muscle
2199 fibers. When the alpha motor neuron is engaged by the spinal cord,
2200 it activates all of the muscle fibers to which it is attached. The
2201 spinal cord generally engages the alpha motor neurons which control
2202 few muscle fibers before the motor neurons which control many
2203 muscle fibers. This recruitment strategy allows for precise
2204 movements at low strength. The collection of all motor neurons that
2205 control a muscle is called the motor pool. The brain essentially
2206 says "activate 30% of the motor pool" and the spinal cord recruits
2207 motor neurons until 30% are activated. Since the distribution of
2208 power among motor neurons is unequal and recruitment goes from
2209 weakest to strongest, the first 30% of the motor pool might be 5%
2210 of the strength of the muscle.
2211
2212 My simulated muscles follow a similar design: Each muscle is
2213 defined by a 1-D array of numbers (the "motor pool"). Each entry in
2214 the array represents a motor neuron which controls a number of
2215 muscle fibers equal to the value of the entry. Each muscle has a
2216 scalar strength factor which determines the total force the muscle
2217 can exert when all motor neurons are activated. The effector
2218 function for a muscle takes a number to index into the motor pool,
2219 and then "activates" all the motor neurons whose index is lower or
2220 equal to the number. Each motor-neuron will apply force in
2221 proportion to its value in the array. Lower values cause less
2222 force. The lower values can be put at the "beginning" of the 1-D
2223 array to simulate the layout of actual human muscles, which are
2224 capable of more precise movements when exerting less force. Or, the
2225 motor pool can simulate more exotic recruitment strategies which do
2226 not correspond to human muscles.
2227
2228 This 1D array is defined in an image file for ease of
2229 creation/visualization. Here is an example muscle profile image.
2230
2231 #+caption: A muscle profile image that describes the strengths
2232 #+caption: of each motor neuron in a muscle. White is weakest
2233 #+caption: and dark red is strongest. This particular pattern
2234 #+caption: has weaker motor neurons at the beginning, just
2235 #+caption: like human muscle.
2236 #+name: muscle-recruit
2237 #+ATTR_LaTeX: :width 7cm
2238 [[./images/basic-muscle.png]]
2239
2240 *** Muscle meta-data
2241
2242 #+caption: Program to deal with loading muscle data from a blender
2243 #+caption: file's metadata.
2244 #+name: motor-pool
2245 #+begin_listing clojure
2246 #+BEGIN_SRC clojure
2247 (defn muscle-profile-image
2248 "Get the muscle-profile image from the node's blender meta-data."
2249 [#^Node muscle]
2250 (if-let [image (meta-data muscle "muscle")]
2251 (load-image image)))
2252
2253 (defn muscle-strength
2254 "Return the strength of this muscle, or 1 if it is not defined."
2255 [#^Node muscle]
2256 (if-let [strength (meta-data muscle "strength")]
2257 strength 1))
2258
2259 (defn motor-pool
2260 "Return a vector where each entry is the strength of the \"motor
2261 neuron\" at that part in the muscle."
2262 [#^Node muscle]
2263 (let [profile (muscle-profile-image muscle)]
2264 (vec
2265 (let [width (.getWidth profile)]
2266 (for [x (range width)]
2267 (- 255
2268 (bit-and
2269 0x0000FF
2270 (.getRGB profile x 0))))))))
2271 #+END_SRC
2272 #+end_listing
2273
2274 Of note here is =motor-pool= which interprets the muscle-profile
2275 image in a way that allows me to use gradients between white and
2276 red, instead of shades of gray as I've been using for all the
2277 other senses. This is purely an aesthetic touch.
2278
2279 *** Creating muscles
2280
2281 #+caption: This is the core movement functoion in =CORTEX=, which
2282 #+caption: implements muscles that report on their activation.
2283 #+name: muscle-kernel
2284 #+begin_listing clojure
2285 #+BEGIN_SRC clojure
2286 (defn movement-kernel
2287 "Returns a function which when called with a integer value inside a
2288 running simulation will cause movement in the creature according
2289 to the muscle's position and strength profile. Each function
2290 returns the amount of force applied / max force."
2291 [#^Node creature #^Node muscle]
2292 (let [target (closest-node creature muscle)
2293 axis
2294 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
2295 strength (muscle-strength muscle)
2296
2297 pool (motor-pool muscle)
2298 pool-integral (reductions + pool)
2299 forces
2300 (vec (map #(float (* strength (/ % (last pool-integral))))
2301 pool-integral))
2302 control (.getControl target RigidBodyControl)]
2303 ;;(println-repl (.getName target) axis)
2304 (fn [n]
2305 (let [pool-index (max 0 (min n (dec (count pool))))
2306 force (forces pool-index)]
2307 (.applyTorque control (.mult axis force))
2308 (float (/ force strength))))))
2309
2310 (defn movement!
2311 "Endow the creature with the power of movement. Returns a sequence
2312 of functions, each of which accept an integer value and will
2313 activate their corresponding muscle."
2314 [#^Node creature]
2315 (for [muscle (muscles creature)]
2316 (movement-kernel creature muscle)))
2317 #+END_SRC
2318 #+end_listing
2319
2320
2321 =movement-kernel= creates a function that will move the nearest
2322 physical object to the muscle node. The muscle exerts a rotational
2323 force dependent on it's orientation to the object in the blender
2324 file. The function returned by =movement-kernel= is also a sense
2325 function: it returns the percent of the total muscle strength that
2326 is currently being employed. This is analogous to muscle tension
2327 in humans and completes the sense of proprioception begun in the
2328 last section.
2329
2330
2331
2188 2332
2189 ** =CORTEX= brings complex creatures to life! 2333 ** =CORTEX= brings complex creatures to life!
2190 2334
2191 ** =CORTEX= enables many possiblities for further research 2335 ** =CORTEX= enables many possiblities for further research
2192 2336