Mercurial > cortex
view 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 source
1 #+title: Simulated Muscles2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: muscles for a simulated creature5 #+keywords: simulation, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org10 * Muscles12 Surprisingly enough, terristerial creatures only move by using torque13 applied about their joints. There's not a single straight line of14 force in the human body at all! (A straight line of force would15 correspond to some sort of jet or rocket propulsion.)17 *(next paragraph is from memory and needs to be checked!)*19 In humans, muscles are composed of millions of sarcomeres, which can20 contract to exert force. A single motor neuron might control 100-1,00021 sarcomeres. When the motor neuron is engaged by the brain, it22 activates all of the sarcomeres to which it is attached. Some motor23 neurons command many sarcomeres, and some command only a few. The24 spinal cord generally engages the motor neurons which control few25 sarcomeres before the motor neurons which control many sarcomeres.26 This recruitment stragety allows for percise movements at low27 strength. The collection of all motor neurons that control a muscle is28 called the motor pool. The brain essentially says "activate 30% of the29 motor pool" and the spinal cord recruits motor neurons untill 30% are30 activated. Since the distribution of power among motor neurons is31 unequal and recruitment goes from weakest to strongest, 30% of the32 motor pool might be 5% of the strength of the muscle.34 My simulated muscles follow a similiar design: Each muscle is defined35 by a 1-D array of numbers (the "motor pool"). Each number represents a36 motor neuron which controlls a number of sarcomeres equal to the37 number. A muscle also has a scalar :strength factor which determines38 the total force the muscle can exert when all motor neurons are39 activated. The effector function for a muscle takes a number to index40 into the motor pool, and that number "activates" all the motor neurons41 whose index is lower or equal to the number. Each motor-neuron will42 apply force in proportion to its value in the array. Lower values43 cause less force. The lower values can be put at the "beginning" of44 the 1-D array to simulate the layout of actual human muscles, which45 are capable of more percise movements when exerting less force. Or,46 the motor pool can simulate more exoitic recruitment strageties which47 do not correspond to human muscles.49 This 1D array is defined in an image file for ease of50 creation/visualization. Here is an example muscle profile image.52 #+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.53 [[../images/basic-muscle.png]]55 * Blender Meta-data57 In blender, each muscle is an empty node whose top level parent is58 named "muscles", just like eyes, ears, and joints.60 These functions define the expected meta-data for a muscle node.62 #+name: movement63 #+begin_src clojure64 (in-ns 'cortex.movement)66 (defvar67 ^{:arglists '([creature])}68 muscles69 (sense-nodes "muscles")70 "Return the children of the creature's \"muscles\" node.")72 (defn muscle-profile-image73 "Get the muscle-profile image from the node's blender meta-data."74 [#^Node muscle]75 (if-let [image (meta-data muscle "muscle")]76 (load-image image)))78 (defn muscle-strength79 "Return the strength of this muscle, or 1 if it is not defined."80 [#^Node muscle]81 (if-let [strength (meta-data muscle "strength")]82 strength 1))84 (defn motor-pool85 "Return a vector where each entry is the strength of the \"motor86 neuron\" at that part in the muscle."87 [#^Node muscle]88 (let [profile (muscle-profile-image muscle)]89 (vec90 (let [width (.getWidth profile)]91 (for [x (range width)]92 (- 25593 (bit-and94 0x0000FF95 (.getRGB profile x 0))))))))96 #+end_src98 Of note here is =(motor-pool)= which interprets the muscle-profile99 image in a way that allows me to use gradients between white and red,100 instead of shades of gray as I've been using for all the other101 senses. This is purely an aesthetic touch.103 * Creating Muscles104 #+begin_src clojure105 (defn movement-kernel106 "Returns a function which when called with a integer value inside a107 running simulation will cause movement in the creature according108 to the muscle's position and strength profile. Each function109 returns the amount of force applied / max force."110 [#^Node creature #^Node muscle]111 (let [target (closest-node creature muscle)112 axis113 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)114 strength (muscle-strength muscle)116 pool (motor-pool muscle)117 pool-integral (reductions + pool)118 force-index119 (vec (map #(float (* strength (/ % (last pool-integral))))120 pool-integral))121 control (.getControl target RigidBodyControl)]122 (fn [n]123 (let [pool-index (max 0 (min n (dec (count pool))))124 force (force-index pool-index)]125 (.applyTorque control (.mult axis force))126 (float (/ force strength))))))128 (defn movement!129 "Endow the creature with the power of movement. Returns a sequence130 of functions, each of which accept an integer value and will131 activate their corresponding muscle."132 [#^Node creature]133 (for [muscle (muscles creature)]134 (movement-kernel creature muscle)))135 #+end_src137 =(movement-kernel)= creates a function that will move the nearest138 physical object to the muscle node. The muscle exerts a rotational139 force dependant on it's orientation to the object in the blender140 file. The function returned by =(movement-kernel)= is also a sense141 function: it returns the percent of the total muscle strength that is142 currently being employed. This is analogous to muscle tension in143 humans and completes the sense of proprioception begun in the last144 post.146 * Visualizing Muscle Tension147 Muscle exertion is a percent of a total, so the visulazation is just a148 simple percent bar.150 #+begin_src clojure151 (defn movement-display-kernel152 "Display muscle exertion data as a bar filling up with red."153 [exertion]154 (let [height 20155 width 300156 image (BufferedImage. width height157 BufferedImage/TYPE_INT_RGB)158 fill (min (int (* width exertion)) width)]159 (dorun160 (for [x (range fill)161 y (range height)]162 (.setRGB image x y 0xFF0000)))163 image))165 (defn view-movement166 "Creates a function which accepts a list of muscle-exertion data and167 displays each element of the list to the screen."168 []169 (view-sense movement-display-kernel))170 #+end_src172 * Adding Touch to the Worm175 * Headers176 #+name: muscle-header177 #+begin_src clojure178 (ns cortex.movement179 "Give simulated creatures defined in special blender files the power180 to move around in a simulated environment."181 {:author "Robert McIntyre"}182 (:use (cortex world util sense body))183 (:use clojure.contrib.def)184 (:import java.awt.image.BufferedImage)185 (:import com.jme3.scene.Node)186 (:import com.jme3.math.Vector3f)187 (:import com.jme3.bullet.control.RigidBodyControl))188 #+end_src192 * COMMENT code generation193 #+begin_src clojure :tangle ../src/cortex/movement.clj194 <<movement>>195 #+end_src