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