changeset 260:959127e21f81

fleshing out text in muscle.org
author Robert McIntyre <rlm@mit.edu>
date Tue, 14 Feb 2012 03:16:50 -0700
parents 7cac5ef852e3
children 2fdcbe8185b1
files images/basic-muscle.png org/movement.org
diffstat 2 files changed, 123 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
     1.1 Binary file images/basic-muscle.png has changed
     2.1 --- a/org/movement.org	Tue Feb 14 02:28:25 2012 -0700
     2.2 +++ b/org/movement.org	Tue Feb 14 03:16:50 2012 -0700
     2.3 @@ -1,4 +1,4 @@
     2.4 -#+title: Movement!
     2.5 +#+title: Simulated Muscles
     2.6  #+author: Robert McIntyre
     2.7  #+email: rlm@mit.edu
     2.8  #+description: muscles for a simulated creature
     2.9 @@ -7,48 +7,61 @@
    2.10  #+INCLUDE: ../../aurellem/org/level-0.org
    2.11  
    2.12  
    2.13 +* Muscles
    2.14 +
    2.15  Surprisingly enough, terristerial creatures only move by using torque
    2.16  applied about their joints.  There's not a single straight line of
    2.17  force in the human body at all!  (A straight line of force would
    2.18 -correspond to some sort of jet or rocket propulseion.)
    2.19 +correspond to some sort of jet or rocket propulsion.)
    2.20  
    2.21 +*(next paragraph is from memory and needs to be checked!)*
    2.22  
    2.23 -Here's how motor-control/ proprioception will work: Each muscle is
    2.24 -defined by a 1-D array of numbers (the "motor pool") each of which
    2.25 -represent muscle fibers. A muscle also has a scalar :strength factor
    2.26 -which determines how strong the muscle as a whole is.  The effector
    2.27 -function for a muscle takes a number < (count motor-pool) and that
    2.28 -number is said to "activate" all the muscle fibers whose index is
    2.29 -lower than the number.  Each fiber will apply force in proportion to
    2.30 -its value in the array.  Lower values cause less force.  The lower
    2.31 -values can be put at the "beginning" of the 1-D array to simulate the
    2.32 -layout of actual human muscles, which are capable of more percise
    2.33 -movements when exerting less force.
    2.34 +In humans, muscles are composed of millions of sarcomeres, which can
    2.35 +contract to exert force. A single motor neuron might control 100-1,000
    2.36 +sarcomeres. When the motor neuron is engaged by the brain, it
    2.37 +activates all of the sarcomeres to which it is attached. Some motor
    2.38 +neurons command many sarcomeres, and some command only a few. The
    2.39 +spinal cord generally engages the motor neurons which control few
    2.40 +sarcomeres before the motor neurons which control many sarcomeres.
    2.41 +This recruitment stragety allows for percise movements at low
    2.42 +strength. The collection of all motor neurons that control a muscle is
    2.43 +called the motor pool. The brain essentially says "activate 30% of the
    2.44 +motor pool" and the spinal cord recruits motor neurons untill 30% are
    2.45 +activated. Since the distribution of power among motor neurons is
    2.46 +unequal and recruitment goes from weakest to strongest, 30% of the
    2.47 +motor pool might be 5% of the strength of the muscle.
    2.48 +
    2.49 +My simulated muscles follow a similiar design: Each muscle is defined
    2.50 +by a 1-D array of numbers (the "motor pool"). Each number represents a
    2.51 +motor neuron which controlls a number of sarcomeres equal to the
    2.52 +number. A muscle also has a scalar :strength factor which determines
    2.53 +the total force the muscle can exert when all motor neurons are
    2.54 +activated.  The effector function for a muscle takes a number to index
    2.55 +into the motor pool, and that number "activates" all the motor neurons
    2.56 +whose index is lower or equal to the number.  Each motor-neuron will
    2.57 +apply force in proportion to its value in the array.  Lower values
    2.58 +cause less force.  The lower values can be put at the "beginning" of
    2.59 +the 1-D array to simulate the layout of actual human muscles, which
    2.60 +are capable of more percise movements when exerting less force. Or,
    2.61 +the motor pool can simulate more exoitic recruitment strageties which
    2.62 +do not correspond to human muscles. 
    2.63 +
    2.64 +This 1D array is defined in an image file for ease of
    2.65 +creation/visualization. Here is an example muscle profile image.
    2.66 +
    2.67 +#+caption: A muscle profile image that describes the strengths of each motor neuron in a muscle. White is weakest and dark red is strongest. This particular pattern has weaker motor neurons at the beginning, just like human muscle.
    2.68 +[[../images/basic-muscle.png]]
    2.69 +
    2.70 +* Blender Meta-data
    2.71 +
    2.72 +In blender, each muscle is an empty node whose top level parent is
    2.73 +named "muscles", just like eyes, ears, and joints.
    2.74 +
    2.75 +These functions define the expected meta-data for a muscle node.
    2.76  
    2.77  #+name: movement
    2.78  #+begin_src clojure 
    2.79 -(ns cortex.movement
    2.80 -  "Give simulated creatures defined in special blender files the power
    2.81 -   to move around in a simulated environment."
    2.82 -  {:author "Robert McIntyre"}
    2.83 -  (:use (cortex world util sense body))
    2.84 -  (:use clojure.contrib.def)
    2.85 -  (:import java.awt.image.BufferedImage)
    2.86 -  (:import com.jme3.scene.Node)
    2.87 -  (:import com.jme3.math.Vector3f)
    2.88 -  (:import com.jme3.bullet.control.RigidBodyControl))
    2.89 -
    2.90 -(defn muscle-profile
    2.91 -  "Return a vector where each entry is the strength of the \"motor
    2.92 -  pool\" at that part in the muscle."
    2.93 -  [#^BufferedImage profile]
    2.94 -  (vec
    2.95 -   (let [width (.getWidth profile)]
    2.96 -     (for [x (range width)]
    2.97 -       (- 255
    2.98 -          (bit-and
    2.99 -           0x0000FF
   2.100 -           (.getRGB profile x 0)))))))
   2.101 +(in-ns 'cortex.movement)
   2.102  
   2.103  (defvar 
   2.104    ^{:arglists '([creature])}
   2.105 @@ -56,30 +69,61 @@
   2.106    (sense-nodes "muscles")
   2.107    "Return the children of the creature's \"muscles\" node.")
   2.108  
   2.109 -(defn movement-fn
   2.110 +(defn muscle-profile-image
   2.111 +  "Get the muscle-profile image from the node's blender meta-data."
   2.112 +  [#^Node muscle]
   2.113 +  (if-let [image (meta-data muscle "muscle")]
   2.114 +    (load-image image)))
   2.115 +
   2.116 +(defn muscle-strength
   2.117 +  "Return the strength of this muscle, or 1 if it is not defined."
   2.118 +  [#^Node muscle]
   2.119 +  (if-let [strength (meta-data muscle "strength")]
   2.120 +    strength 1))
   2.121 +
   2.122 +(defn motor-pool
   2.123 +  "Return a vector where each entry is the strength of the \"motor
   2.124 +   neuron\" at that part in the muscle."
   2.125 +  [#^Node muscle]
   2.126 +  (let [profile (muscle-profile-image muscle)]
   2.127 +    (vec
   2.128 +     (let [width (.getWidth profile)]
   2.129 +       (for [x (range width)]
   2.130 +       (- 255
   2.131 +          (bit-and
   2.132 +           0x0000FF
   2.133 +           (.getRGB profile x 0))))))))
   2.134 +#+end_src
   2.135 +
   2.136 +Of note here is =(motor-pool)= which interprets the muscle-profile
   2.137 +image in a way that allows me to use gradients between white and red,
   2.138 +instead of shades of gray as I've been using for all the other
   2.139 +senses. This is purely an aesthetic touch.
   2.140 +
   2.141 +* Creating Muscles
   2.142 +#+begin_src clojure
   2.143 +(defn movement-kernel
   2.144    "Returns a function which when called with a integer value inside a
   2.145     running simulation will cause movement in the creature according
   2.146     to the muscle's position and strength profile. Each function
   2.147     returns the amount of force applied / max force."
   2.148 -  [#^Node parts #^Node muscle]
   2.149 -  (let [target (closest-node parts muscle)
   2.150 +  [#^Node creature #^Node muscle]
   2.151 +  (let [target (closest-node creature muscle)
   2.152          axis
   2.153          (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
   2.154 -        strength (meta-data muscle "strength")
   2.155 -        image-name (read-string (meta-data muscle "muscle"))
   2.156 -        image (load-image image-name)
   2.157 -        fibers (muscle-profile image)
   2.158 -        fiber-integral (reductions + fibers)
   2.159 +        strength (muscle-strength muscle)
   2.160 +        
   2.161 +        pool (motor-pool muscle)
   2.162 +        pool-integral (reductions + pool)
   2.163          force-index
   2.164 -        (vec (map  #(float (* strength (/ % (last fiber-integral))))
   2.165 -              fiber-integral))
   2.166 +        (vec (map  #(float (* strength (/ % (last pool-integral))))
   2.167 +              pool-integral))
   2.168          control (.getControl target RigidBodyControl)]
   2.169      (fn [n]
   2.170 -      (let [pool-index (max 0 (min n (dec (count fibers))))
   2.171 +      (let [pool-index (max 0 (min n (dec (count pool))))
   2.172              force (force-index pool-index)]
   2.173          (.applyTorque control (.mult axis force))
   2.174          (float (/ force strength))))))
   2.175 -        
   2.176  
   2.177  (defn movement!
   2.178    "Endow the creature with the power of movement. Returns a sequence
   2.179 @@ -87,8 +131,23 @@
   2.180     activate their corresponding muscle."
   2.181    [#^Node creature]
   2.182      (for [muscle (muscles creature)]
   2.183 -      (movement-fn creature muscle)))
   2.184 +      (movement-kernel creature muscle)))
   2.185 +#+end_src
   2.186  
   2.187 +=(movement-kernel)= creates a function that will move the nearest
   2.188 +physical object to the muscle node. The muscle exerts a rotational
   2.189 +force dependant on it's orientation to the object in the blender
   2.190 +file. The function returned by =(movement-kernel)= is also a sense
   2.191 +function: it returns the percent of the total muscle strength that is
   2.192 +currently being employed. This is analogous to muscle tension in
   2.193 +humans and completes the sense of proprioception begun in the last
   2.194 +post. 
   2.195 +
   2.196 +* Visualizing Muscle Tension
   2.197 +Muscle exertion is a percent of a total, so the visulazation is just a
   2.198 +simple percent bar.
   2.199 +
   2.200 +#+begin_src clojure
   2.201  (defn movement-display-kernel
   2.202    "Display muscle exertion data as a bar filling up with red."
   2.203    [exertion]
   2.204 @@ -108,11 +167,26 @@
   2.205    displays each element of the list to the screen."
   2.206    []
   2.207    (view-sense movement-display-kernel))
   2.208 -
   2.209  #+end_src
   2.210  
   2.211 +* Adding Touch to the Worm
   2.212  
   2.213  
   2.214 +* Headers
   2.215 +#+name: muscle-header
   2.216 +#+begin_src clojure
   2.217 +(ns cortex.movement
   2.218 +  "Give simulated creatures defined in special blender files the power
   2.219 +   to move around in a simulated environment."
   2.220 +  {:author "Robert McIntyre"}
   2.221 +  (:use (cortex world util sense body))
   2.222 +  (:use clojure.contrib.def)
   2.223 +  (:import java.awt.image.BufferedImage)
   2.224 +  (:import com.jme3.scene.Node)
   2.225 +  (:import com.jme3.math.Vector3f)
   2.226 +  (:import com.jme3.bullet.control.RigidBodyControl))
   2.227 +#+end_src
   2.228 +
   2.229  
   2.230  
   2.231  * COMMENT code generation