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