Skip to content

Instantly share code, notes, and snippets.

@viblo
Created September 5, 2018 09:53
Show Gist options
  • Save viblo/3d27e47d7f28c0cf8f98befe403c8b23 to your computer and use it in GitHub Desktop.
Save viblo/3d27e47d7f28c0cf8f98befe403c8b23 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Oropod model using pymunk for the physics\n",
"\n",
"* Currently runs for 50sec, with a 10sec cycle of actions repeated 5 times.\n",
"* Still have not yet found a good way to get the force applied during the collisions. I can apparently get the total kinetic energy expended in the collision, which, by magnitude, looks like it could be acceptable. However, when the collision isn't happening (like during \"hiccups\"), there is no value, which means it will require not only some filtering (probably a moving average), but also some callbacks to handle both cases: a hiccup step(s), and really leaving a collision. **this has been slightly improved**\n",
"* The pytorch network is not incorporated into the slr class at the moment, but will be."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# various imports\n",
"import math\n",
"import h5py\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import torch"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading chipmunk for Darwin (64bit) [/anaconda3/lib/python3.6/site-packages/pymunk/libchipmunk.dylib]\n",
"pygame 1.9.4\n",
"Hello from the pygame community. https://www.pygame.org/contribute.html\n"
]
}
],
"source": [
"# pymunk (physics)\n",
"import pymunk\n",
"from pymunk import Vec2d\n",
"import pymunk.pygame_util"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# pygame (visualization)\n",
"import pygame\n",
"from pygame.locals import *\n",
"from pygame.color import *\n",
"\n",
"# screen constants\n",
"screen_width = 600\n",
"screen_height = 600\n",
"screen_size = np.array([screen_width, screen_height])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# coordinate conversion from simulation to/from pymunk\n",
"x_center = screen_width/2.0\n",
"y_center = 200\n",
"unit_ratio = 25\n",
"\n",
"def get_pymunk_coord(sim_coord):\n",
" #expects 1d array\n",
" sim_coord[0] = sim_coord[0]*unit_ratio + x_center\n",
" sim_coord[1] = sim_coord[1]*unit_ratio + y_center\n",
" return sim_coord\n",
"\n",
"def get_sim_coord(pymunk_coord):\n",
" #expects 1d array\n",
" pymunk_coord[0] = (pymunk_coord[0] - x_center)/unit_ratio\n",
" pymunk_coord[1] = (pymunk_coord[1] - y_center)/unit_ratio\n",
" return pymunk_coord"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# pymunk init\n",
"space = pymunk.Space()\n",
"space.gravity = (0.0, -900.0)\n",
"\n",
"#add note for how to increase iterations\n",
"\n",
"# elasticity of everything\n",
"global_elasticity = 0"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class oropod_arm():\n",
" \"\"\"Object that handles the oropod_arm, including the physical representation.\n",
" shape is assumed to be square (to allow friction with body)\n",
" \"\"\"\n",
" \n",
" #orientation (default as left, with extension being outward from center)\n",
" is_left = True\n",
" side_sign = -1 #necessary for getting signs correct depending on orientation\n",
" name = \"left\"\n",
" \n",
" #physics\n",
" phys_body = pymunk.Body()\n",
" phys_shape = None\n",
" \n",
" #these properties give about 1.9sec for end to end movement\n",
" mass = 0.02 #for some reason, very small masses do not work\n",
" elasticity = 0\n",
" friction = 1\n",
" muscle_damping = 1.7\n",
" muscle_force = 5\n",
" v_max = 213 #need to calculate this if physical properties are changed\n",
" \n",
" #dimensions\n",
" sq_side = 1 #square side\n",
"\n",
" #center is relative to body\n",
" body_phys_body = pymunk.Body() #used for calculating x_center\n",
" center_from_body = 0\n",
" \n",
" #muscles\n",
" phys_ext = pymunk.Constraint()\n",
" phys_flex = pymunk.Constraint()\n",
" muscle_anchor_dist_from_center = 6 #distance for each muscle from the center\n",
" \n",
" #limits\n",
" anatomical_limit = 4 #+/- limit\n",
" \n",
" #touching state\n",
" touching_wall = False\n",
" touching_other_arm = False\n",
" cutaneous_f = 0\n",
" prev_cutaneous_f = 0\n",
" last_touch_global_step = 0\n",
" \n",
" #history\n",
" x_history = None\n",
" x_and_v_norm_history = None\n",
" proprioceptor_history = None\n",
" contact_history = None #testing arbiter\n",
" \n",
" def __init__(self, pos_0, is_left, body_phys_body):\n",
" assert(pos_0.shape == (2,))\n",
"\n",
" #store orientation\n",
" self.is_left = is_left\n",
" if not is_left:\n",
" self.side_sign = 1\n",
" self.name = \"right\"\n",
" \n",
" #store body pointer\n",
" self.body_phys_body = body_phys_body\n",
" \n",
" #calculate distance from center\n",
" self.center_from_body = get_sim_coord(self.body_phys_body.position)[0] - pos_0[0]\n",
" \n",
" #arm size and moment\n",
" arm_size = np.array([self.sq_side, self.sq_side])*unit_ratio\n",
" arm_moment = pymunk.moment_for_box(self.mass, arm_size)\n",
" \n",
" #phys_body (starts at (x_init, y_0))\n",
" self.phys_body = pymunk.Body(self.mass, arm_moment)\n",
" self.phys_body.position = get_pymunk_coord(np.copy(pos_0))\n",
" self.phys_body.start_position = Vec2d(self.phys_body.position)\n",
" \n",
" #phys_shape\n",
" self.phys_shape = pymunk.Poly.create_box(self.phys_body, arm_size)\n",
" self.phys_shape.elasticity = self.elasticity\n",
" self.phys_shape.friction = self.friction\n",
" \n",
" #add to pymunk space\n",
" space.add(self.phys_body, self.phys_shape)\n",
" \n",
" #prevent rotation of arm (no rotation wrt space allowed)\n",
" rotation_limit_phys = pymunk.RotaryLimitJoint(space.static_body, self.phys_body, 0, 0)\n",
" space.add(rotation_limit_phys)\n",
" \n",
" #add muscles\n",
" #muscles are initally \"off\", but always provide damping\n",
" anchor_offset = 0.01 #small offset to prevent issues at end points\n",
" body_y = get_sim_coord(self.body_phys_body.position)[1] #get the y position\n",
" \n",
" #anchors are defined relative to body\n",
" anchor_y = self.y - body_y\n",
" ext_anchor = np.array([(self.x + self.side_sign*self.muscle_anchor_dist_from_center)*unit_ratio + self.side_sign*anchor_offset, anchor_y*unit_ratio])\n",
" flex_anchor = np.array([(self.x - self.side_sign*self.muscle_anchor_dist_from_center)*unit_ratio - self.side_sign*anchor_offset, anchor_y*unit_ratio])\n",
" \n",
" self.ext_phys = pymunk.DampedSpring(self.body_phys_body, self.phys_body, ext_anchor, (0,0), 0, 0, self.muscle_damping)\n",
" space.add(self.ext_phys)\n",
" \n",
" self.flex_phys = pymunk.DampedSpring(self.body_phys_body, self.phys_body, flex_anchor, (0,0), 0, 0, self.muscle_damping)\n",
" space.add(self.flex_phys)\n",
" \n",
" #add anatomical limits from x_center\n",
" anatomical_anchor = np.array([self.phys_body.position[0]-self.body_phys_body.position[0], (self.phys_body.position[1]-self.body_phys_body.position[1])])\n",
" anatomical_limit_phys = pymunk.SlideJoint(self.body_phys_body, self.phys_body, anatomical_anchor, (0,0), 0, self.anatomical_limit*unit_ratio)\n",
" space.add(anatomical_limit_phys)\n",
" \n",
" def set_collision_type(self, collision_type):\n",
" self.phys_shape.collision_type = collision_type\n",
" \n",
" def begin_touching_wall(self, arbiter, space, data):\n",
" print(self.name + \" arm began touching wall\")\n",
" self.touching_wall = True\n",
" \n",
" return True #allow collision\n",
" \n",
" def end_touching_wall(self, arbiter, space, data):\n",
" global global_step\n",
" print(self.name + \" arm stopped touching wall\")\n",
" self.touching_wall = False\n",
" self.prev_cutaneous_f = self.cutaneous_f\n",
" self.cutaneous_f = 0 #zero out cutaneous_f upon a collision stopping\n",
" self.last_touch_global_step = global_step\n",
" \n",
" def begin_touching_other_arm(self):\n",
" print(self.name + \" arm began touching other arm\")\n",
" self.touching_other_arm = True\n",
" \n",
" return True #allow collision\n",
" \n",
" def end_touching_other_arm(self):\n",
" global global_step\n",
" print(self.name + \" arm stopped touching other arm\")\n",
" self.touching_other_arm = False\n",
" self.prev_cutaneous_f = self.cutaneous_f\n",
" self.cutaneous_f = 0 #zero out cutaneous_f upon a collision stopping\n",
" self.last_touch_global_step = global_step\n",
" \n",
" def touching_post_solve(self, arbiter, space, data):\n",
" global global_step\n",
"\n",
" #still need to verify that this is the best (or only) way to get an analog of the collision force \n",
" #using the kinetic energy property of the collision looks okay,\n",
" #except that the force, when the arm reaches its anatomical limit should probably drop off to zero,\n",
" #as the internal arm \"structure\" should now be taking all of the force, and none should be\n",
" #applied outside\n",
" \n",
" #hack to fix the force, if the contact only left briefly\n",
" if self.last_touch_global_step > 0 and (global_step - self.last_touch_global_step) <= 5 and self.prev_cutaneous_f > 0:\n",
" self.cutaneous_f = self.prev_cutaneous_f\n",
" else:\n",
" \n",
" #log transform the kinetic energy, and smooth the values\n",
" alpha = 0.30\n",
" self.cutaneous_f = (1-alpha)*self.cutaneous_f + alpha*np.log10(1 + arbiter.total_ke)\n",
" \n",
" #self.contact_history[global_step, 0] = self.phys_body.force[0] + self.phys_body.force[1]\n",
" #self.contact_history[global_step, 1] = arbiter.total_ke\n",
" \n",
" def each_arbiter_callback(self, arbiter, *args, **kwargs): \n",
" global global_step\n",
" total_impulse = arbiter.total_impulse\n",
" total_impulse = math.sqrt(total_impulse[0]**2 + total_impulse[1]**2)\n",
" \n",
" total_ke = arbiter.total_ke\n",
" \n",
" body_force = self.phys_body.force\n",
" body_force = math.sqrt(body_force[0]**2 + body_force[1]**2)\n",
"\n",
" self.contact_history[global_step, :] = np.array([total_impulse, total_ke, body_force])\n",
" \n",
" #unused\n",
" #def update_force(self):\n",
" # global global_step\n",
" #self.contact_history[global_step, 0] = self.phys_body.force[0] + self.phys_body.force[1]\n",
" \n",
" @property\n",
" def x_center(self):\n",
" #get the arm center (world coord), which is defined relative to body\n",
" return get_sim_coord(self.body_phys_body.position)[0] - self.center_from_body\n",
" \n",
" @property\n",
" def x(self):\n",
" #get the arm end (world coord)\n",
" return get_sim_coord(self.phys_body.position)[0]\n",
" \n",
" @x.setter\n",
" def x(self, value):\n",
" #set the arm end (world coord)\n",
" #check against body location before setting\n",
" assert(value >= self.x_center - self.anatomical_limit)\n",
" assert(value <= self.x_center + self.anatomical_limit)\n",
" new_x = get_pymunk_coord(np.array([value, 0]))[0]\n",
" self.phys_body.position = np.array([new_x, self.phys_body.position[1]])\n",
" \n",
" @property\n",
" def x_norm(self):\n",
" #get the normalized x (arm coord)\n",
" #1 is full extension\n",
" #-1 is full flexion\n",
" return self.side_sign*(self.x - self.x_center)/self.anatomical_limit\n",
" \n",
" @property\n",
" def y(self):\n",
" #get the arm end (world coord)\n",
" return get_sim_coord(self.phys_body.position)[1]\n",
" \n",
" @property\n",
" def activations(self):\n",
" #get the activations\n",
" ext_a = self.ext_phys.stiffness / self.muscle_force\n",
" flex_a = self.flex_phys.stiffness / self.muscle_force\n",
" return np.array([ext_a, flex_a])\n",
" \n",
" @activations.setter\n",
" def activations(self, value):\n",
" #set the activations\n",
" #making sure they fall between 0 and 1\n",
" assert(value.shape == (2,))\n",
" ext_a = value[0]\n",
" flex_a = value[1]\n",
" assert(ext_a >= 0 and ext_a <= 1)\n",
" assert(flex_a >= 0 and ext_a <= 1)\n",
" \n",
" #turn on the muscles (setting the stiffness)\n",
" self.ext_phys.stiffness = ext_a * self.muscle_force\n",
" self.flex_phys.stiffness = flex_a * self.muscle_force\n",
" \n",
" @property\n",
" def v(self):\n",
" #get the velocity (world units)\n",
" return self.phys_body.velocity[0]\n",
" \n",
" @property\n",
" def v_norm(self):\n",
" #get the velocity (arm coord)\n",
" #+1 is max velocity in extension direction (out, extension muscle is shortening)\n",
" #-1 is max velocity in flexion direction (in, flexion muscle is shortening)\n",
" return self.side_sign * self.phys_body.velocity[0] / self.v_max\n",
" \n",
" @property\n",
" def x_and_v_norm(self):\n",
" #get both x and v norm\n",
" return np.array([self.x_norm, self.v_norm])\n",
" \n",
" @property\n",
" def lengths(self):\n",
" #get the muscle lengths (ext, flex)\n",
" len_max = 1\n",
" len_min = 0.2\n",
" \n",
" ext_len = ((1 - self.x_norm)/2)*(len_max - len_min) + len_min\n",
" flex_len = ((self.x_norm + 1)/2)*(len_max - len_min) + len_min\n",
" \n",
" return np.array([ext_len, flex_len])\n",
" \n",
" @property\n",
" def proprioceptors(self):\n",
" #get current proprioceptor states, including cutaneous receptor\n",
" #(ext_ia, flex_ia, ext_ii, flex_ii, ext_f, flex_f, cutaneous_f)\n",
" global global_step\n",
" len_max = 1\n",
" len_min = 0.2\n",
" ext_len, flex_len = self.lengths\n",
" ext_a, flex_a = self.activations\n",
" \n",
" #ia spindles\n",
" raw_ext_ia = ((1.5 + np.log10(ext_a + 0.1))*(self.v_norm) + ext_a)/2\n",
" raw_flex_ia = ((1.5 + np.log10(flex_a + 0.1))*(-self.v_norm) + flex_a)/2\n",
" \n",
" ext_ia = max(min(raw_ext_ia, 1), 0)\n",
" flex_ia = max(min(raw_flex_ia, 1), 0)\n",
" \n",
" #ii spindles\n",
" ii_scale = 1.0/(len_max - len_min)\n",
" ext_ii = ((ext_len - len_min)*ii_scale + ext_a)/2\n",
" flex_ii = ((flex_len - len_min)*ii_scale + flex_a)/2\n",
" \n",
" #muscle forces\n",
" ext_f = ext_len * ext_a\n",
" flex_f = flex_len * flex_a\n",
" \n",
" #cutaneous\n",
" if (global_step - self.last_touch_global_step) <= 1:\n",
" cutaneous_f = self.prev_cutaneous_f\n",
" else:\n",
" cutaneous_f = self.cutaneous_f\n",
" \n",
" return np.array([ext_ia, flex_ia, ext_ii, flex_ii, ext_f, flex_f, cutaneous_f])\n",
" \n",
" @property\n",
" def energy_consumption(self):\n",
" ext_len, flex_len = self.lengths\n",
" ext_a, flex_a = self.activations\n",
" v_norm = self.v_norm\n",
" \n",
" ext_f = ext_len * ext_a\n",
" flex_f = flex_len * flex_a\n",
" \n",
" #constants\n",
" muscle_force_base = 1.0\n",
" basal_rate = 0.1\n",
" \n",
" ext_v_shortening = max(v_norm, 0)\n",
" flex_v_shortening = max(-v_norm, 0)\n",
" \n",
" #energy consumed\n",
" ext_energy = ext_f*(ext_v_shortening + muscle_force_base) + basal_rate\n",
" flex_energy = flex_f*(flex_v_shortening + muscle_force_base) + basal_rate\n",
" \n",
" return ext_energy + flex_energy\n",
" \n",
" def init_history(self, sim_steps):\n",
" #initalize the history\n",
" self.x_history = np.zeros((sim_steps, 1))\n",
" self.x_and_v_norm_history = np.zeros((sim_steps, 2))\n",
" self.proprioceptor_history = np.zeros((sim_steps, 7))\n",
" self.contact_history = np.zeros((sim_steps, 3))\n",
" \n",
" def store_to_history(self):\n",
" #store the current state to the history\n",
" global global_step\n",
" self.x_history[global_step] = self.x\n",
" self.x_and_v_norm_history[global_step, :] = self.x_and_v_norm\n",
" self.proprioceptor_history[global_step, :] = self.proprioceptors\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"class oropod_body():\n",
" \"\"\"Class that handles the oropod_body, including physical representation\n",
" shape is assumed to be rectangular\n",
" \"\"\"\n",
" \n",
" #arms\n",
" left_arm = None\n",
" right_arm = None\n",
" \n",
" #physics\n",
" phys_body = pymunk.Body()\n",
" phys_shape = None\n",
" mass = 0.2 #for some reason, very small masses do not work\n",
" elasticity = 0\n",
" friction = 1\n",
" \n",
" #dimensions\n",
" width = 16\n",
" height = 1\n",
" \n",
" #history\n",
" x_history = None\n",
" \n",
" def __init__(self, pos_0):\n",
" assert(pos_0.shape == (2,))\n",
" \n",
" #square size and moment\n",
" body_size = np.array([self.width, self.height])*unit_ratio\n",
" body_moment = pymunk.moment_for_box(self.mass, body_size)\n",
" \n",
" #phys_body\n",
" self.phys_body = pymunk.Body(self.mass, body_moment)\n",
" self.phys_body.position = get_pymunk_coord(np.copy(pos_0))\n",
" self.phys_body.start_position = Vec2d(self.phys_body.position)\n",
" \n",
" #phys_shape\n",
" self.phys_shape = pymunk.Poly.create_box(self.phys_body, body_size)\n",
" self.phys_shape.elasticity = self.elasticity\n",
" self.phys_shape.friction = self.friction\n",
"\n",
" #add to pymunk space\n",
" space.add(self.phys_body, self.phys_shape)\n",
" \n",
" #prevent rotation of body (no rotation wrt space allowed)\n",
" rotation_limit_phys = pymunk.RotaryLimitJoint(space.static_body, self.phys_body, 0, 0)\n",
" space.add(rotation_limit_phys)\n",
" \n",
" #create arms\n",
" self.left_arm = oropod_arm(np.array([-3, 0]), True, self.phys_body)\n",
" self.right_arm = oropod_arm(np.array([3, 0]), False, self.phys_body)\n",
" \n",
" def setup_collisions(self, left_wall, right_wall):\n",
" COLLTYPE_ARM_L = 1\n",
" COLLTYPE_ARM_R = 2\n",
" COLLTYPE_WALL_L = 3\n",
" COLLTYPE_WALL_R = 4\n",
" \n",
" #add the collision types\n",
" self.left_arm.set_collision_type(COLLTYPE_ARM_L)\n",
" self.right_arm.set_collision_type(COLLTYPE_ARM_R)\n",
" \n",
" #setup callbacks\n",
" #arms touching has to have a special callback (to call two functions for one collision pair)\n",
" #h1 = space.add_collision_handler(COLLTYPE_ARM_L, COLLTYPE_ARM_R)\n",
" #h1.begin = self.arms_began_touching_callback\n",
" #h1.separate = self.arms_end_touching_callback\n",
" #h1.post_solve = self.arms_touching_post_solve\n",
" print('arm collision is temporarily disabled')\n",
" \n",
" left_wall.collision_type = COLLTYPE_WALL_L\n",
" h2 = space.add_collision_handler(COLLTYPE_ARM_L, COLLTYPE_WALL_L)\n",
" h2.begin = self.left_arm.begin_touching_wall\n",
" h2.separate = self.left_arm.end_touching_wall\n",
" h2.post_solve = self.left_arm.touching_post_solve\n",
" \n",
" right_wall.collision_type = COLLTYPE_WALL_R\n",
" h3 = space.add_collision_handler(COLLTYPE_ARM_R, COLLTYPE_WALL_R)\n",
" h3.begin = self.right_arm.begin_touching_wall\n",
" h3.separate = self.right_arm.end_touching_wall\n",
" h3.post_solve = self.right_arm.touching_post_solve\n",
" \n",
" def arms_began_touching_callback(self, arbiter, space, data):\n",
" #call these separately\n",
" self.left_arm.begin_touching_other_arm()\n",
" self.right_arm.begin_touching_other_arm()\n",
" return True #allow collision\n",
" \n",
" def arms_end_touching_callback(self, arbiter, space, data):\n",
" #call these separately\n",
" self.left_arm.end_touching_other_arm()\n",
" self.right_arm.end_touching_other_arm()\n",
" \n",
" def arms_touching_post_solve(self, arbiter, space, data):\n",
" #call these separately\n",
" self.left_arm.touching_post_solve(arbiter, space, data)\n",
" self.right_arm.touching_post_solve(arbiter, space, data)\n",
" \n",
" @property\n",
" def x(self):\n",
" return get_sim_coord(self.phys_body.position)[0]\n",
" \n",
" @x.setter\n",
" def x(self, value):\n",
" new_x = get_pymunk_coord(np.array([value, 0]))[0]\n",
" self.phys_body.position = np.array([new_x, self.phys_body.position[1]])\n",
" \n",
" @property\n",
" def y(self):\n",
" return get_sim_coord(self.phys_body.position)[1]\n",
" \n",
" def init_history(self, sim_steps):\n",
" self.x_history = np.zeros((sim_steps, 1))\n",
" self.left_arm.init_history(sim_steps)\n",
" self.right_arm.init_history(sim_steps)\n",
" \n",
" def store_to_history(self):\n",
" global global_step\n",
" self.x_history[global_step] = self.x\n",
" self.left_arm.store_to_history()\n",
" self.right_arm.store_to_history()\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"class oropod_cgp():\n",
" #default is off\n",
" activation_list = np.array([[0, 0, 0, 0, 0]])\n",
" has_converted = False\n",
"\n",
" def __init__(self):\n",
" self.index = 0\n",
" self.has_converted = False\n",
" \n",
" def convert_times_to_steps(self, dt):\n",
" if self.has_converted:\n",
" print(\"already converted\")\n",
" return\n",
" assert(self.activation_list[0,0] == 0) #the first time must be 0\n",
" self.activation_list[:,0] = np.round(self.activation_list[:,0]/dt)\n",
" self.has_converted = True\n",
" \n",
" def get_current_activations(self, step):\n",
" assert(self.has_converted)\n",
" \n",
" temp = (step - self.activation_list[:,0])\n",
" temp[temp<0] = np.inf\n",
" idx = temp.argmin()\n",
" current_activation = self.activation_list[idx, 1:5] \n",
" return current_activation\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"class oropod_slr():\n",
" cgp = oropod_cgp()\n",
" left_arm = None #pointer\n",
" right_arm = None #pointer\n",
" \n",
" \n",
" def __init__(self, body):\n",
" #copy the pointers to the arms locally\n",
" self.left_arm = body.left_arm\n",
" self.right_arm = body.right_arm\n",
" \n",
" def update(self, step):\n",
" \n",
" #get proprioceptors\n",
" left_proprioceptors = torch.from_numpy(self.left_arm.proprioceptors)\n",
" right_proprioceptors = torch.from_numpy(self.right_arm.proprioceptors)\n",
" \n",
" #get the cgp activations\n",
" cgp_activations = self.cgp.get_current_activations(step % 1000) #using mod to repeat cycle\n",
" \n",
" #neural network goes here\n",
" network_outputs = cgp_activations #dummy copy\n",
" \n",
" #set the arm activations\n",
" self.left_arm.activations = network_outputs[0:2]\n",
" self.right_arm.activations = network_outputs[2:4]\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"#floor (has friction)\n",
"floor_width = 20\n",
"floor_height = 1\n",
"floor_friction = 1\n",
"floor_y = -2 \n",
"\n",
"floor_left = get_pymunk_coord(np.array([-floor_width/2.0, floor_y]))\n",
"floor_right = get_pymunk_coord(np.array([floor_width/2.0, floor_y]))\n",
"floor_thickness = floor_height/2.0*unit_ratio\n",
"\n",
"floor = pymunk.Segment(space.static_body, floor_left, floor_right, floor_thickness)\n",
"floor.friction = floor_friction\n",
"space.add(floor) \n",
"\n",
"#markers\n",
"for x in range(-10,11):\n",
" point_1 = np.array([x, floor_y - floor_height/2])\n",
" point_2 = np.array([x, floor_y - floor_height*1.5])\n",
" marker = pymunk.Segment(space.static_body, get_pymunk_coord(point_1), get_pymunk_coord(point_2), 1.0)\n",
" space.add(marker)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"#instead of \"disabling\" walls, just set wall_dist_from_center to a larger number (like 10)\n",
"\n",
"#walls\n",
"wall_dist_from_center = 6 #normal is 6\n",
"wall_width = 1.0\n",
"wall_bottom = -0.4 #just above the body\n",
"wall_top = 3 #some distance above the arms\n",
"wall_fudge = 0.54 #adjustment to get blocks to reach +/- distance exactly\n",
"\n",
"#left wall\n",
"left_wall_x = 0 - (wall_dist_from_center + wall_fudge)\n",
"left_wall_p1 = get_pymunk_coord(np.array([left_wall_x, wall_bottom]))\n",
"left_wall_p2 = get_pymunk_coord(np.array([left_wall_x, wall_top]))\n",
"left_wall = pymunk.Segment(space.static_body, left_wall_p1, left_wall_p2, wall_width)\n",
"left_wall.elasticity = global_elasticity\n",
"space.add(left_wall) \n",
"\n",
"#right wall\n",
"right_wall_x = 0 + (wall_dist_from_center + wall_fudge)\n",
"right_wall_p1 = get_pymunk_coord(np.array([right_wall_x, wall_bottom]))\n",
"right_wall_p2 = get_pymunk_coord(np.array([right_wall_x, wall_top]))\n",
"right_wall = pymunk.Segment(space.static_body, right_wall_p1, right_wall_p2, wall_width)\n",
"right_wall.elasticity = global_elasticity\n",
"space.add(right_wall) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arm collision is temporarily disabled\n"
]
}
],
"source": [
"#create the body, (includes the arms, in base positions)\n",
"body = oropod_body(np.array([0, -1]))\n",
"\n",
"#set up collisions with arms (other and walls)\n",
"body.setup_collisions(left_wall, right_wall)\n",
"\n",
"slr = oropod_slr(body)\n",
"\n",
"#copy in the activation list (first row must start at 0 sec)\n",
"#filepath = 'cgp_array.mat'\n",
"#variables = {}\n",
"#f = h5py.File(filepath) #open file\n",
"#for k, v in f.items():\n",
"# variables[k] = np.array(v)\n",
"#slr.cgp.activation_list = np.copy(np.transpose(variables['cgp_array'])) #copy the array\n",
"#f.close() #close file before continuing"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"#variables necessary for main loop\n",
"global_time = 0\n",
"global_step = 0\n",
"dt = 0.01\n",
"sim_time = 50.00\n",
"sim_steps = round(sim_time/dt)\n",
"\n",
"\n",
"### example to play with contact forces (otherwise, comment out)\n",
"sim_time = 15\n",
"sim_steps = round(sim_time/dt)\n",
"body.right_arm.x = 3\n",
"slr.cgp.activation_list = np.array([[0.0, 1, 0, 0, 0],\n",
" [2.5, 0, 1, 0, 0],\n",
" [6.0, 1, 0, 0, 0]])\n",
"\n",
"\n",
"\n",
"\n",
"#have the cpg convert times to steps\n",
"slr.cgp.convert_times_to_steps(dt)\n",
"\n",
"#update slr with initial state\n",
"slr.update(global_step)\n",
"\n",
"#preallocate history\n",
"body.init_history(sim_steps + 1)\n",
"body.store_to_history() #store initial conditions"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"# keep all code above here, and start pygame at this point\n",
"# this way it fails before creating the pygame window\n",
"\n",
"# pygame init\n",
"pygame.init()\n",
"screen = pygame.display.set_mode(screen_size)\n",
"pygame.font.init()\n",
"font = pygame.font.SysFont(\"Arial\", 16)\n",
"pygame.display.set_caption(\"oropod\")\n",
"\n",
"# turn on pymunk's link to pygame\n",
"draw_options = pymunk.pygame_util.DrawOptions(screen)\n",
"# hide the constraints\n",
"draw_options.flags = pymunk.SpaceDebugDrawOptions.DRAW_SHAPES | pymunk.SpaceDebugDrawOptions.DRAW_COLLISION_POINTS"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"left arm began touching wall\n",
"left arm stopped touching wall\n",
"left arm began touching wall\n",
"left arm stopped touching wall\n",
"left arm began touching wall\n",
"left arm stopped touching wall\n",
"left arm began touching wall\n",
"left arm stopped touching wall\n"
]
}
],
"source": [
"#main simulation loop\n",
"while True:\n",
" \n",
" ### update physics\n",
" for x in range(4):\n",
" global_step = global_step + 1\n",
" global_time = global_step*dt #update global_time before solving\n",
" \n",
" #update the slr (in and our)\n",
" slr.update(global_step)\n",
" \n",
" space.step(dt)\n",
" \n",
" body.left_arm.phys_body.each_arbiter(body.left_arm.each_arbiter_callback)\n",
" \n",
" #story each new step to history\n",
" body.store_to_history()\n",
" \n",
" if global_step >= sim_steps:\n",
" break\n",
" \n",
" ### clear screen\n",
" screen.fill(THECOLORS[\"white\"])\n",
" \n",
" ### draw bodies\n",
" space.debug_draw(draw_options)\n",
" \n",
" ### put time on screen\n",
" screen.blit(font.render(\"time: \" + \"{:.3f}\".format(global_time), 1, THECOLORS[\"black\"]), (5,0))\n",
" \n",
" ### put positions on screen\n",
" screen.blit(font.render(\"left: \" + \"{:.2f}\".format(body.left_arm.x), 1, THECOLORS[\"black\"]), (5,20))\n",
" screen.blit(font.render(\"body: \" + \"{:.2f}\".format(body.x), 1, THECOLORS[\"black\"]), (5,40))\n",
" screen.blit(font.render(\"right: \" + \"{:.2f}\".format(body.right_arm.x), 1, THECOLORS[\"black\"]), (5,60))\n",
" \n",
" ### flip screen\n",
" pygame.display.flip()\n",
" \n",
" #need to put event.get at the end to really update the flip the last time\n",
" for event in pygame.event.get():\n",
" #check for window exit button or escape key\n",
" if event.type == QUIT:\n",
" break\n",
" elif event.type == KEYDOWN and event.key == K_ESCAPE:\n",
" break\n",
" \n",
" #stop at end of desired steps\n",
" if global_step >= sim_steps:\n",
" break\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"#get time array\n",
"t = np.arange(0., sim_steps + 1,1)*dt"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax1 = plt.subplots()\n",
"\n",
"color = 'tab:red'\n",
"ax1.set_xlabel('time (s)')\n",
"ax1.set_ylabel('left x', color=color)\n",
"ax1.plot(t, body.left_arm.x_history, color=color)\n",
"ax1.tick_params(axis='y', labelcolor=color)\n",
"\n",
"ax2 = ax1.twinx()\n",
"\n",
"color = 'tab:blue'\n",
"ax2.set_ylabel('body x', color=color)\n",
"ax2.plot(t, body.x_history, color=color)\n",
"ax2.tick_params(axis='y', labelcolor=color)\n",
"\n",
"fig.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax1 = plt.subplots()\n",
"\n",
"color = 'tab:red'\n",
"ax1.set_xlabel('time (s)')\n",
"ax1.set_ylabel('right x', color=color)\n",
"ax1.plot(t, body.right_arm.x_history, color=color)\n",
"ax1.tick_params(axis='y', labelcolor=color)\n",
"\n",
"fig.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvIxREBQAAIABJREFUeJztnXmcW1X5/98nmX3pzHTfCYWW3G7QUltkFaFaDQIuIIsKCvKVr/v2M3xRVPyqcd9RKyIofkVAhULYSqUUhJaWQulyAy0l0H1fZutsOb8/cjNNp8lMZibJvcl93q9XXpN777n3fibJPc85z3nOc5TWGkEQBEFwGh67BQiCIAhCKsRACYIgCI5EDJQgCILgSMRACYIgCI5EDJQgCILgSMRACYIgCI6kxM6bm37jDuAiYLcRMaenOK6AXwDvBVqAa42Iudo6dg3wdavo/xoR8678qBYEQShefMFwd70cDQWOq5d9wfBx9XI0FFidCy1296DuBBb0cvw9wGTrdQPwWwDTbwwFvgnMA+YC3zT9RkNOlQqCILiDOxlAvZwLbDVQRsRcBuzvpcglwJ+NiKmNiLkcqDf9xhjg3cBiI2LuNyLmAWAxvX+ggiAIQgZEQ4GM6uVoKKCjocByoN4XDI/JhRZbXXwZMA7YkrS91dqXbv9xKKVuIG7lAU6vqqrKgUxnEyuvJVZem1nhrg5KmvfkVpADiLUeATSeykq7pQh5JFZaRayyPuPy3ua9qK72HCrKPy0tLRpIdskt1Fov7Mcl0tW/O7Ig7xicbqBUin26l/3H74x/8AsBqqurdXNzc/bUFQg/fCzC75dtZvEXz+213B3/eYO7l7/FS9+YT0N1WZ7U2YPpNwCY9PBDlJ98ss1qhHxxx7NvcOvDG3jw02dRW5G++ms80sklv/kPN7/X4JPnTsqjwtyjlGrVWs8ZzCVS7MtJzjynG6itwISk7fHAdmv/O3rsX5o3VQWIR8GkETW9lnnv9DHcvfwt1m47xLlTRuRJmb20rlkjBsqF+IZVU1dV2muZsXUVrN12KE+KCop09XLWsTtIoi8WAR8z/YYy/cYZwCEjYu4AHgfeZfqNBis44l3WPmEQTBtXB+CKh9JTEzfWrevW2axEcCozxtexzgXPwgBYBHzMFwwrXzB8BnAoGgpk3b0H9oeZ/414T2i46Te2Eo/MKwUwIubvgEeIhzJuIh7O+HHr2H7Tb3wHWGld6lYjYvY2qCdkQF1lKScMq3LFQ6nb2gA4sm69zUoEpzJjXB2Pr99F45EOait6720VE75guLte9gXDx9TL0VAgbb2cC2w1UEbEvLKP4xr4dJpjdwB35EJXsdEf5/D0cXWs2XIwZ1qcgO7qQnd0ANAWiaDb21FlxT3mJsTp77MAsG7bYd5+0rDcCHIg0VCg13o5GgqkrZezjdNdfEKWUCnHNY9nxrg6th5o5UBzcUUuJaPb4/9bxbRp6I4Ojry20WZFQt7J4HGY0W2git+j4FTEQAnHMMMF41C6qwuAylNPBeCIjEMJKRhWUy6BEjYjBko4hulji99AEYsBUDpxAt76eo6sFwMlpEYCJexFDJQL0P1wvNdVlTJxaJEHSlgGSnm8VEyfTutaMVBuQffnYSDuUdi8t5nDRzpypEjoDTFQwnHMGF9X1D2o7krK46Fi+jTaNm4kduSIvaIER5IIlFi/7bDNStyJGCi3kFmMBOCCQAmrB4VHUTl9OnR10RaJ2KtJyCsqw+dBAiXsRQyUcByJh/KVYn0ou118HipmzAAQN5+QkkSgRNE+Cw5HDJRwHDPH16EUvPTWAbul5AQds1x8ykPJyJF4RwyXSD4hLTPH1xf93ECnIgbKBeh+5nGsrShlyshaVr9VpA+lPuriU0pROW06rRLJJ6Rh9gn1vLW/hT2NbXZLcR1ioFxCP4aggPhD+dJbB4jFcpKk2F6SXHwAFTOm0/76Zrqa3Jfp3q3053k4/YT4Wqiri9Sj4GTEQAkpmTWxgcYjnWze22S3lKyT7OIDqJwxA7TmyLq1NqoSnMq0sXWUepUYKBsQAyWkZPZEq9X4ZhG6+WLxTBJ44u3oytNOA6VoWb26l5MEt1JR6mXa2DpeKsZnweGIgXIDA/DSTRpeTV1laXG2GhMuPq8XAO+QIZSffDKtq1+yU5WQB/o5T7eb2RMbWLP1IB1dsewKEnpFDJSQEo9HMWtifVEaqJ4uPoDK2bNpffnl7jx9gpDM7BPqaeuMsWG7TNjNJ2KgXEKmExOTmT2xgY27m4ovzYtOBEkc/VCqZs8i1tRE26ZNdqkS8ojq5wMhgRL2IAZKSMvsiQ1oDS8XW7h5dyaJY3tQAK0yDiWkYExdJWPqKop36oVDEQMlpOXUCfEJu8XWakzl4isdPx7viOG0yDiUkIbZExtY/WZxPQtORwyUCxjoTKbailL8o4ewKlpkD2XSRN0ESimqZs2WHlSR099J68nMPqGBbQdb2XGoNYuKhN4QAyX0yrwTh7Lqzf20dxZR9FKPiboJKmfPomPbNjp27bZDleBw5p04FIAX3thvsxL3IAbKJWS65HtPzpg0jCMdMdZuKx7feyoXH0BVYhzqJelFFTsDeRqMMUOorShh+eZ9WdcjpKbEzpubfmMB8AvAC9xuRMxQj+M/A863NquAkUbErLeOdQGJqf9vGRHz4vyodhdzrVbj8s37Of2EoTaryRI9JuomqDAMVGUlLateZMiCBTYIE5yM16OY6xvKis3Sg8oXthko0294gd8A84GtwErTbywyIuaGRBkjYn4xqfxngVlJl2g1IuZp+dLrVoZWl3HKqFqWb97Hp88/2W452aHHRN0EqrSUqtmzaVmxwg5VQgFwxqRhLInsZtfhI4waUmG3nKLHThffXGCTETE3GxGzHbgHuKSX8lcCf8uLsiKjv8tc9+SMSUN58c0DRTOLPp2LD6Bq3jzaNm6kc+/ePKsS8sEgHwXmTUp4FMTNlw/sNFDjgC1J21utfcdh+o0TgBOBfyftrjD9xirTbyw3/cal6W6ilLpBKbVKKbWqs7MzG7oLkoFM1E0wb9IwWtq7imcZ+BQTdRNUnzEPgJYXXsirJCG/DPR5mDpmCLXlJayQQIm8YKeBSvUTSde+uQK434iYyXloJhoRcw5wFfBz02+clOpErfVCrfUcrfWckhJbh9wKlqPjUEXSakxM1E1RS1VMnYqnuprmFWKghOMp8XqY42sonmfB4dhpoLYCE5K2xwPb05S9gh7uPSNibrf+bgaWcuz4lJBFhteUM3lkTfENDqcwUKqkhKq3vY2W5cttECQUAmdMGsbmPc3sPnzEbilFj50GaiUw2fQbJ5p+o4y4EVrUs5DpN04BGoDnk/Y1mH6j3Ho/HDgL2NDzXCHOYP3uEPe9r4ruL4pxqL7G5KrOmEf7m2/SsXNnnhQJ+SIby2+eMWkYAMvFzZdzbDNQRsTsBD4DPA6YwL1GxFxv+o1bTb+RHDJ+JXCPETGTf1sGsMr0G2uAp4BQcvSfkH3OPnkEze1dxZHqpfuXlHogonqeNQ4l0XxCCqaNHcKQihKe3bjHbilFj62DMkbEfAR4pMe+W3psfyvFec8BM3IqrsgYRIwEAGeePAyvR7Fs4x7mWS3IgifNSHn5KafgraujefkK6i7pLbBUKFQGOnEd4uNQZ508nGWv7UVr3e/M6ELmSCYJISOGVJQya0I9z2wsgvDrPlx8yuOhat48mp9/ftAh+kJxcu6UEew8fISNu5vsllLUiIESMuacySNYu+0Q+5vb7ZaSHXpp+FaffRadO3fStnFj/vQIBcM5k4cDsOw1cfPlEjFQLiBbfYBzpwxHa3h2U6H3ovr+RGrOPReA5meeybUYIY9kq0M8vqGKSSOqWVYMHgUHIwZKyJiZ4+upqywt/FajVUv1NnZQOno05ZMn07RMDJSQmnMnj2DF5n0c6ejqu7AwIMRAuYRsDOR6PYqzTx7OMxv3FMfYTB+fSfW559CyejVdTc15EiTki2zENZw3ZQRtnTFZfiOHiIES+sW5U4az63Abr+0q4MHhDI1rzTnnQkcHLcuf77uw4DrmTRpKmddT+B4FByMGSugX500ZCcCSyC6blWSBPprRVbNn4amuFjdfETGYFXV7UlVWwtwTh/LUq7LAZa4QA+UCsumNG11XwYxxdTy5oXANVKbuSVVWRvWZb6fpmWeKw6UpZJ0LjJG8vqeZN/aKGzgXSPZUl5DNqYQXGqP4+ZLX2NPYxoja8ixeOU8kbE0GAxHV55xD4+InaXttIxWnTMmtLqHgmD91FN9+aAOLN+zkhnNT5qsuOHzB8DELyUZDgVCP4xOBu4B6q0wwGgo8ctyFsoD0oIR+M3/qKLSGfxeDm68Pat7xDlCKxiVP2i1FcCDjG6owxgxhcQF7FJLxBcOJhWTfA0wFrvQFw1N7FPs6cG80FJhFPIfqbbnSIwZK6DfGmFrG1VcW7kPZ7a7ruwdVOnIklaeeSuOTYqCE1MyfOooX3zzAvqY2u6Vkg7nApmgosDkaCqRbSFYDQ6z3daRfhWLQiIHKgK6mJlrXrrVbxoDJ5sAwxEPW508dxTMb99LaXsBzQDL0e9bOn0/bBpP2rVtzq0fIObkYSnzX1FHENCyJFEWwRCYLyX4L+IgvGN5KPJfqZ3MlRgxUBmz73OeIXna5VFBJXGiMoq0zxjMFmdG5f7VU7fwLAaQXJaRk2tghjK2rKCSPQklilXHrdUPSsUwWkr0SuDMaCowH3gv8xRcM58SWiIHKgNZX4r2n5meftVnJIMhywuV5k4ZSW1HCE4XzUB5HppOXyyZOpPyUU8RAFRHZTECulOLCqaN4ZuOeQvEodCZWGbdeC5OOZbKQ7HXAvQDRUOB5oAIYnguhYqAyoGT0KAD23323hBtblHo9zJ86iifW76S9s8AWMRzAd1h74YW0vriazr2Se004nndPG82RjhhLC39O1Epgsi8YPtEXDKdbSPYt4AIAXzBsEDdQOXGliIHKgFhjPGtC+6bXaYtEbFbjHN43cyyHj3QWnpsvYaD60YyunX8haE3jv/+dI1FCIXPGpGEMrynnoVdyFi+QF6KhwHELyUZDgfW+YPhWXzCcWEj2y8AnfcHwGuBvwLXRUCAnLXeZB5UBur2d2vcsoHHxkxx66GEqDMNuSf0iV52+s04eTn1VKQ+t2c4Fxqjc3CSX9MNAlZ9yCqUnTOTwo4/ScPnlORQlFCJejyIwYzT3rNxCU1snNeWFW7Vac5oe6bHvlqT3G4Cz8qFFelAZoGMxSoYNp+acczgcDqO7CsLPfAy5WPOzrMTDgmmjWbxhV0FldB6Im1YpRV3gIlqWr6BjV8G7cVzPYFbUTcf7Th1LW2esoLOsOA0xUJnQ2Ynyeql730V07tpFy8pVdityDBfNHEtzexdPFWKIbT9HyodcdBFozeFHcjJpXihwZk9sYGxdBQ+tKWw3n5MQA5UBuqsLvF5qzj8fT1UVhx5+yG5JjuGMSUMZXlPGw6/ssFtK5gzQ51k+6UQqpk3j8MMPZ1mQUAx4PIrAzDEs27iHQy0ddsspCmw1UKbfWGD6jVdNv7HJ9BvBFMevNf3GHtNvvGy9rk86do3pNzZar2tyqVN3daG8XjyVldTOn0/j408QayuKWeODpsTr4b0zxrAksovDRwrkoey2T/138wx530UcWb+ets1vZFWSkB9yHYX7vlPH0tGleXRdATXYHIxtBsr0G8flfDL9Rs+cTwB/NyLmadbrduvcocA3gXnEU3N80/QbDTkT29UFJV4AhrzvfcQaG2l6+umc3a7Q+MDs8RzpiBEupF7UABnynveCUtKLElIyY1wdk0ZU84/VMqk/G9jZg5oLbDIi5mYjYqbL+ZSOdwOLjYi534iYB4DFwIJciNSxGMRiKG88Kqf6jHl4hw/n8EOFVUFlY0XddJw6vo7JI2u4b9WWvgs7gv6HmScoHTWSqjPmceihh+K/DaEgydXjoJTi8jkTWBk9wOY9Bbyop0Ow00BlkvMJ4IOm33jF9Bv3m34jMcM503NRSt2QSOnR2dnZf5VWxJ7yxj8qVVLCkPe+h6alS+k6fLj/1ytClFJcNmc8q986yKbdjXbLyZwBVlL1738/HVu20PLCC9nVIxQFH5g1Dq9Hcd+L0osaLHYaqExyPj0E+IyIORN4kvgaJJmeG9+p9cJESo+Skv7PTegOKfcePbfufRejOzo4HA73+3rFyvtnjS+ch3KQ4xC173oXniFDOHjvfVkSJBQTI4dUcP4pI/jHi1vp7JJe9mCw00D1mfPJiJj7jIiZiEb4A3B6pudmje4elLd7V8X0aZRPNTjw93sLIvVRPjSOqC3n/FNG8s/V25z/UFqfx0Ddnp6KCuouvpjGxYvpPHAgm8qEHJOvx/WyORPY3djGskLLsuIw7DRQK4HJpt840fQbKXM+mX5jTNLmxcRTb0A8Dce7TL/RYAVHvMval3USPShVctRAKaVouPzDtEUiHFmzJhe3LUgunzOePY1tPPVq8T+U9Zddhu7o4NCDD9otRXAg7/SPZHhNGX9fWSjjss7ENgNlRMzjcj4ZEXO96TduNf1GIufT50y/sd70G2uAzwHXWufuB75D3MitBG619mWdVC4+iE/a9FRVceCev+fitlknhzES3ZzvH8noIRX8+flo7m82CPQAcvH1pOKUKVScOpOD991fEL1o4Vhy/TiUej188PTxPGnuZvvB1hzfrXixNWGUETGPy/lkRMxbkt7fBNyU5tw7gDtyKhDACqxIBEkk8NZUM+Ti93HoXw8w6qYg3rq6nEtxOqVeD1fPm8hPFr/G63uaOGlEjd2SemeQVrvhssvY8fVv0LpqFVVve1uWRAnFwkfmncAflm3mryve5Kvv9tstpyCRTBJ9oGOJ1vbxH1XDFVeg29o49MADeVblXK6YO5Eyr4e/PP+m3VLSk6Uez5BAAE9dHfv//JesXE/IPfns604YWsUFxij+9sKWgspV6STEQPVJendQhd9P5axZ7L/7r45OIJvPh3JEbTmBmWO4/8WtNLUNIKw/nwyyB+WprKTh8stpXLJEVlsWUnLtmT72N7cXViowByEGqi+6xytSHx567bV0bNlC45NL8qdpAORhCKqbj739BJraOvmnU2fTZ9FiN1x9FXg8HLj7r9m7qJBzcjlxPZkzTxrGySNruOu5qIxVDgAxUH3Rx4B67YUXUDphAvv/9Kc8inI2p02o59QJ9fzx2TecGXLeXVEMvpIqHT2aIe9+Nwfvv5+upuZBX08oLpRSXHOmj7XbDrEyKlMS+osYqL7oY86M8noZes01tL78Mi2rX8qnMseilOLG8ybx5r4WHl230245OWfoNR8j1tTEoX/+w24pggP50OzxDKsu47alm+yWUnCIgeqLDEKS6z/w/vhg+Z9yH1Q4EOzwLLxr6mgmjajmtqWvO9C10bvbtr9UzpxJ5ZzT2XfHn4i1t2fnokJOsOOnWFnm5eNn+Vj66h7WbTuUfwEFjBioPtAZLM3gqaqi4aoraXxyCW0bN+ZFl9PxeBSfOu8kzB2HWfqaMyfuZnMcYviNN9K5cyeH/iURncLxfPTtPmrKS/jt06/bLaWgEAPVJ5lN6hz6sY/hqaxkz2235UFT/8nXoHAyl542jjF1Ffz2KYc9lDloRlefeSYVp85k38KF6I4CWRfLxeT7aairLOUjZ5zAo2t38MZeGavMFDFQfZFh1oGShgYaPvpRGh97nCOvvZYHYc6nrMTDDedO4oXofv6zaa/dco6ShUwSPVFKMfzGG+nYto1Di2TFZeF4rjv7REq9Hn61RLwsmSIGqi/6CDNPZtjHr8VTVcXe236bW00FxJVzJzK2roIfPv6qA8eiskvNeedRMXUqe3//e+lFCccxoraca8708a+Xt/HargJalsZGxED1RT8yX3vr62n42EdpfOwxjrz6aq6VZYzO61TdY6ko9fL5CyezZstBFm/YZZuOZLKRiy8VSimGf+6zdLz1Fgfuk6U4nIidzwLAjeedRHVZCT9+3Dn1g5MRA9UX/azMhl17LZ66Onb/8Ec5FNV/8j8CdZQPzh7PicOr+ckTr9EVc1AvKgfjcjXnnUfV297G3t/cJvOiHIwNQ7IANFSX8clzJvHEhl289JbMi+oLMVB90N/WtreujuE3form//yHpmeeyaGywqHE6+FL86fw6q5GZ2SXyKGNVEox8qtfoWvfPvbf4cxpB4K9XHfOiQyrLuMHj0WK3u09WMRA9UUGYeY9GXrVVZSeMJFdP/gBeiDLzBchgRljOG1CPT98/FUaj9g8PpPFTBKpqJw5k9oFC9h355107N6dk3sIhUtNeQmfv3Ayyzfv5zEXTGQfDGKg+qT/4xWqrIyRX/4y7Zte5+D99+dIV2Hh8Si+dfE09jS28et/F/+M+pFf/AJ0dLD7Rz+2W4qQhFM6LFfNnYh/dC3/GzZpbXduomm7EQPVF/2I4kumdv58qubMYc/Pfm77suBOeShPm1DPZaeP547/vMHmPU02KsluJolUlJ1wAkOvv47DDz1E84oXcncjoSAp8Xr41sXT2Hawld/J5N20iIHqi35E8SWjlGLULd+gq7mZ3T/5SS6U9VOP3QrifHXBKZSXePn2QxvslpJzht9wA6XjxrHzO7dK2LnDsGPiek/OmDSMi2aO4XdPv86W/S12y3EkYqD6YhAhyRVTplD/wQ9y6F8PoGMOzOptAyNrK7jmzBN4+rU9HGq1qdIeYKOjv3gqKxl18820b3qdfXfemdN7CYXJzQGDts4Yf3vhLbulOBIxUH0w2DkzpaNHQVeXc/xsDmBETTmA/SHneWhF177zfGrnX8jeX/2atk3FP/Ym9I8xdZXUlJfQ1ikN2FSIgeqLAUTxHUOiErSxB+U005joudgWYpvn+47+5jfxVFWxPXiTRHXajNOeBYjXLDFpwKakxM6bm35jAfALwAvcbkTMUI/jXwKuBzqBPcAnjIj5pnWsC1hrFX3LiJgX50blYLMOWOfJD7AbT+Ijsen+ucokkY6S4cMZ/a1vse0LX2DfH/7A8BtvzMt9hQJBSfWQDtt6UKbf8AK/Ad4DTAWuNP3G1B7FXgLmGBFzJnA/8MOkY61GxDzNeuXIODHgKL5uPB7rMnb/Au0fFO7GMgxuajUOWfBuhrz3vez5zW20vvKK3XIEB+FxQMCGU7HTxTcX2GREzM1GxGwH7gEuSS5gRMynjIiZCG9ZDozPs8bBZ75OnOaiyrgvPN2fiU0Cuufp5rdiGP3NWygdOZJtX/giXQcP5vXegnNRyl2Ntf5gp4EaB2xJ2t5q7UvHdcCjSdsVpt9YZfqN5abfuDTdSUqpG5RSq5RSqzoH4v8fZMSXsnpQdo5BOQ1Fogdlt5D8GihvXR3jfvFzOvbsiY9HyW9CIN6DEvuUGjsNVKraIeXXZPqNjwBzgOQMrBONiDkHuAr4uek3Tkp1rtZ6odZ6jtZ6TklJ/4fcBj9eYf8YlNN+/Kp7DModQRLJVM6YwaivfY2mpUvZt/APtulwLU57GJAgid6w00BtBSYkbY8HtvcsZPqNC4GbgYuNiNmW2G9EzO3W383AUmBWTlQO1h1kd8TasTIcgcdum53jXHx90XD1VQy56CL2/PznHH78CVs0uBknPQsQ1yPmKTV2RvGtBCabfuNEYBtwBfHeUDem35gF/B5YYETM3Un7G4AWI2K2mX5jOHAWxwZQZI/BVma218bO46iLz52fiVKKMd/9Xzq2bmX7//t/lI4ZTeXMmXbLEmxCOczF5wuGj4mujoYCoRRlLge+Rdy2romGAlf1LNOjfCUwMRoK9GshLNt6UEbE7AQ+AzwOmMC9RsRcb/qNW02/kYjK+xFQA9xn+o2XTb+xKHE6sMr0G2uAp4CQETFzlDtncFF83WNXTvoF2oz9H0liXNGu+4OnvJzxv/k1JSNGsOW/P01Xk525CQU7UdjvYUngC4aPi672BcNTe5SZDNwEnBUNBaYBX+jjmu8DXgYes7ZP8wXDi3o7J4Gt86CMiPkI8EiPfbckvb8wzXnPATNyqy5LKCcESTjjx5/g6ERdm4XYTMmwYYz44hfY/uWv0LFlC17DsFtS0ePEn5xy1jyoucCmaCiwGcAXDCeiq5M7AJ8EfhMNBQ4AREOBvtaU+ZZ13aVW+Zd9wbAvEzGSSaIvBh1m7owxKCdxNMrc5iAJBwxGeCoqACSiz8V4lMq3u7skEdlsvW5IOpZJdPUUYIovGP6PLxhebrkEe6MzGgocGpDQgZzkKgabWNQhY1D2V8VH6Y68t80+OcdAHe1hSwMmXzjgWz8GRd57dp1a6zlpjmUSXV0CTAbeQTy47RlfMDw9Ggqkm9y3zhcMXwV4Lffg54DnMhEqPai+yFIPym4D5SQSQRLSqySpASM9KLfisCCJTKKrtwIPRkOBjmgo8AbwKnGDlY7PAtOANuBvwGH6GLdKID2oPhhsa7u75yUunG6OzoOyCQf1oGQitxAfg3KMhVoJTPYFw2mjq4EHgCuBO33B8HDiLr/N6S4YDQVaiE8Vurm/YsRA9cWgs5lnlouv6/BhOnbupGLKlIHdJwW6q4umpUuJ6RFZu2Y2sD2buZNI/D7ExZcXnPiTc9I8qGgo0OkLhhPR1V7gjmgosN4XDN8KrIqGAousY+/yBcMbgC7gq9FQYF/Pa/mC4Yfo5V+LhgJ95lAVA9Un2XLx9V7szauvpm3jJoyIObD7pGD/X/7C7tAP6PivHwPlWbvuYLF9WM6mXHypUF6rByUuPtdiQ5BEr0RDgeOiq6OhwC1J7zXwJevVGz8erBYxUH0x6GzmmY0xtG3M/mJ2nTt2ABA70opSzjFQjsnF54ThcnHx5R0nLPeeTHwelN0qsk80FHh6sNfo00CZfmOEETH3DPZGBctgk8VKkMRxuDkX33GIi8/1KKUc4+LLJr5geC29u/j6TJ+SSQ/qOdNvvAH8HfinETEPZC6xCBh0FJ+0kHvisT1uZJC94iyiJIovr9jWKOqFIl5u4yLr76etv3+x/l4NtBxf/Hj6NFBGxJxs+o25xKM5bjb9xgbgHiNi3t1PsQXJoOfM9DNrgtY66y4I5/30rc/Egcryjrj4XI8CJz5qOBpVAAAgAElEQVSkgyYaCrwJ4AuGz4qGAmclHQr6guH/ALf2dY2M5kEZEfMFI2J+iXi6iv3AXQPQW5gMOoqvny3kHFVUygndBQv7gyQGOfk6m4iLL+844Fs/Bo9Sxd5Yq/YFw2cnNnzB8JlAdSYnZjIGNQR4P/Ee1EnAv4gbKncw2HlQ/a2Nu7rA6x3QvQoFycV3lO7fR6zLXiGCbShV9B3o64A7fMFwnbV9EPhEJidmMga1hvjErFuNiPn8wPQVMoMcr+jnRF0dizmuhZdt7M7F56hUR55ED6q4ayghPYri7kFFQ4EXgVN9wfAQQPUnL18mBmqSETGL99Pri8G6gzKcqNtNV/G3pO3OxeekTBKSiy+/OLHXHg+SsFtF7vAFw+XABwEfUOILhgGIhgJ9jkFlEiRxzEdn+o3vAYeA242Iedzs4aIja7n4MrydC1rSkosvCYnicz0Oy8WXCx4kbjNeJJ6PL2MGMlH3BeJjUT8DPjaA8wuKwUfxJS5kc5CEAzoLCezPxddDiI0oa7zRDQ0Tp+CAr/0YEjGtRcz4aCjQ15IcKel3NnMjYj4A/MqImEVvnIBBV2bdyUAzbCK5oaKSXHxJiIvP9Xg8Rf/1P+cLhge0wGwmUXxLgWuNiBm1tucCfwBOHcgNC47uSnSQ86AyNTxuGINySJi5E5rSMlFXUKhib6ydDVzrC4bfIO7iU4DOViaJ7wOPmX7jl8RXVnwP8PFBiC0wBhvFl+hBZXi3ruxXVE776duei89JlYFM1M0rDvrmu/EUeZAEcZsxIPp08RkR83HgU8AviMeuv9eImKsHesOCY9BRfInrZDoGlZselP19haMcTU9Y3E9lRshE3bzjpEnrABRvLr4h1tvGNK8+ycTF9w3gcuBcYCaw1PQbXzYiZnggontcewFxw+clHhUY6nG8HPgzcDqwD/hwkqvxJuITwLqAz1mGNPsMeqJuP8egctCDQuMoC9U9NczmKAknZJIQF58Qz2ZejCaK/yOej+9Fjq+FNDCprwtk4uIbDsw1ImYr8LzpNx4DbgcGZaBMv+EFfgPMJ76E8ErTbywyIuaGpGLXAQeMiHmy6TeuAH4AfNj0G1OJZ7aYBowFnjT9xhQjYma9+5G1XHyZunBcUFF1h5kXZbuxn4iLz/XEDuyntfEQ+/+6icrTTqPsBB/emowyATmaaChwkfX3xIFeI5N5UJ/vsf0mcaMyWOYCm4yIuRnA9Bv3AJcAyQbqEuBb1vv7gV+bfkNZ++8xImYb8IbpNzZZ18t+possGai9v/wVlbNOw2ovxQ2W1vFuRFLrafcPf0jphInH3lsnyui4KyjVfp28P36s+dlnAWhdu5bYFOdkp4rt2wvAU1/7XzbQxsHqBhora+koLafT46VDxV+dyhOfI6KU1fY6NiD36N/+fTddzc0Mm/pevp+V/2aQWAZq5/e+T/Pzy4/+znr+3pJb2EnvO7Zto/PAfiqmTk19/d7aAL212ouwRd/+xhs0nnwh2jvBbinHENu3j85DB9j1nYUAHCyrZvuIiRwYPpYDVfW0llXSXlpOW0kZ7aqETo+H4VWlfPs719msPHN8wfAHiAdLaOCZaCjwQCbn2blg4ThgS9L2VmBeujJGxOw0/cYhYJi1f3mPc8eluolS6gbgBoCysrJ+i/RUVlHm86HKBrbgX/mUKZSdcAJNzz5L09N9r9/VtOyZo61q6K6oVOK9x3NMJda9P7liS7w6OxMXIdbcPCD9uaD0YHx+9x9OPradU6q7KNExSnUXpboLr46hLGOrumNVjq04FT32Z1CvNlXVcWjKSdzsLad+EP9HNigZOZKqefNo3/IWzS+siO/strz6WEN1zNv4Rsf27fGibe3pb9Jb46rXQ/a7QLNF5/79xBobafeeBCeOtVvOsWjNwaGj+Os37mTJa3vZkWIqq0fHqIh1Uq678OouJrT2a76rrfiC4duAk4G/Wbs+5QuG50dDgU/3chpgr4FK9evvWb2kK5PJufGdWi8EFgJUV1f3u1lYfcY8Tnrs0f6e1k3Z+PGc9Phj8R5OR0d8Z8KAWMYml2MhurOTkq/8AeWgFrExxMu3n7+dsV/5MhPeNpPhNeU0VJXh9eSnQrzj2Te49eENKK/9C0p7yso44a47B3z+wQceINbUzNCPXJ09UUWI1pqu/fsp+9H94DBvaomOES2pY7u5n/NPGcXHT2hgyqhaRtdVMLK2gpryEkq9ua0ncsx5wHRrqXh8wfBdwNpMTswkSOIsI2L+p699A2ArkNzXHg9sT1Nmq+k3SoA64st9ZHKuo1BKwQB6cIO+b0mJowIkIN4anLsrwgljKqgaPaTvE3JEMYyB1V96qd0SCgKlFCXDhtktIyWf3L+abUNGc8VPggypKLVbTi54FZgIvGltTwBeyeTETJqQvwJmZ7Cvv6wEJpt+40RgG/Ggh6t6lFkEXEN8bOlDwL+NiKlNv7EI+D/Tb/yUeJDEZOIpmIQCoDtgxNPvRCaCUHRMbd3NjKrOYjVOEB+WMX3BcKKOfhvwvC8YXgQQDQUuTndiWgNl+o23A2cCI0y/8aWkQ0OIh4UPCmtM6TPA49b17jAi5nrTb9wKrDIi5iLgj8BfrCCI/cSNGFa5e4kHVHQCn85FBF+x4Lh+QiK+3CaXxdF5WLbcXrCR/gbU5IVYDKWKurF2y0BP7K0HVQbUWGVqk/YfJt6bGTRGxHwEeKTHvluS3h8BLktz7neB72ZDh5BnrFB6JT0oId840D5prYvdm7AKaI2GAjFfMDwF8AOPRkOBjr5O7M1AXW9EzI+afuOQETF/ni2lgh3EQ9udgt0uvqMLJgpuxHF5G2Kxowkqi5NlwDm+YLgBWELcYH0Y6DOyp7ca4nTTb5wAfNz0Gw2m3xia/MqKbMGddLv4irrVKAiZUfwuPhUNBVqADwC/ioYC7yeeZKFPeutB/Q54jHg6ip659zJKUyE4BKc1zqx8g8prUw+qcMN1hcGilOO6zjoWA++gh/WdjPIFw28n3mNKzC7O6B9Oa6CMiPlL4Jem3/itETFvHLREwUacVSHb7eLr1iFREoITiMWO5mQsTj4P3AT8KxoKrPcFw5OApzI5MZNURzeafuNsYLIRMf9k+o3hQK0RMd8YlGQhrygn1cU2R/EJ7sZxv7pYrKjd3dFQYBnxcajE9mbgc5mc2+enYvqNbwJfI24BIR7dd3f/ZQqChc1RfLYvOS8ISbggim/AZPKpvB+4GGgGMCLmdo4NOxeEfuEUF5/gRhzXf3KDi2/AZFJDtBsRM54yGzD9RuHngXcZ2mmuNLsn6lp/ZQjKfTjyKy9yF58vGD4rk32pyORTudf0G78H6k2/8UngSeAP/ZMoCEkkXHzFHbkkOBGHtdXAFS6+X2W47zgyCZL4sek35hPPIHEKcIsRMRf3T59gN06anNi9arBdD6XTepRCnnHOswAU7URdK7T8TGCELxgeULq8jNYbsAySGCUhO1hjUHbPRyqGbOZCERCLoTxF6U0YdLq83pLFNpK6qaEAbURM+9ZJEAob7YxUR4ILcWDvOe7ic56uLHB9NBT4qC8YPhQNBQaULq+3iboSqVcsOGz2vGOi+Bz0mQj5wZFfeVdXsSZOPt0XDJ8AfNxapPAYKxwNBfb3dQH7lxQV8oSDHk2ZqCvYhMKBPejijeIbdLo8MVBC/rE5ik8m6roZx5knx0Xx+YLhBcAviAcy3B4NBUJpyn0IuA94WzQUWNXzeDQU+CXwS18w/NtoKDCgdHnO+VQE12B7FJ8gOAkHTdT1BcNe4DfAe4CpwJW+YHhqinK1xNMVrejrmtFQ4EZfMHy2Lxj+uHXucF8wfGImeqSGcAsO6S5orWl7NQKAKrGnA68c2IoW8oPGWeOxra+8Qqy1FVVRabeUBHOBTdFQYHM0FGgH7gEuSVHuO8APgSN9XdAXDA84XZ4YKBfgpEwS+/5wOwfvu5+Gq67CW2tvHI5kkhDspG3jRrZ88gZKx4yh4eqr8nnrEqXUqqTXDUnHxgFbkra3Wvu68QXDs4AJ0VDg4Qzvd0y6vGgokHG6PBmDcglOMFGHHg6z56c/ZUggwKiv32ybDgfZayHfKGdMWu/YvZu3bvgvVFkZE/90B6UjR+bz9p1a6zlpjqV6Oro/MF8w7AF+Blzbj/u1R0MB7QuGtXWNjNPlSQ9KyAstq1ez46abqJozhzHf/54jwmploq5gB7HWVrZ++jN0HTzIhN//jrIJE+yWlMxWIFnQeGB70nYtMB1Y6guGo8AZwCJfMJzO4AHc6wuGfw/U+4LhfqXLs6UHZS0Z/3fAB0SBy42IeaBHmdOA3xJPi9EFfNeImH+3jt0JnAccsopfa0TMl/OhXeg/7Vu2sPXTn6F07FjG/eqXeMrK7JYkCLagYzG23/Q/HFm3jvG//hUVU4+LP7CblcBkK4hhG3AF0O1/jIYCh4DhiW1fMLwU+EqqKL6kc37sC4aPSZcXDQUyykxkl4svCCwxImbI9BtBa/trPcq0AB8zIuZG02+MBV40/cbjRsQ8aB3/qhEx78+j5oJFx5N/2HLvWFsbWz//eXRXFxN+/ztKGhps0ZGMZDN3L3aPx+774x9pfOwxRn71K9RecIGtWlIRDQU6fcHwZ4DHiYeZ32GtgnsrsCoaCiwa4HUHlC7PLgN1CfAO6/1dwFJ6GCgjYr6W9H676Td2AyOAgwgFw67vfZ+2DSbjb7uNMp/PbjmCYBstL77Inp//gtr3LGDoJz5ht5y0REOBR4BHeuy7JU3Zd6S7ji8Y7jVdXjQU6DNdnl0GapQRMXcAGBFzh+k3eh0hNP3GXOKhia8n7f6u6TduAZYAQSNitqU614pQuQGgzMWuJTuWfD+0aBEH//53hl1/HbXvPD//AtIgE3Xdi12ZJDr372fbF79E6fhxjPnOd2xPlJwPoqHAoMN0c2agTL/xJDA6xaF+hW+ZfmMM8BfgGiNiWjM8uQnYSdxoLSTe+7o11fla64VWGaqrq91ZJ9nwLLRv3cqOb32byjmnM+ILX8i/AEFwCFprtt90E10HD+L7/T14a2rsllQw5MxAGRHzwnTHTL+xy/QbY6ze0xhgd5pyQ4Aw8HUjYi5PuvYO622b6Tf+BHwli9KFQaJjMXbc9D8opRj3wx/aNiE3HTJR183kfzz20D/+QfPTyxh1881UGEZe713o2BXruwi4xnp/DfBgzwKm3ygD/gX82YiY9/U4Nsb6q4BLgXU5VVvw5LdCPnD33bSsXMmo//kfSseOzeu9+4OWKAnXke9vvGP7dnaFfkDV3Ln5noxbFNjVtA0RX0r+OuAt4DIA02/MAT5lRMzrgcuBc4Fhpt+41jovEU7+V9NvjCBe874MfCrP+guQ/DyabZvfYPdPfkrNO95B3Qfen5d7CkLG5LEDpbVmx9e/gY7FGPO97zpi7l+hYYuBMiLmPuC4GEsjYq4Crrfe302afE1GxHxnTgUKA0Jrzc5vfxtVXs7oW7/t3IHgRJCEdKBcSP5+k4f+9QDNzz3H6G/eQtn48Xm7bzEhJt0N5OmZPBx+hJYVKxj5xS/kO3WLIDiKrkOH2P3jH1M5axb1H/6w3XIKFmeNXgsFS1djI7t+EKJi+nTqL7/cbjm94tB+nZAH8tVp3vPLX9F18CCj/3i7uPYGgRgoF6DzUCXv/fWv6dq7jwm33WbbQoSC4ASOmCYH/vY3Gq68UqL2BomYdpegcjjg0v7mm+z/6/9R/6EPUTljRs7uky0cOzYm5J4cZzPXWrPre9/HW1/PiM9/Lmf3cQtioIRBs/vnP0eVljL8s5+xW0q/kCAJIds0L1tGy8qVDP/Mp/EO6TOTj9AHYqDcQA57DK2vvELjo48x7OMfL5jACOk/uZdcTtLWXV3s/slPKT1hIg2XXZaz+7gJMVAuIFcdBa01u3/0Y7zDhjk6+WU6ZD0o96Fz2Do59NBDtL32GiM//3lUaWnubuQixEC5hFw8ly3PPx93Z9x4I96ajBfJFARbycWzoNvb2fPLX1IxbRq1Cxbk4A7uRAyUMGD23HYbJaNGUX95YbkzlEzUdTG56UIdfPBBOrfvYMQXPi9h5VlEPklXkP2HsvmFF2hd9SLDrr9eVsgVXI3u7GTfwj9QMX061WefbbecokIMlGvIbndh722/xTtiOPWXfSir180HEmXuXnLRaT78yCN0bNnC8Bs/JVMYsowYKDeQ5WemZfVLtCxfzrBPXIenoiK7F88j4uFzKVn84nUsxt7fL6R8yhRqznfOopzFghgot5DFh3LfHX/EW1dHw4edndIoHbIelJvJbjrzxiVLaH/9dYZ/6r9k7CkHyCcq9Iv2t96iacm/qb/iCjxVVXbLGRSyHpQLyXLb5MBdf6Z03Dhq3/3u7F5YAMRAuYTsPZX7/3I3lJTQcJUsvia4myMbNtCyahUNV18t+SdzhBgoF5CtfkJXYyOH/vEPhrxnAaWjCiNrRCq6w8ztlSHYQDa/8/1//guqqor6D30wi1cVkhEDJWTMwfv/QaylhaHXXGO3FEGwlc69ezkcDlN/6aWScy+HiIFyCYPN4Ky15uA991A5ezaV06ZlSZW9yBCU+1BKZSWb+YF7/o7u6KDhox/JgiohHWKg3EAWhqBaVrxA+5tvFmzkniBkC93VxcH77qP67LMpP/FEu+UUNWKgXMHgLdTBe+/FU1dXFNFKMplSGAzNzz5L565d1EvG8pxjy4q6pt8YCvwd8AFR4HIjYh5IUa4LWGttvmVEzIut/ScC9wBDgdXAR42I2Z575YXJYB0anfv3c3jxYhquvKKgJ+Yej/j43EY2Vpc+eP/9eIcOpfb8dwxekNArdvWggsASI2JOBpZY26loNSLmadbr4qT9PwB+Zp1/ALgut3ILn8GsqHvoXw9AR4escSMUBUoPfA5c5549ND61lLpLL0VJDsqcY5eBugS4y3p/F3BppieafkMB7wTuH8j5Qv/QWnPwvvuonD2b8smT7ZaTFRJtaAmSEPrLoQcfhM5OCS3PE3YZqFFGxNwBYP1NN6mmwvQbq0y/sdz0GwkjNAw4aETMTmt7KzAu3Y2UUjcopVYppVZ1dnamKyak4cjatbRHo9R/4P12SxGE7DGA1onWmoP3/4PK00+nfNKkHIgSepKzMSjTbzwJjE5x6OZ+XGaiETG3m35jEvBv02+sBQ6nKJf216a1XggsBKiurnZlm3kwQQGHFj2EKisriuCIBDJR170MZkXdI6+8Qns0yphPXp89QUKv5MxAGRHzwnTHTL+xy/QbY4yIucP0G2OA3Wmusd36u9n0G0uBWcA/gHrTb5RYvajxwPas/wNFxEArYt3RweFHHqHmne/EW1ubVU2CYA8DX63y0MPheGPtXe/KsiYhHXa5+BYBiXQE1wAP9ixg+o0G02+UW++HA2cBG4yIqYGngA/1dr7Qk/4/kM3PPUfX/v3Uve+iHOixD8lm7nZ0vw2U7uri8KOPUnPeedJYyyN2GagQMN/0GxuB+dY2pt+YY/qN260yBrDK9BtriBukkBExN1jHvgZ8yfQbm4iPSf0xr+oLkQF0ow4teghvXR0155yTfT0OQIIk3MdAmyYtK1bQtXcvQy4qrsaa07FlHpQRMfcBF6TYvwq43nr/HDAjzfmbgbm51Oh2upqaaVyyhLpLLym6cFqZpyv0t3Vy6OEwnpoaas47N0eChFRIJgkXMJDJiU1Ll6KPHKGuiFuMWsIkXIceQOsk1tZG4xNPUDt/fpFNVHc+YqCElDQ+8QTeEcOpnD3bbimCkH360YNqfuYZYk1NDAkEcihISIUtLj4hz6j+ZTOPtbbS9MwzcfdeES5jLRN13U1/+1CNixfjrauj+ox5OdHjNHzB8ALgF4AXuD0aCoR6HP8S8aGYTmAP8IloKPBmLrQUX+0jDJqmZ59Ft7YyRMJphSIl07aJ7uig8aml1Jx/Pqqk+NvzvmDYC/wGeA8wFbjSFwxP7VHsJWBONBSYSTyjzw9zpaf4P3Gh3yRajFVz5tgtJSdIkIR76TZMGXafW1atInb4MLXz007rLDbmApuiocBmAF8wfA/x1HSJCGqiocBTSeWXAzlbFEt6UC6gP54s3d5O01NLqbngAlRpac40OQFx8bmR/rVOGhc/iaqooPrMM3Okx3GMA7YkbfeaSo54ou5HcyVGelAuQKFQGVbGzStWEGtsLPIWo3Sh3IzSmU3U1bEYjUuWUHPO2XgqK/OgLG+UKKVWJW0vtFLCQeqHI+WH5QuGPwLMAc7Lsr5uxEC5hswsVOPiJ/FUVbmixShh5i6kH22TI+vX07lrFzUXfCF3euyhU2udzn+/FZiQtJ0ylZwvGL6QeF7V86KhQFv2JcYRAyV0o7Wmadkyqs8+G095ud1yBCF3ZNCDalz8JHi91L7jHbnX4xxWApN9wfCJwDbgCuCq5AK+YHgW8HtgQTQUSJlHNVvIGJQbyLDV2PbaRjp37iz62fJq4PlChWIhgy+/aelSqk4/HW99fR4EOYNoKNAJfAZ4HDCBe6OhwHpfMHyrLxhOLBr7I6AGuM8XDL/sC4YX5UqP9KBcgM5wFlTTsqcBqD67OHPvCUKmrbWOnTtpe+01Rn71KznW4zyiocAjwCM99t2S9D5vA9TSg3IJmTyWzU8vo3yqQemodOtHFgcSIuFuVAbZzJuffRaA6iJNlFwoiIESAOg6fJiWl16i5tzidu8JQiY0LXuGklGjKJ882W4prkYMlFvoq8X43HPQ1UXNuTmLGHUMg1lhWCgOenscdEcHzc89R/U5Z8tvxWbEQLmAjMafnl6Gt66OylNn5lyPU5AgCfeRSTbz1jVriDU1UXOOeBPsRgyUS+jtsdRa0/TMM1SfdRbK682bJkGwj/Stk6ZnngWvl+q3n5FHPUIqxEC5gT5ajW0bN9K1dy/VZ52VJ0H20p3NXCbqupdeus9NzyyjctZpeIcMyaMgIRVioFxD+geyZflyANcsJyC4mD48fJ3799O2waTm7LPzo0foFTFQAs3LV1A6cSKl43rLCVk8yERd99L9naf58lteeAGA6jPEvecExEC5hTSVse7spOWFF+SBFNxBH+7u5hUr8FRVUTFtWp4ECb1hSyYJ028MBf4O+IAocLkRMQ/0KHM+8LOkXX7gCiNiPmD6jTuJZ9A9ZB271oiYL+dYdlFyZMMGYk1NrnLvSeSwu+ktm3nLiheonHN60S81UyjYleooCCwxImbI9BtBa/tryQWMiPkUcBp0G7RNwBNJRb5qRMz786S3wElfIzcvXwFA1Tz3GKgE4uFzMSkMVMfu3bRv3kz9Bz9ggyAhFXa5+C4B7rLe3wVc2kf5DwGPGhGzJaeqXEjL8ucpnzKFkmHD7JaSN5QkO3IvVvdZpzBQLS+sBKBqrvsaa07FLgM1yoiYOwCsv30lf7sC+FuPfd81/cYrpt/4mek30q4NoZS6QSm1Sim1qrOzc3CqCxUFqfoLsfZ2Wl5c7dr5HqkqKcElpDJQK1bgqa2lYqphgyAhFTlz8Zl+40lgdIpDN/fzOmOAGcTTvye4CdgJlAELibsHb011vrVS5EKA6upqV9ZIGpXSn9X68svotjaq5rnTQAkuJDEAGYsdd6j5hRVUzZkjk9UdRM4MlBEx06ZkN/3GLtNvjDEi5g7LAPW26NXlwL+MiNmRdO0d1ts202/8CXBfTvz+oBQKjdb6mNxirS++CEpRdfpsG8XZQCLM3F4Vgi3EHby6h4Hq2LmTjjffouHKK+2RJaTELhffIuAa6/01wIO9lL2SHu49y6hh+g1FfPxqXQ40Fg8Jm9TjoWxZ/RLlJ5+Mt64u/5oEwQ6604gc2zzpnv/kwmAhJ2OXgQoB802/sRGYb21j+o05pt+4PVHI9Bs+YALwdI/z/2r6jbXAWmA48L/5EF24WE9lV1f3Ht3VRetLL1Hptt4Tsh6Uq0nj4mt5cTWemhrKp0yxQZSQDlvCzI2IuQ+4IMX+VcD1SdtR4Lj0BkbEfGcu9RUdSZFLicq5beNGYk1NVJ1+un26bEZiJNxIagPVuno1laedJuNPDkMySbgEBcc8lC0vvghA5SwX9qBkpq57UQrQx4xBdR0+TNumTVTOnmWfLiElYqDcQAq3RuvqlygZNYrScWNtEuUEpAvlOlKMx7auWQNaUzVLDJTTEAPlIpJbjS2rV1N1+mzpTQguw3J393gW8HqpnOmexToLBTFQbqBHD6pj+3Y6d+xwpXsP0gZyCS5Ap0hl37r6JSpOOQVPdbVNqoR0iIFyAd0rDFgGquXF1QDum/8kuB7Vw8WnOztpfeUVKsW950jEQLkBpeIZnK2HsvWl1XiqqlwbUqtkoq6LUSh9tLF2JPIqurVVAiQcihgoF9A9ypQwUK+spWLGDFSJXcnsBcEmevh3W1db3oTZ4k1wImKg3EBiHlRME2tv58irr1I5Y7rNouxDspm7mB7jsa1r11IyciSlY8bYKEpIhxgoF9A9PVfHaItEoKODiukz7BXlACRIwn3oHlF8R9bGvQmCMxED5QYSHYauLlrXrgVwdQ9KcDEKFBpimq7GRtqjUSqny/LuTkUMlBtISnV0ZO06vEOHUjLWvRN0j0YaSxfKfSRcfF0cWb8BQLwJDkYMlAtIDpJoXbeWihnTZYKu4E7UURffkXVxb0KF9KAcixgoN2A9lF2NjbS/vplKl7cYuwO5bFUh2ELSRN3WdespHTeOkoYGezUJaRED5QISA8NH1q0HramQ8SfB7cRiHFm3TgIkHI4YKDdgDQy3rlkDQKXbH0rxbroXFZ9k0Ll/Px1bt0qAhMMRA+UK4jVy65o1lIwdQ8mwYTbrcQYSI+FejqxNjD+JN8HJiIFyA564gWp//XXXjz+BTNR1NSrRWHsFgIpp0oNyMmKgXEDyKqEy/nQULWES7sN6FlpWr6bM58NbW2uzIKE3xEC5Ac/Rr9n140+Cu0k8C52d4t4rAMRAuQGPB835aFUAAAjqSURBVGV1FsSlkbTkgnSgXEfcmxD/4iWbivOxJZ216TcuA74FGMBcI2KuSlNuAfALwAvcbkTMkLX/ROAeYCiwGvioETHb8yC9MPEcdfGJS0NwNcnubulBpcQXDB9T70ZDgVCP4+XAn4HTgX3Ah6OhQDQXWuzqQa0DPgAsS1fA9Bte4DfAe4CpwJWm35hqHf4B8DMjYk4GDgDX5VZu4RKLaSgvB6Dh6qttVuMMiilEYvOeJiI7D9stoyA40tF17HisYdioxpn4guHj6l1fMDy1R7HrgAPRUOBk4GfE6+OcYEsPyoiYJoDp7/UHMhfYZETMzVbZe4BLTL9hAu8ErrLK3UW8N/bbXGhd+upuPv3X1bm4dF5o64zRGdPMmjmDUf99pt1yHIHHimr8+J0r8XoGbq6yEaY+2ECNIx3xrNyVpd4+SmaXfGbKysatOmKa9s4YXo9ihPXFeaqqsnDlomMusCkaCmwG8AXD9wCXABuSylxCvM4FuB/4tS8YVtFQIOtOcyevWDcO2JK0vRWYBwwDDhoRszNp/7h0F1FK3QDcYG1qpVTrALSUAJ19lrKHjLS9CXg+m3sxPXDy5wbO1ifaBkaf2jYT7xrk1crGccrnVqmUSh5WWai1Xmi9T1fvJtNdJhoKdPqC4UPE6+W92RaaMwNl+o0ngdEpDt1sRMwHM7hEql+P7mV/SqwPfmG645mglFqltZ4zmGvkCtE2cJysT7QNDNE2aDKpX/tVBw+GnBkoI2JeOMhLbAUmJG2PB7YTt9L1pt8osXpRif2CIAjC4EhX76Yqs9UXDJcAdcD+XIhxsotvJTDZitjbBlwBXGVETG36jaeADxGP5LsGyKRHJgiCIPTOSmCyLxg+pt7tUWYR8Xr3eeL18L9zMf4ENkXxmX7j/abf2Aq8HQibfuNxa/9Y0288AmD1jj4DPA6YwL1GxFxvXeJrwJdMv7GJuO/zjzmWPCgXYY4RbQPHyfpE28AQbYMgGgocV+9GQ4H1vmD4Vl8wfLFV7I/AMF8wvAn4EhDMlR4lq4oKgiAITkQySQiCIAiORAyUIAiC4EjEQPWBUmqBUupVpdQmpVTOfK39RSk1QSn1lFLKVEqtV0p93m5NPVFKeZVSLymlHrZbSzJKqXql1P1KqYj1+b3dbk0JlFJftL7PdUqpvymlKmzUcodSardSal3SvqFKqcVKqY3WX1vWS0+j7UfWd/qKUupfSql6p2hLOvYVpZRWSg23Q1uhIQaqF5RSx6X9UEr1TPthF53Al7XWBnAG8GkHaUvweeIDrU7jF8BjWms/cCoO0aiUGgd8DpijtZ5OPBfaFTZKuhNY0GNfEFiitZ4MLCGHA+R9cCfHa1sMTNdazwReA27KtyiLOzleG0qpCcB84K18CypUxED1zlxgk9Z6s9a6nXhY+yU2awJAa71Da73aet9IvJJNm1Ej3yilxgMB4Ha7tSSjlBoCnIsV+am1btdaH7RX1TGUEJ/pXwJUYeMcP631Mo6f33IJ8fRiWH8vzasoi1TatNZPaK0TmRqWE5/Dk3fSfG4Qz1v3/5A8+hkjBqp3UqX9cIwRSKCU8gGzgBX2KjmGnxN/GGN2C+nBJGAP8CfL/Xi7UqrablEAWuttwI+Jt7B3AIe01k/Yq+o4Rmmtd0C8kQSMtFlPOj4BPGq3iARKqYuBbVrrNXZrKSTEQPVO3lJ6DBSlVA3wD+ALWmtHpLVWSl0E7NZav2i3lhSUALOB32qtZwHN2OemOgZrPOcS4ERgLFCtlPqIvaoKD6XUzcRd4H+1WwuAUqoKuBm4xW4thYYYqN7JJO2HbSilSokbp79qrf9pt54kzgIuVkpFibtF36mUutteSd1sBbZqrRO9zfuJGywncCHwhtZ6j9a6A/gn4LQU9LuUUmMArL+7bdZzDEqpa4CLgKu1cyZ5nkS80bHGeibGA6uVUqlylQpJiIHqnZXAZKXUiUqpMuID1ots1gSAUkoRH0cxtdY/tVtPMlrrm7TW47XWPuKf2b+11o7oCWitdwJblFKnWLsu4NilBOzkLeAMpVSV9f1egEMCOJJIpLkBh6UZU0otIJ5l5mKtdYvdehJorddqrUdqrX3WM7EVmG39FoVeEAPVC9aA6zFpP7TW63s/K2+cBXyUeO/kZev1XrtFFQifBf6qlHoFOA34ns16ALB6dfcTXyV6LfHn07b0OEqpvxHPt3aKUmqrUuo6IATMV0ptJB6RFurtGnnW9mugFlhsPQ+/c5A2YQBIqiNBEATBkUgPShAEQXAkYqAEQRAERyIGShAEQXAkYqAEQRAERyIGShAEQXAkYqAEoReszOf/nbQ9Vil1f47udalSKm22AaXUDKXUnbm4tyA4EQkzF4ResPIcPmxlF8/1vZ4jPsl0by9lngQ+obWWjNhC0SM9KEHonRBwkjXx80dKKV9inR+l1LVKqQeUUg8ppd5QSn1GKfUlKwntcqXUUKvcSUqpx5RSLyqlnlFK+XveRCk1BWhLGCel1GXWmlBrlFLLkoo+hL1LcAhC3hADJQi9EwRe11qfprX+aorj04GriC/N8l2gxUpC+zzwMavMQuCzWuvTga8At6W4zlnEM0gkuAV4t9b6VODipP2rgHMG8f8IQsFQYrcAQShwnrLW42pUSh0i3sOBeKqimVa2+TOB++Lp9QAoT3GdMcSXAUnwH+BOpdS9xJPGJthNPNO5IBQ9YqAEYXC0Jb2PJW3HiD9fHuCg1vq0Pq7TCtQlNrTWn1JKzSO+6OPLSqnTtNb7gAqrrCAUPeLiE4TeaSSegHRAWGt0vaGUugziWeiVUqemKGoCJyc2lFInaa1XaK1vAfZydNmXKcC6geoRhEJCDJQg9ILVa/mPFbDwowFe5mrgOqXUGmA98UUJe7IMmKWO+gF/pJRaawVkLAMSK7GeD4QHqEMQCgoJMxcEh6CU+gXwkNb6yTTHy4GngbOtpWAEoaiRHpQgOIfvAVW9HJ8IBMU4CW5BelCCIAiCI5EelCAIguBIxEAJgiAIjkQMlCAIguBIxEAJgiAIjkQMlCAIguBI/j/mqngG1vxIugAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax1 = plt.subplots()\n",
"\n",
"color = 'tab:red'\n",
"ax1.set_xlabel('time (s)')\n",
"ax1.set_ylabel('left x,v', color=color)\n",
"ax1.plot(t, body.left_arm.x_and_v_norm_history[:,1], color=color)\n",
"ax1.tick_params(axis='y', labelcolor=color)\n",
"ax1.set_ylim((-1, 1))\n",
"\n",
"ax2 = ax1.twinx()\n",
"\n",
"color = 'tab:blue'\n",
"ax2.set_ylabel('left spindle', color=color)\n",
"ax2.plot(t, body.left_arm.proprioceptor_history[:,1], color=color)\n",
"ax2.tick_params(axis='y', labelcolor=color)\n",
"ax2.set_ylim((0, 1))\n",
"\n",
"fig.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax1 = plt.subplots()\n",
"\n",
"color = 'tab:red'\n",
"ax1.set_xlabel('time (s)')\n",
"ax1.set_ylabel('right x,v', color=color)\n",
"ax1.plot(t, body.right_arm.x_and_v_norm_history[:,1], color=color)\n",
"ax1.tick_params(axis='y', labelcolor=color)\n",
"ax1.set_ylim((-1, 1))\n",
"\n",
"ax2 = ax1.twinx()\n",
"\n",
"color = 'tab:blue'\n",
"ax2.set_ylabel('right spindle', color=color)\n",
"ax2.plot(t, body.right_arm.proprioceptor_history[:,1], color=color)\n",
"ax2.tick_params(axis='y', labelcolor=color)\n",
"ax2.set_ylim((0, 1))\n",
"\n",
"fig.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, ax1 = plt.subplots()\n",
"\n",
"color = 'tab:red'\n",
"ax1.set_xlabel('time (s)')\n",
"ax1.set_ylabel('total_impulse', color=color)\n",
"#ax1.plot(t, body.left_arm.proprioceptor_history[:,6], color=color)\n",
"ax1.plot(t, body.left_arm.contact_history[:,0], color=color)\n",
"ax1.tick_params(axis='y', labelcolor=color)\n",
"\n",
"ax2 = ax1.twinx()\n",
"\n",
"color = 'tab:blue'\n",
"ax2.set_ylabel('total_ke', color=color)\n",
"ax2.plot(t, body.left_arm.contact_history[:,1], color=color)\n",
"ax2.tick_params(axis='y', labelcolor=color)\n",
"\n",
"\n",
"fig.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"#it is not recommended to kill pygame inside jupyter, as it kills the kernel \n",
"#will kill the kernel, but seems to be the only way to close the pygame window \n",
"#pygame.display.quit()\n",
"#pygame.quit()\n",
"#exit(0)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment