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