diff org/movement.org @ 260:959127e21f81

fleshing out text in muscle.org
author Robert McIntyre <rlm@mit.edu>
date Tue, 14 Feb 2012 03:16:50 -0700
parents 66fbab414d45
children 2fdcbe8185b1
line wrap: on
line diff
     1.1 --- a/org/movement.org	Tue Feb 14 02:28:25 2012 -0700
     1.2 +++ b/org/movement.org	Tue Feb 14 03:16:50 2012 -0700
     1.3 @@ -1,4 +1,4 @@
     1.4 -#+title: Movement!
     1.5 +#+title: Simulated Muscles
     1.6  #+author: Robert McIntyre
     1.7  #+email: rlm@mit.edu
     1.8  #+description: muscles for a simulated creature
     1.9 @@ -7,48 +7,61 @@
    1.10  #+INCLUDE: ../../aurellem/org/level-0.org
    1.11  
    1.12  
    1.13 +* Muscles
    1.14 +
    1.15  Surprisingly enough, terristerial creatures only move by using torque
    1.16  applied about their joints.  There's not a single straight line of
    1.17  force in the human body at all!  (A straight line of force would
    1.18 -correspond to some sort of jet or rocket propulseion.)
    1.19 +correspond to some sort of jet or rocket propulsion.)
    1.20  
    1.21 +*(next paragraph is from memory and needs to be checked!)*
    1.22  
    1.23 -Here's how motor-control/ proprioception will work: Each muscle is
    1.24 -defined by a 1-D array of numbers (the "motor pool") each of which
    1.25 -represent muscle fibers. A muscle also has a scalar :strength factor
    1.26 -which determines how strong the muscle as a whole is.  The effector
    1.27 -function for a muscle takes a number < (count motor-pool) and that
    1.28 -number is said to "activate" all the muscle fibers whose index is
    1.29 -lower than the number.  Each fiber will apply force in proportion to
    1.30 -its value in the array.  Lower values cause less force.  The lower
    1.31 -values can be put at the "beginning" of the 1-D array to simulate the
    1.32 -layout of actual human muscles, which are capable of more percise
    1.33 -movements when exerting less force.
    1.34 +In humans, muscles are composed of millions of sarcomeres, which can
    1.35 +contract to exert force. A single motor neuron might control 100-1,000
    1.36 +sarcomeres. When the motor neuron is engaged by the brain, it
    1.37 +activates all of the sarcomeres to which it is attached. Some motor
    1.38 +neurons command many sarcomeres, and some command only a few. The
    1.39 +spinal cord generally engages the motor neurons which control few
    1.40 +sarcomeres before the motor neurons which control many sarcomeres.
    1.41 +This recruitment stragety allows for percise movements at low
    1.42 +strength. The collection of all motor neurons that control a muscle is
    1.43 +called the motor pool. The brain essentially says "activate 30% of the
    1.44 +motor pool" and the spinal cord recruits motor neurons untill 30% are
    1.45 +activated. Since the distribution of power among motor neurons is
    1.46 +unequal and recruitment goes from weakest to strongest, 30% of the
    1.47 +motor pool might be 5% of the strength of the muscle.
    1.48 +
    1.49 +My simulated muscles follow a similiar design: Each muscle is defined
    1.50 +by a 1-D array of numbers (the "motor pool"). Each number represents a
    1.51 +motor neuron which controlls a number of sarcomeres equal to the
    1.52 +number. A muscle also has a scalar :strength factor which determines
    1.53 +the total force the muscle can exert when all motor neurons are
    1.54 +activated.  The effector function for a muscle takes a number to index
    1.55 +into the motor pool, and that number "activates" all the motor neurons
    1.56 +whose index is lower or equal to the number.  Each motor-neuron will
    1.57 +apply force in proportion to its value in the array.  Lower values
    1.58 +cause less force.  The lower values can be put at the "beginning" of
    1.59 +the 1-D array to simulate the layout of actual human muscles, which
    1.60 +are capable of more percise movements when exerting less force. Or,
    1.61 +the motor pool can simulate more exoitic recruitment strageties which
    1.62 +do not correspond to human muscles. 
    1.63 +
    1.64 +This 1D array is defined in an image file for ease of
    1.65 +creation/visualization. Here is an example muscle profile image.
    1.66 +
    1.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.
    1.68 +[[../images/basic-muscle.png]]
    1.69 +
    1.70 +* Blender Meta-data
    1.71 +
    1.72 +In blender, each muscle is an empty node whose top level parent is
    1.73 +named "muscles", just like eyes, ears, and joints.
    1.74 +
    1.75 +These functions define the expected meta-data for a muscle node.
    1.76  
    1.77  #+name: movement
    1.78  #+begin_src clojure 
    1.79 -(ns cortex.movement
    1.80 -  "Give simulated creatures defined in special blender files the power
    1.81 -   to move around in a simulated environment."
    1.82 -  {:author "Robert McIntyre"}
    1.83 -  (:use (cortex world util sense body))
    1.84 -  (:use clojure.contrib.def)
    1.85 -  (:import java.awt.image.BufferedImage)
    1.86 -  (:import com.jme3.scene.Node)
    1.87 -  (:import com.jme3.math.Vector3f)
    1.88 -  (:import com.jme3.bullet.control.RigidBodyControl))
    1.89 -
    1.90 -(defn muscle-profile
    1.91 -  "Return a vector where each entry is the strength of the \"motor
    1.92 -  pool\" at that part in the muscle."
    1.93 -  [#^BufferedImage profile]
    1.94 -  (vec
    1.95 -   (let [width (.getWidth profile)]
    1.96 -     (for [x (range width)]
    1.97 -       (- 255
    1.98 -          (bit-and
    1.99 -           0x0000FF
   1.100 -           (.getRGB profile x 0)))))))
   1.101 +(in-ns 'cortex.movement)
   1.102  
   1.103  (defvar 
   1.104    ^{:arglists '([creature])}
   1.105 @@ -56,30 +69,61 @@
   1.106    (sense-nodes "muscles")
   1.107    "Return the children of the creature's \"muscles\" node.")
   1.108  
   1.109 -(defn movement-fn
   1.110 +(defn muscle-profile-image
   1.111 +  "Get the muscle-profile image from the node's blender meta-data."
   1.112 +  [#^Node muscle]
   1.113 +  (if-let [image (meta-data muscle "muscle")]
   1.114 +    (load-image image)))
   1.115 +
   1.116 +(defn muscle-strength
   1.117 +  "Return the strength of this muscle, or 1 if it is not defined."
   1.118 +  [#^Node muscle]
   1.119 +  (if-let [strength (meta-data muscle "strength")]
   1.120 +    strength 1))
   1.121 +
   1.122 +(defn motor-pool
   1.123 +  "Return a vector where each entry is the strength of the \"motor
   1.124 +   neuron\" at that part in the muscle."
   1.125 +  [#^Node muscle]
   1.126 +  (let [profile (muscle-profile-image muscle)]
   1.127 +    (vec
   1.128 +     (let [width (.getWidth profile)]
   1.129 +       (for [x (range width)]
   1.130 +       (- 255
   1.131 +          (bit-and
   1.132 +           0x0000FF
   1.133 +           (.getRGB profile x 0))))))))
   1.134 +#+end_src
   1.135 +
   1.136 +Of note here is =(motor-pool)= which interprets the muscle-profile
   1.137 +image in a way that allows me to use gradients between white and red,
   1.138 +instead of shades of gray as I've been using for all the other
   1.139 +senses. This is purely an aesthetic touch.
   1.140 +
   1.141 +* Creating Muscles
   1.142 +#+begin_src clojure
   1.143 +(defn movement-kernel
   1.144    "Returns a function which when called with a integer value inside a
   1.145     running simulation will cause movement in the creature according
   1.146     to the muscle's position and strength profile. Each function
   1.147     returns the amount of force applied / max force."
   1.148 -  [#^Node parts #^Node muscle]
   1.149 -  (let [target (closest-node parts muscle)
   1.150 +  [#^Node creature #^Node muscle]
   1.151 +  (let [target (closest-node creature muscle)
   1.152          axis
   1.153          (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
   1.154 -        strength (meta-data muscle "strength")
   1.155 -        image-name (read-string (meta-data muscle "muscle"))
   1.156 -        image (load-image image-name)
   1.157 -        fibers (muscle-profile image)
   1.158 -        fiber-integral (reductions + fibers)
   1.159 +        strength (muscle-strength muscle)
   1.160 +        
   1.161 +        pool (motor-pool muscle)
   1.162 +        pool-integral (reductions + pool)
   1.163          force-index
   1.164 -        (vec (map  #(float (* strength (/ % (last fiber-integral))))
   1.165 -              fiber-integral))
   1.166 +        (vec (map  #(float (* strength (/ % (last pool-integral))))
   1.167 +              pool-integral))
   1.168          control (.getControl target RigidBodyControl)]
   1.169      (fn [n]
   1.170 -      (let [pool-index (max 0 (min n (dec (count fibers))))
   1.171 +      (let [pool-index (max 0 (min n (dec (count pool))))
   1.172              force (force-index pool-index)]
   1.173          (.applyTorque control (.mult axis force))
   1.174          (float (/ force strength))))))
   1.175 -        
   1.176  
   1.177  (defn movement!
   1.178    "Endow the creature with the power of movement. Returns a sequence
   1.179 @@ -87,8 +131,23 @@
   1.180     activate their corresponding muscle."
   1.181    [#^Node creature]
   1.182      (for [muscle (muscles creature)]
   1.183 -      (movement-fn creature muscle)))
   1.184 +      (movement-kernel creature muscle)))
   1.185 +#+end_src
   1.186  
   1.187 +=(movement-kernel)= creates a function that will move the nearest
   1.188 +physical object to the muscle node. The muscle exerts a rotational
   1.189 +force dependant on it's orientation to the object in the blender
   1.190 +file. The function returned by =(movement-kernel)= is also a sense
   1.191 +function: it returns the percent of the total muscle strength that is
   1.192 +currently being employed. This is analogous to muscle tension in
   1.193 +humans and completes the sense of proprioception begun in the last
   1.194 +post. 
   1.195 +
   1.196 +* Visualizing Muscle Tension
   1.197 +Muscle exertion is a percent of a total, so the visulazation is just a
   1.198 +simple percent bar.
   1.199 +
   1.200 +#+begin_src clojure
   1.201  (defn movement-display-kernel
   1.202    "Display muscle exertion data as a bar filling up with red."
   1.203    [exertion]
   1.204 @@ -108,11 +167,26 @@
   1.205    displays each element of the list to the screen."
   1.206    []
   1.207    (view-sense movement-display-kernel))
   1.208 -
   1.209  #+end_src
   1.210  
   1.211 +* Adding Touch to the Worm
   1.212  
   1.213  
   1.214 +* Headers
   1.215 +#+name: muscle-header
   1.216 +#+begin_src clojure
   1.217 +(ns cortex.movement
   1.218 +  "Give simulated creatures defined in special blender files the power
   1.219 +   to move around in a simulated environment."
   1.220 +  {:author "Robert McIntyre"}
   1.221 +  (:use (cortex world util sense body))
   1.222 +  (:use clojure.contrib.def)
   1.223 +  (:import java.awt.image.BufferedImage)
   1.224 +  (:import com.jme3.scene.Node)
   1.225 +  (:import com.jme3.math.Vector3f)
   1.226 +  (:import com.jme3.bullet.control.RigidBodyControl))
   1.227 +#+end_src
   1.228 +
   1.229  
   1.230  
   1.231  * COMMENT code generation