NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
AppAchillesHierarchy.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2012, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
7  * under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * http://www.apache.org/licenses/LICENSE-2.0.
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language
16  * governing permissions and limitations under the License.
17 */
18 
28 #include "AppAchillesHierarchy.h"
29 #include "dev/btietz/JSONTests/tgCPGJSONLogger.h"
30 
31 AppAchillesHierarchy::AppAchillesHierarchy(int argc, char** argv)
32 {
33  bSetup = false;
34  use_graphics = false;
35  add_controller = true;
36  add_blocks = false;
37  add_hills = false;
38  all_terrain = false;
39  timestep_physics = 1.0f/1000.0f;
40  timestep_graphics = 1.0f/60.0f;
41  nEpisodes = 1;
42  nSteps = 60000;
43  nSegments = 7;
44  nTypes = 3;
45 
46  startX = 0;
47  startY = 20; //May need adjustment
48  startZ = 0;
49  startAngle = 0;
50 
51  suffix = "default";
52  lowerPath = "default";
53 
54  handleOptions(argc, argv);
55 }
56 
58 {
59  // First create the world
60  world = createWorld();
61 
62  // Second create the view
63  if (use_graphics)
64  view = createGraphicsView(world); // For visual experimenting on one tensegrity
65  else
66  view = createView(world); // For running multiple episodes
67 
68  // Third create the simulation
69  simulation = new tgSimulation(*view);
70 
71  // Fourth create the models with their controllers and add the models to the
72  // simulation
74  //FlemonsSpineModelContact* myModel =
75  //new FlemonsSpineModelContact(nSegments);
76 
77  //Parameters for the structure:
78  const int segments = 7;
79  const int hips = 4;
80  const int legs = 4;
81 
82  MountainGoatAchilles* myModel = new MountainGoatAchilles(segments, hips, legs);
83 
84  // Fifth create the controllers, attach to model
85  if (add_controller)
86  {
87  const int segmentSpan = 3;
88  const int numMuscles = 16;
89  const int numParams = 2;
90  const int segNumber = 0; // For learning results
91  const double controlTime = .01;
92  const double lowPhase = -1 * M_PI;
93  const double highPhase = M_PI;
94  const double lowAmplitude = 0.0;
95  const double highAmplitude = 300.0;
96  const double kt = 0.0; //May need to retune kt, kp, and kv
97  const double kp = 1000.0;
98  const double kv = 200.0;
99  const bool def = true;
100 
101  // Overridden by def being true
102  const double cl = 10.0;
103  const double lf = 0.0;
104  const double hf = 30.0;
105 
106  // Feedback parameters... may need to retune
107  const double ffMin = 0.1;
108  const double ffMax = 10.0;
109  const double afMin = 0.0;
110  const double afMax = 200.0;
111  const double pfMin = -0.5;
112  const double pfMax = 6.28;
113 
114  const double maxH = 30.0;
115  const double minH = 7.0;
116 
117  const double numHipMuscles = 6;
118  const double numLegMuscles = 6;
119  //Including the achilles tendon
120  const double numAchillesMuscles = 2;
121 
122  // For the higher level of CPGs
123  const double numHighCPGs = 5;
124  const double hf2 = 30.0;
125  const double ffMax2 = 10.0;
126 
127  JSONAchillesHierarchyControl::Config control_config(segmentSpan,
128  numMuscles,
129  numMuscles,
130  numParams,
131  segNumber,
132  controlTime,
133  lowAmplitude,
134  highAmplitude,
135  lowPhase,
136  highPhase,
137  kt,
138  kp,
139  kv,
140  def,
141  cl,
142  lf,
143  hf,
144  ffMin,
145  ffMax,
146  afMin,
147  afMax,
148  pfMin,
149  pfMax,
150  maxH,
151  minH,
152  numHipMuscles,
153  numHipMuscles,
154  numLegMuscles,
155  numLegMuscles,
156  numAchillesMuscles,
157  numAchillesMuscles,
158  numHighCPGs,
159  numHighCPGs,
160  hf2,
161  ffMax2);
163  myControl =
164  new JSONAchillesHierarchyControl(control_config, suffix, lowerPath); //JSONAchillesHierarchyControl * const
165 
166 #if (0)
167  tgCPGJSONLogger* const myLogger =
168  new tgCPGJSONLogger("logs/CPGValues.txt");
169 
170  myControl->attach(myLogger);
171 #endif
172  myModel->attach(myControl);
173  }
174 
175  // Sixth add model & controller to simulation
176  simulation->addModel(myModel);
177 
178  if (add_blocks)
179  {
180  tgModel* blockField = getBlocks();
181  simulation->addObstacle(blockField);
182  }
183 
184  bSetup = true;
185  return bSetup;
186 }
187 
188 void AppAchillesHierarchy::handleOptions(int argc, char **argv)
189 {
190  // Declare the supported options.
191  po::options_description desc("Allowed options");
192  desc.add_options()
193  ("help,h", "produce help message")
194  ("graphics,G", po::value<bool>(&use_graphics), "Test using graphical view")
195  ("controller,c", po::value<bool>(&add_controller), "Attach the controller to the model.")
196  ("blocks,b", po::value<bool>(&add_blocks)->implicit_value(false), "Add a block field as obstacles.")
197  ("hills,H", po::value<bool>(&add_hills)->implicit_value(false), "Use hilly terrain.")
198  ("all_terrain,A", po::value<bool>(&all_terrain)->implicit_value(false), "Alternate through terrain types. Only works with graphics off")
199  ("phys_time,p", po::value<double>(), "Physics timestep value (Hz). Default=1000")
200  ("graph_time,g", po::value<double>(), "Graphics timestep value a.k.a. render rate (Hz). Default = 60")
201  ("episodes,e", po::value<int>(&nEpisodes), "Number of episodes to run. Default=1")
202  ("steps,s", po::value<int>(&nSteps), "Number of steps per episode to run. Default=60K (60 seconds)")
203  ("segments,S", po::value<int>(&nSegments), "Number of segments in the tensegrity spine. Default=6")
204  ("start_x,x", po::value<double>(&startX), "X Coordinate of starting position for robot. Default = 0")
205  ("start_y,y", po::value<double>(&startY), "Y Coordinate of starting position for robot. Default = 20")
206  ("start_z,z", po::value<double>(&startZ), "Z Coordinate of starting position for robot. Default = 0")
207  ("angle,a", po::value<double>(&startAngle), "Angle of starting rotation for robot. Degrees. Default = 0")
208  ("goal_angle,B", po::value<double>(&goalAngle), "Angle of starting rotation for goal box. Degrees. Default = 0")
209  ("learning_controller,l", po::value<std::string>(&suffix), "Which learned controller to write to or use. Default = default")
210  ("lower_path,P", po::value<std::string>(&lowerPath), "Which resources folder in which you want to store controllers. Default = default")
211  ;
212 
213  po::variables_map vm;
214  po::store(po::parse_command_line(argc, argv, desc), vm);
215 
216  if (vm.count("help"))
217  {
218  std::cout << desc << "\n";
219  exit(0);
220  }
221 
222  po::notify(vm);
223 
224  if (vm.count("phys_time"))
225  {
226  timestep_physics = 1/vm["phys_time"].as<double>();
227  std::cout << "Physics timestep set to: " << timestep_physics << " seconds.\n";
228  }
229 
230  if (vm.count("graph_time"))
231  {
232  timestep_graphics = 1/vm["graph_time"].as<double>();
233  std::cout << "Graphics timestep set to: " << timestep_graphics << " seconds.\n";
234  }
235 }
236 
237 const tgHillyGround::Config AppAchillesHierarchy::getHillyConfig()
238 {
239  btVector3 eulerAngles = btVector3(0.0, 0.0, 0.0);
240  btScalar friction = 0.5;
241  btScalar restitution = 0.0;
242  // Size doesn't affect hilly terrain
243  btVector3 size = btVector3(0.0, 0.1, 0.0);
244  btVector3 origin = btVector3(0.0, 0.0, 0.0);
245  size_t nx = 100;
246  size_t ny = 100;
247  double margin = 0.5;
248  double triangleSize = 4.0;
249  double waveHeight = 2.0;
250  double offset = 0.0;
251  const tgHillyGround::Config hillGroundConfig(eulerAngles, friction, restitution,
252  size, origin, nx, ny, margin, triangleSize,
253  waveHeight, offset);
254  return hillGroundConfig;
255 }
256 
257 const tgBoxGround::Config AppAchillesHierarchy::getBoxConfig()
258 {
259  const double yaw = 0.0;
260  const double pitch = 0.0;
261  const double roll = 0.0;
262  const double friction = 0.5;
263  const double restitution = 0.0;
264  const btVector3 size(1000.0, 1.5, 1000.0);
265 
266  const tgBoxGround::Config groundConfig(btVector3(yaw, pitch, roll),
267  friction,
268  restitution,
269  size );
270 
271  return groundConfig;
272 }
273 
274 tgModel* AppAchillesHierarchy::getBlocks()
275 {
276  // Room to add a config
277  tgBlockField* myObstacle = new tgBlockField();
278  return myObstacle;
279 }
280 
281 tgWorld* AppAchillesHierarchy::createWorld()
282 {
283  const tgWorld::Config config(
284  981 // gravity, cm/sec^2
285  );
286 
287  tgBulletGround* ground;
288 
289  if (add_hills)
290  {
291  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
292  ground = new tgHillyGround(hillGroundConfig);
293  }
294  else
295  {
296  const tgBoxGround::Config groundConfig = getBoxConfig();
297  ground = new tgBoxGround(groundConfig);
298  }
299 
300  return new tgWorld(config, ground);
301 }
302 
303 tgSimViewGraphics *AppAchillesHierarchy::createGraphicsView(tgWorld *world)
304 {
305  return new tgSimViewGraphics(*world, timestep_physics, timestep_graphics);
306 }
307 
308 tgSimView *AppAchillesHierarchy::createView(tgWorld *world)
309 {
310  return new tgSimView(*world, timestep_physics, timestep_graphics);
311 }
312 
314 {
315  if (!bSetup)
316  {
317  setup();
318  }
319 
320  if (use_graphics)
321  {
322  // Run until the user stops
323  simulation->run();
324  }
325  else
326  {
327  // or run for a specific number of steps
328  simulate(simulation);
329  }
330 
332  delete simulation;
333  delete view;
334  delete world;
335  // Trying to fix the memory leak in the comments above:
336  delete myControl;
337 
338  return true;
339 }
340 
341 void AppAchillesHierarchy::simulate(tgSimulation *simulation)
342 {
343  for (int i=0; i<nEpisodes; i++) {
344  fprintf(stderr,"Episode %d\n", i);
345  try
346  {
347  simulation->run(nSteps);
348  }
349  catch (std::runtime_error e)
350  {
351  // Nothing to do here, score will be set to -1
352  }
353 
354  // Don't change the terrain before the last episode to avoid leaks
355  if (all_terrain && i != nEpisodes - 1)
356  {
357  // Next run has Hills
358  if (i % nTypes == 0)
359  {
360 
361  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
362  tgBulletGround* ground = new tgHillyGround(hillGroundConfig);
363  simulation->reset(ground);
364  }
365  // Flat
366  else if (i % nTypes == 1)
367  {
368  const tgBoxGround::Config groundConfig = getBoxConfig();
369  tgBulletGround* ground = new tgBoxGround(groundConfig);
370  simulation->reset(ground);
371  }
372  // Flat with blocks
373  else if (i % nTypes == 2)
374  {
375  simulation->reset();
376  tgModel* obstacle = getBlocks();
377  simulation->addObstacle(obstacle);
378  }
379  }
380  // Avoid resetting twice on the last run
381  else if (i != nEpisodes - 1)
382  {
383  simulation->reset();
384  }
385 
386  }
387 }
388 
395 int main(int argc, char** argv)
396 {
397  std::cout << "AppAchillesHierarchy" << std::endl;
398  AppAchillesHierarchy app (argc, argv);
399 
400  if (app.setup())
401  app.run();
402 
403  //Teardown is handled by delete, so that should be automatic
404  return 0;
405 }
406 
407 
void addObstacle(tgModel *pObstacle)
int main(int argc, char **argv)
void addModel(tgModel *pModel)
void run() const
void attach(tgObserver< T > *pObserver)
Definition: tgSubject.h:91