NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
AppQuadControlHierarchy.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 
29 #include "dev/btietz/JSONTests/tgCPGJSONLogger.h"
30 
31 AppQuadControlHierarchy::AppQuadControlHierarchy(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  MountainGoat* myModel = new MountainGoat(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; //This may be ok, but confirm.
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 = 20; // I don't know why I need to double this in order for learning/app to work. This should be 10.
118  const double numLegMuscles = 10;//3;
119 
120  // For the higher level of CPGs
121  const double numHighCPGs = 5;
122  const double hf2 = 30.0; //Not sure this one is necessary, if is overridden by def being true.
123  const double ffMax2 = 10.0;
124 
125  JSONHierarchyFeedbackControl::Config control_config(segmentSpan,
126  numMuscles,
127  numMuscles,
128  numParams,
129  segNumber,
130  controlTime,
131  lowAmplitude,
132  highAmplitude,
133  lowPhase,
134  highPhase,
135  kt,
136  kp,
137  kv,
138  def,
139  cl,
140  lf,
141  hf,
142  ffMin,
143  ffMax,
144  afMin,
145  afMax,
146  pfMin,
147  pfMax,
148  maxH,
149  minH,
150  numHipMuscles,
151  numHipMuscles,
152  numLegMuscles,
153  numLegMuscles,
154  numHighCPGs,
155  numHighCPGs,
156  hf2,
157  ffMax2);
159  JSONHierarchyFeedbackControl* const myControl =
160  new JSONHierarchyFeedbackControl(control_config, suffix, lowerPath);
161 
162 #if (0)
163  tgCPGJSONLogger* const myLogger =
164  new tgCPGJSONLogger("logs/CPGValues.txt");
165 
166  myControl->attach(myLogger);
167 #endif
168  myModel->attach(myControl);
169  }
170 
171  // Sixth add model & controller to simulation
172  simulation->addModel(myModel);
173 
174  if (add_blocks)
175  {
176  tgModel* blockField = getBlocks();
177  simulation->addObstacle(blockField);
178  }
179 
180  bSetup = true;
181  return bSetup;
182 }
183 
184 void AppQuadControlHierarchy::handleOptions(int argc, char **argv)
185 {
186  // Declare the supported options.
187  po::options_description desc("Allowed options");
188  desc.add_options()
189  ("help,h", "produce help message")
190  ("graphics,G", po::value<bool>(&use_graphics), "Test using graphical view")
191  ("controller,c", po::value<bool>(&add_controller), "Attach the controller to the model.")
192  ("blocks,b", po::value<bool>(&add_blocks)->implicit_value(false), "Add a block field as obstacles.")
193  ("hills,H", po::value<bool>(&add_hills)->implicit_value(false), "Use hilly terrain.")
194  ("all_terrain,A", po::value<bool>(&all_terrain)->implicit_value(false), "Alternate through terrain types. Only works with graphics off")
195  ("phys_time,p", po::value<double>(), "Physics timestep value (Hz). Default=1000")
196  ("graph_time,g", po::value<double>(), "Graphics timestep value a.k.a. render rate (Hz). Default = 60")
197  ("episodes,e", po::value<int>(&nEpisodes), "Number of episodes to run. Default=1")
198  ("steps,s", po::value<int>(&nSteps), "Number of steps per episode to run. Default=60K (60 seconds)")
199  ("segments,S", po::value<int>(&nSegments), "Number of segments in the tensegrity spine. Default=6")
200  ("start_x,x", po::value<double>(&startX), "X Coordinate of starting position for robot. Default = 0")
201  ("start_y,y", po::value<double>(&startY), "Y Coordinate of starting position for robot. Default = 20")
202  ("start_z,z", po::value<double>(&startZ), "Z Coordinate of starting position for robot. Default = 0")
203  ("angle,a", po::value<double>(&startAngle), "Angle of starting rotation for robot. Degrees. Default = 0")
204  ("goal_angle,B", po::value<double>(&goalAngle), "Angle of starting rotation for goal box. Degrees. Default = 0")
205  ("learning_controller,l", po::value<std::string>(&suffix), "Which learned controller to write to or use. Default = default")
206  ("lower_path,P", po::value<std::string>(&lowerPath), "Which resources folder in which you want to store controllers. Default = default")
207  ;
208 
209  po::variables_map vm;
210  po::store(po::parse_command_line(argc, argv, desc), vm);
211 
212  if (vm.count("help"))
213  {
214  std::cout << desc << "\n";
215  exit(0);
216  }
217 
218  po::notify(vm);
219 
220  if (vm.count("phys_time"))
221  {
222  timestep_physics = 1/vm["phys_time"].as<double>();
223  std::cout << "Physics timestep set to: " << timestep_physics << " seconds.\n";
224  }
225 
226  if (vm.count("graph_time"))
227  {
228  timestep_graphics = 1/vm["graph_time"].as<double>();
229  std::cout << "Graphics timestep set to: " << timestep_graphics << " seconds.\n";
230  }
231 }
232 
233 const tgHillyGround::Config AppQuadControlHierarchy::getHillyConfig()
234 {
235  btVector3 eulerAngles = btVector3(0.0, 0.0, 0.0);
236  btScalar friction = 0.5;
237  btScalar restitution = 0.0;
238  // Size doesn't affect hilly terrain
239  btVector3 size = btVector3(0.0, 0.1, 0.0);
240  btVector3 origin = btVector3(0.0, 0.0, 0.0);
241  size_t nx = 100;
242  size_t ny = 100;
243  double margin = 0.5;
244  double triangleSize = 4.0;
245  double waveHeight = 2.0;
246  double offset = 0.0;
247  const tgHillyGround::Config hillGroundConfig(eulerAngles, friction, restitution,
248  size, origin, nx, ny, margin, triangleSize,
249  waveHeight, offset);
250  return hillGroundConfig;
251 }
252 
253 const tgBoxGround::Config AppQuadControlHierarchy::getBoxConfig()
254 {
255  const double yaw = 0.0;
256  const double pitch = 0.0;
257  const double roll = 0.0;
258  const double friction = 0.5;
259  const double restitution = 0.0;
260  const btVector3 size(1000.0, 1.5, 1000.0);
261 
262  const tgBoxGround::Config groundConfig(btVector3(yaw, pitch, roll),
263  friction,
264  restitution,
265  size );
266 
267  return groundConfig;
268 }
269 
270 tgModel* AppQuadControlHierarchy::getBlocks()
271 {
272  // Room to add a config
273  tgBlockField* myObstacle = new tgBlockField();
274  return myObstacle;
275 }
276 
277 tgWorld* AppQuadControlHierarchy::createWorld()
278 {
279  const tgWorld::Config config(
280  981 // gravity, cm/sec^2
281  );
282 
283  tgBulletGround* ground;
284 
285  if (add_hills)
286  {
287  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
288  ground = new tgHillyGround(hillGroundConfig);
289  }
290  else
291  {
292  const tgBoxGround::Config groundConfig = getBoxConfig();
293  ground = new tgBoxGround(groundConfig);
294  }
295 
296  return new tgWorld(config, ground);
297 }
298 
299 tgSimViewGraphics *AppQuadControlHierarchy::createGraphicsView(tgWorld *world)
300 {
301  return new tgSimViewGraphics(*world, timestep_physics, timestep_graphics);
302 }
303 
304 tgSimView *AppQuadControlHierarchy::createView(tgWorld *world)
305 {
306  return new tgSimView(*world, timestep_physics, timestep_graphics);
307 }
308 
310 {
311  if (!bSetup)
312  {
313  setup();
314  }
315 
316  if (use_graphics)
317  {
318  // Run until the user stops
319  simulation->run();
320  }
321  else
322  {
323  // or run for a specific number of steps
324  simulate(simulation);
325  }
326 
328  delete simulation;
329  delete view;
330  delete world;
331 
332  return true;
333 }
334 
335 void AppQuadControlHierarchy::simulate(tgSimulation *simulation)
336 {
337  for (int i=0; i<nEpisodes; i++) {
338  fprintf(stderr,"Episode %d\n", i);
339  try
340  {
341  simulation->run(nSteps);
342  }
343  catch (std::runtime_error e)
344  {
345  // Nothing to do here, score will be set to -1
346  }
347 
348  // Don't change the terrain before the last episode to avoid leaks
349  if (all_terrain && i != nEpisodes - 1)
350  {
351  // Next run has Hills
352  if (i % nTypes == 0)
353  {
354 
355  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
356  tgBulletGround* ground = new tgHillyGround(hillGroundConfig);
357  simulation->reset(ground);
358  }
359  // Flat
360  else if (i % nTypes == 1)
361  {
362  const tgBoxGround::Config groundConfig = getBoxConfig();
363  tgBulletGround* ground = new tgBoxGround(groundConfig);
364  simulation->reset(ground);
365  }
366  // Flat with blocks
367  else if (i % nTypes == 2)
368  {
369  simulation->reset();
370  tgModel* obstacle = getBlocks();
371  simulation->addObstacle(obstacle);
372  }
373  }
374  // Avoid resetting twice on the last run
375  else if (i != nEpisodes - 1)
376  {
377  simulation->reset();
378  }
379 
380  }
381 }
382 
389 int main(int argc, char** argv)
390 {
391  std::cout << "AppQuadControlHierarchy" << std::endl;
392  AppQuadControlHierarchy app (argc, argv);
393 
394  if (app.setup())
395  app.run();
396 
397  //Teardown is handled by delete, so that should be automatic
398  return 0;
399 }
400 
401 
void addObstacle(tgModel *pObstacle)
void addModel(tgModel *pModel)
int main(int argc, char **argv)
void run() const
Contains the definition function main() for the Multiple terrains app, used here for control of a qua...
void attach(tgObserver< T > *pObserver)
Definition: tgSubject.h:91