annotate org/movement.org @ 223:14718d7b19eb

minor fix
author Robert McIntyre <rlm@mit.edu>
date Sat, 11 Feb 2012 12:26:54 -0700
parents 66fbab414d45
children 959127e21f81
rev   line source
rlm@158 1 #+title: Movement!
rlm@158 2 #+author: Robert McIntyre
rlm@158 3 #+email: rlm@mit.edu
rlm@158 4 #+description: muscles for a simulated creature
rlm@158 5 #+keywords: simulation, jMonkeyEngine3, clojure
rlm@158 6 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@158 7 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@158 8
rlm@180 9
rlm@180 10 Surprisingly enough, terristerial creatures only move by using torque
rlm@180 11 applied about their joints. There's not a single straight line of
rlm@180 12 force in the human body at all! (A straight line of force would
rlm@180 13 correspond to some sort of jet or rocket propulseion.)
rlm@180 14
rlm@180 15
rlm@180 16 Here's how motor-control/ proprioception will work: Each muscle is
rlm@180 17 defined by a 1-D array of numbers (the "motor pool") each of which
rlm@180 18 represent muscle fibers. A muscle also has a scalar :strength factor
rlm@180 19 which determines how strong the muscle as a whole is. The effector
rlm@180 20 function for a muscle takes a number < (count motor-pool) and that
rlm@180 21 number is said to "activate" all the muscle fibers whose index is
rlm@180 22 lower than the number. Each fiber will apply force in proportion to
rlm@180 23 its value in the array. Lower values cause less force. The lower
rlm@180 24 values can be put at the "beginning" of the 1-D array to simulate the
rlm@180 25 layout of actual human muscles, which are capable of more percise
rlm@180 26 movements when exerting less force.
rlm@180 27
rlm@158 28 #+name: movement
rlm@158 29 #+begin_src clojure
rlm@158 30 (ns cortex.movement
rlm@180 31 "Give simulated creatures defined in special blender files the power
rlm@180 32 to move around in a simulated environment."
rlm@180 33 {:author "Robert McIntyre"}
rlm@158 34 (:use (cortex world util sense body))
rlm@180 35 (:use clojure.contrib.def)
rlm@180 36 (:import java.awt.image.BufferedImage)
rlm@180 37 (:import com.jme3.scene.Node)
rlm@180 38 (:import com.jme3.math.Vector3f)
rlm@180 39 (:import com.jme3.bullet.control.RigidBodyControl))
rlm@158 40
rlm@180 41 (defn muscle-profile
rlm@180 42 "Return a vector where each entry is the strength of the \"motor
rlm@180 43 pool\" at that part in the muscle."
rlm@180 44 [#^BufferedImage profile]
rlm@158 45 (vec
rlm@180 46 (let [width (.getWidth profile)]
rlm@158 47 (for [x (range width)]
rlm@158 48 (- 255
rlm@158 49 (bit-and
rlm@158 50 0x0000FF
rlm@180 51 (.getRGB profile x 0)))))))
rlm@158 52
rlm@180 53 (defvar
rlm@180 54 ^{:arglists '([creature])}
rlm@180 55 muscles
rlm@180 56 (sense-nodes "muscles")
rlm@180 57 "Return the children of the creature's \"muscles\" node.")
rlm@158 58
rlm@180 59 (defn movement-fn
rlm@180 60 "Returns a function which when called with a integer value inside a
rlm@191 61 running simulation will cause movement in the creature according
rlm@191 62 to the muscle's position and strength profile. Each function
rlm@191 63 returns the amount of force applied / max force."
rlm@180 64 [#^Node parts #^Node muscle]
rlm@158 65 (let [target (closest-node parts muscle)
rlm@158 66 axis
rlm@158 67 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
rlm@158 68 strength (meta-data muscle "strength")
rlm@158 69 image-name (read-string (meta-data muscle "muscle"))
rlm@180 70 image (load-image image-name)
rlm@180 71 fibers (muscle-profile image)
rlm@158 72 fiber-integral (reductions + fibers)
rlm@191 73 force-index
rlm@191 74 (vec (map #(float (* strength (/ % (last fiber-integral))))
rlm@191 75 fiber-integral))
rlm@158 76 control (.getControl target RigidBodyControl)]
rlm@158 77 (fn [n]
rlm@191 78 (let [pool-index (max 0 (min n (dec (count fibers))))
rlm@191 79 force (force-index pool-index)]
rlm@191 80 (.applyTorque control (.mult axis force))
rlm@191 81 (float (/ force strength))))))
rlm@191 82
rlm@158 83
rlm@180 84 (defn movement!
rlm@180 85 "Endow the creature with the power of movement. Returns a sequence
rlm@180 86 of functions, each of which accept an integer value and will
rlm@180 87 activate their corresponding muscle."
rlm@158 88 [#^Node creature]
rlm@180 89 (for [muscle (muscles creature)]
rlm@180 90 (movement-fn creature muscle)))
rlm@158 91
rlm@191 92 (defn movement-display-kernel
rlm@191 93 "Display muscle exertion data as a bar filling up with red."
rlm@191 94 [exertion]
rlm@191 95 (let [height 20
rlm@191 96 width 300
rlm@191 97 image (BufferedImage. width height
rlm@191 98 BufferedImage/TYPE_INT_RGB)
rlm@191 99 fill (min (int (* width exertion)) width)]
rlm@191 100 (dorun
rlm@191 101 (for [x (range fill)
rlm@191 102 y (range height)]
rlm@191 103 (.setRGB image x y 0xFF0000)))
rlm@191 104 image))
rlm@191 105
rlm@191 106 (defn view-movement
rlm@191 107 "Creates a function which accepts a list of muscle-exertion data and
rlm@191 108 displays each element of the list to the screen."
rlm@191 109 []
rlm@191 110 (view-sense movement-display-kernel))
rlm@191 111
rlm@158 112 #+end_src
rlm@158 113
rlm@158 114
rlm@158 115
rlm@158 116
rlm@158 117
rlm@158 118 * COMMENT code generation
rlm@158 119 #+begin_src clojure :tangle ../src/cortex/movement.clj
rlm@158 120 <<movement>>
rlm@158 121 #+end_src