Mercurial > cortex
changeset 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 |
files | thesis/cortex.org thesis/images/basic-muscle.png |
diffstat | 2 files changed, 145 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
1.1 --- a/thesis/cortex.org Fri Mar 28 23:17:10 2014 -0400 1.2 +++ b/thesis/cortex.org Fri Mar 28 23:30:39 2014 -0400 1.3 @@ -2184,7 +2184,151 @@ 1.4 #+ATTR_LaTeX: :width 11cm 1.5 [[./images/proprio.png]] 1.6 1.7 -** Muscles are both effectors and sensors 1.8 +** COMMENT Muscles are both effectors and sensors 1.9 + 1.10 + Surprisingly enough, terrestrial creatures only move by using 1.11 + torque applied about their joints. There's not a single straight 1.12 + line of force in the human body at all! (A straight line of force 1.13 + would correspond to some sort of jet or rocket propulsion.) 1.14 + 1.15 + In humans, muscles are composed of muscle fibers which can contract 1.16 + to exert force. The muscle fibers which compose a muscle are 1.17 + partitioned into discrete groups which are each controlled by a 1.18 + single alpha motor neuron. A single alpha motor neuron might 1.19 + control as little as three or as many as one thousand muscle 1.20 + fibers. When the alpha motor neuron is engaged by the spinal cord, 1.21 + it activates all of the muscle fibers to which it is attached. The 1.22 + spinal cord generally engages the alpha motor neurons which control 1.23 + few muscle fibers before the motor neurons which control many 1.24 + muscle fibers. This recruitment strategy allows for precise 1.25 + movements at low strength. The collection of all motor neurons that 1.26 + control a muscle is called the motor pool. The brain essentially 1.27 + says "activate 30% of the motor pool" and the spinal cord recruits 1.28 + motor neurons until 30% are activated. Since the distribution of 1.29 + power among motor neurons is unequal and recruitment goes from 1.30 + weakest to strongest, the first 30% of the motor pool might be 5% 1.31 + of the strength of the muscle. 1.32 + 1.33 + My simulated muscles follow a similar design: Each muscle is 1.34 + defined by a 1-D array of numbers (the "motor pool"). Each entry in 1.35 + the array represents a motor neuron which controls a number of 1.36 + muscle fibers equal to the value of the entry. Each muscle has a 1.37 + scalar strength factor which determines the total force the muscle 1.38 + can exert when all motor neurons are activated. The effector 1.39 + function for a muscle takes a number to index into the motor pool, 1.40 + and then "activates" all the motor neurons whose index is lower or 1.41 + equal to the number. Each motor-neuron will apply force in 1.42 + proportion to its value in the array. Lower values cause less 1.43 + force. The lower values can be put at the "beginning" of the 1-D 1.44 + array to simulate the layout of actual human muscles, which are 1.45 + capable of more precise movements when exerting less force. Or, the 1.46 + motor pool can simulate more exotic recruitment strategies which do 1.47 + not correspond to human muscles. 1.48 + 1.49 + This 1D array is defined in an image file for ease of 1.50 + creation/visualization. Here is an example muscle profile image. 1.51 + 1.52 + #+caption: A muscle profile image that describes the strengths 1.53 + #+caption: of each motor neuron in a muscle. White is weakest 1.54 + #+caption: and dark red is strongest. This particular pattern 1.55 + #+caption: has weaker motor neurons at the beginning, just 1.56 + #+caption: like human muscle. 1.57 + #+name: muscle-recruit 1.58 + #+ATTR_LaTeX: :width 7cm 1.59 + [[./images/basic-muscle.png]] 1.60 + 1.61 +*** Muscle meta-data 1.62 + 1.63 + #+caption: Program to deal with loading muscle data from a blender 1.64 + #+caption: file's metadata. 1.65 + #+name: motor-pool 1.66 + #+begin_listing clojure 1.67 + #+BEGIN_SRC clojure 1.68 +(defn muscle-profile-image 1.69 + "Get the muscle-profile image from the node's blender meta-data." 1.70 + [#^Node muscle] 1.71 + (if-let [image (meta-data muscle "muscle")] 1.72 + (load-image image))) 1.73 + 1.74 +(defn muscle-strength 1.75 + "Return the strength of this muscle, or 1 if it is not defined." 1.76 + [#^Node muscle] 1.77 + (if-let [strength (meta-data muscle "strength")] 1.78 + strength 1)) 1.79 + 1.80 +(defn motor-pool 1.81 + "Return a vector where each entry is the strength of the \"motor 1.82 + neuron\" at that part in the muscle." 1.83 + [#^Node muscle] 1.84 + (let [profile (muscle-profile-image muscle)] 1.85 + (vec 1.86 + (let [width (.getWidth profile)] 1.87 + (for [x (range width)] 1.88 + (- 255 1.89 + (bit-and 1.90 + 0x0000FF 1.91 + (.getRGB profile x 0)))))))) 1.92 + #+END_SRC 1.93 + #+end_listing 1.94 + 1.95 + Of note here is =motor-pool= which interprets the muscle-profile 1.96 + image in a way that allows me to use gradients between white and 1.97 + red, instead of shades of gray as I've been using for all the 1.98 + other senses. This is purely an aesthetic touch. 1.99 + 1.100 +*** Creating muscles 1.101 + 1.102 + #+caption: This is the core movement functoion in =CORTEX=, which 1.103 + #+caption: implements muscles that report on their activation. 1.104 + #+name: muscle-kernel 1.105 + #+begin_listing clojure 1.106 + #+BEGIN_SRC clojure 1.107 +(defn movement-kernel 1.108 + "Returns a function which when called with a integer value inside a 1.109 + running simulation will cause movement in the creature according 1.110 + to the muscle's position and strength profile. Each function 1.111 + returns the amount of force applied / max force." 1.112 + [#^Node creature #^Node muscle] 1.113 + (let [target (closest-node creature muscle) 1.114 + axis 1.115 + (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y) 1.116 + strength (muscle-strength muscle) 1.117 + 1.118 + pool (motor-pool muscle) 1.119 + pool-integral (reductions + pool) 1.120 + forces 1.121 + (vec (map #(float (* strength (/ % (last pool-integral)))) 1.122 + pool-integral)) 1.123 + control (.getControl target RigidBodyControl)] 1.124 + ;;(println-repl (.getName target) axis) 1.125 + (fn [n] 1.126 + (let [pool-index (max 0 (min n (dec (count pool)))) 1.127 + force (forces pool-index)] 1.128 + (.applyTorque control (.mult axis force)) 1.129 + (float (/ force strength)))))) 1.130 + 1.131 +(defn movement! 1.132 + "Endow the creature with the power of movement. Returns a sequence 1.133 + of functions, each of which accept an integer value and will 1.134 + activate their corresponding muscle." 1.135 + [#^Node creature] 1.136 + (for [muscle (muscles creature)] 1.137 + (movement-kernel creature muscle))) 1.138 + #+END_SRC 1.139 + #+end_listing 1.140 + 1.141 + 1.142 + =movement-kernel= creates a function that will move the nearest 1.143 + physical object to the muscle node. The muscle exerts a rotational 1.144 + force dependent on it's orientation to the object in the blender 1.145 + file. The function returned by =movement-kernel= is also a sense 1.146 + function: it returns the percent of the total muscle strength that 1.147 + is currently being employed. This is analogous to muscle tension 1.148 + in humans and completes the sense of proprioception begun in the 1.149 + last section. 1.150 + 1.151 + 1.152 + 1.153 1.154 ** =CORTEX= brings complex creatures to life! 1.155
2.1 Binary file thesis/images/basic-muscle.png has changed