Mercurial > cortex
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