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