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