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