NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
AppTSGoal.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 
27 #include "AppTSGoal.h"
28 
29 AppTSGoal::AppTSGoal(int argc, char** argv)
30 {
31  bSetup = false;
32  use_graphics = false;
33  add_controller = true;
34  add_blocks = false;
35  add_hills = false;
36  all_terrain = false;
37  timestep_physics = 1.0f/1000.0f;
38  timestep_graphics = 1.0f/60.0f;
39  nEpisodes = 1;
40  nSteps = 60000;
41  nSegments = 6;
42  nTypes = 3;
43 
44  startX = 0;
45  startY = 20;
46  startZ = 0;
47  startAngle = 0;
48 
49  suffix = "default";
50 
51  handleOptions(argc, argv);
52 }
53 
55 {
56  // First create the world
57  const double scale = 100;
58  world = createWorld();
59 
60  // Second create the view
61  if (use_graphics)
62  view = createGraphicsView(world); // For visual experimenting on one tensegrity
63  else
64  view = createView(world); // For running multiple episodes
65 
66  // Third create the simulation
67  simulation = new tgSimulation(*view);
68 
69  // Fourth create the models with their controllers and add the models to the
70  // simulation
72  TetraSpineGoal* myModel =
73  new TetraSpineGoal(nSegments, 0.0, scale);
74 
75  // Fifth create the controllers, attach to model
76  if (add_controller)
77  {
78 
79  const int segmentSpan = 3;
80  const int numMuscles = 6;
81  const int numParams = 2;
82  const int segNumber = 5; // 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  const double tensionFeedback = 1000.0;
106 #if (0) // Switch for .nnw or JSON based methods
107  JSONGoalControl::Config control_config(segmentSpan,
108  numMuscles,
109  numMuscles,
110  numParams,
111  segNumber,
112  controlTime,
113  lowAmplitude,
114  highAmplitude,
115  lowPhase,
116  highPhase,
117  kt,
118  kp,
119  kv,
120  def,
121  cl,
122  lf,
123  hf,
124  ffMin,
125  ffMax,
126  afMin,
127  afMax,
128  pfMin,
129  pfMax,
130  tensionFeedback
131  );
132 
134  JSONGoalControl* const myControl =
135  new JSONGoalControl(control_config, suffix, "bmirletz/Tetra_Goal/");
136 
137 #else
138 
139  JSONFeedbackControl::Config control_config(segmentSpan,
140  numMuscles,
141  numMuscles,
142  numParams,
143  segNumber,
144  controlTime,
145  lowAmplitude,
146  highAmplitude,
147  lowPhase,
148  highPhase,
149  kt,
150  kp,
151  kv,
152  def,
153  cl,
154  lf,
155  hf,
156  ffMin,
157  ffMax,
158  afMin,
159  afMax,
160  pfMin,
161  pfMax);
163  JSONFeedbackControl * const myControl =
164  new JSONFeedbackControl(control_config, suffix, "bmirletz/Tetra_Goal/");
165 
166 #endif
167 
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 AppTSGoal::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  ("learning_controller,l", po::value<std::string>(&suffix), "Which learned controller to write to or use. Default = default")
205  ;
206 
207  po::variables_map vm;
208  po::store(po::parse_command_line(argc, argv, desc), vm);
209 
210  if (vm.count("help"))
211  {
212  std::cout << desc << "\n";
213  exit(0);
214  }
215 
216  po::notify(vm);
217 
218  if (vm.count("phys_time"))
219  {
220  timestep_physics = 1/vm["phys_time"].as<double>();
221  std::cout << "Physics timestep set to: " << timestep_physics << " seconds.\n";
222  }
223 
224  if (vm.count("graph_time"))
225  {
226  timestep_graphics = 1/vm["graph_time"].as<double>();
227  std::cout << "Graphics timestep set to: " << timestep_graphics << " seconds.\n";
228  }
229 }
230 
231 const tgHillyGround::Config AppTSGoal::getHillyConfig()
232 {
233  btVector3 eulerAngles = btVector3(0.0, 0.0, 0.0);
234  btScalar friction = 0.5;
235  btScalar restitution = 0.0;
236  // Size doesn't affect hilly terrain
237  btVector3 size = btVector3(0.0, 0.1, 0.0);
238  btVector3 origin = btVector3(0.0, 0.0, 0.0);
239  size_t nx = 180;
240  size_t ny = 180;
241  double margin = 0.5;
242  double triangleSize = 4.0;
243  double waveHeight = 2.0;
244  double offset = 0.0;
245  const tgHillyGround::Config hillGroundConfig(eulerAngles, friction, restitution,
246  size, origin, nx, ny, margin, triangleSize,
247  waveHeight, offset);
248  return hillGroundConfig;
249 }
250 
251 const tgBoxGround::Config AppTSGoal::getBoxConfig()
252 {
253  const double yaw = 0.0;
254  const double pitch = 0.0;
255  const double roll = 0.0;
256  const double friction = 0.5;
257  const double restitution = 0.0;
258  const btVector3 size(1000.0, 1.5, 1000.0);
259 
260  const tgBoxGround::Config groundConfig(btVector3(yaw, pitch, roll),
261  friction,
262  restitution,
263  size );
264 
265  return groundConfig;
266 }
267 
268 tgModel* AppTSGoal::getBlocks()
269 {
270  // Room to add a config
271  tgBlockField* myObstacle = new tgBlockField();
272  return myObstacle;
273 }
274 
275 tgWorld* AppTSGoal::createWorld()
276 {
277  const tgWorld::Config config(
278  981 // gravity, cm/sec^2
279  );
280 
281  tgBulletGround* ground;
282 
283  if (add_hills)
284  {
285  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
286  ground = new tgHillyGround(hillGroundConfig);
287  }
288  else
289  {
290  const tgBoxGround::Config groundConfig = getBoxConfig();
291  ground = new tgBoxGround(groundConfig);
292  }
293 
294  return new tgWorld(config, ground);
295 }
296 
297 tgSimViewGraphics *AppTSGoal::createGraphicsView(tgWorld *world)
298 {
299  return new tgSimViewGraphics(*world, timestep_physics, timestep_graphics);
300 }
301 
302 tgSimView *AppTSGoal::createView(tgWorld *world)
303 {
304  return new tgSimView(*world, timestep_physics, timestep_graphics);
305 }
306 
308 {
309  if (!bSetup)
310  {
311  setup();
312  }
313 
314  if (use_graphics)
315  {
316  // Run until the user stops
317  simulation->run();
318  }
319  else
320  {
321  // or run for a specific number of steps
322  simulate(simulation);
323  }
324 
326  delete simulation;
327  delete view;
328  delete world;
329 
330  return true;
331 }
332 
333 void AppTSGoal::simulate(tgSimulation *simulation)
334 {
335  for (int i=0; i<nEpisodes; i++) {
336  fprintf(stderr,"Episode %d\n", i);
337  try
338  {
339  simulation->run(nSteps);
340  }
341  catch (std::runtime_error e)
342  {
343  // Nothing to do here, score will be set to -1
344  }
345 
346  // Don't change the terrain before the last episode to avoid leaks
347  if (i != nEpisodes - 1)
348  {
349 
350  if (all_terrain)
351  {
352  // Next run has Hills
353  if (i % nTypes == 0)
354  {
355 
356  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
357  tgBulletGround* ground = new tgHillyGround(hillGroundConfig);
358  simulation->reset(ground);
359  }
360  // Flat
361  else if (i % nTypes == 1)
362  {
363  const tgBoxGround::Config groundConfig = getBoxConfig();
364  tgBulletGround* ground = new tgBoxGround(groundConfig);
365  simulation->reset(ground);
366  }
367  // Flat with blocks
368  else if (i % nTypes == 2)
369  {
370  simulation->reset();
371  tgModel* obstacle = getBlocks();
372  simulation->addObstacle(obstacle);
373  }
374  }
375  else if(add_blocks)
376  {
377  simulation->reset();
378  tgModel* obstacle = getBlocks();
379  simulation->addObstacle(obstacle);
380  }
381  // Avoid resetting twice on the last run
382  else
383  {
384  simulation->reset();
385  }
386  }
387  }
388 }
389 
396 int main(int argc, char** argv)
397 {
398  std::cout << "AppTSGoal" << std::endl;
399  AppTSGoal app (argc, argv);
400 
401  if (app.setup())
402  app.run();
403 
404  //Teardown is handled by delete, so that should be automatic
405  return 0;
406 }
407 
int main(int argc, char **argv)
Definition: AppTSGoal.cpp:396
void addObstacle(tgModel *pObstacle)
void addModel(tgModel *pModel)
bool setup()
Definition: AppTSGoal.cpp:54
bool run()
Definition: AppTSGoal.cpp:307
void run() const
void attach(tgObserver< T > *pObserver)
Definition: tgSubject.h:91