NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
AppQuadSimpleActuation.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 "AppQuadSimpleActuation.h"
29 #include "dev/btietz/JSONTests/tgCPGJSONLogger.h"
30 #include "helpers/FileHelpers.h"
31 #include <json/json.h>
32 
33 AppQuadSimpleActuation::AppQuadSimpleActuation(int argc, char** argv)
34 {
35  bSetup = false;
36  use_graphics = false;
37  add_controller = true;
38  add_blocks = false;
39  add_hills = false;
40  all_terrain = false;
41  timestep_physics = 1.0f/1000.0f;
42  timestep_graphics = 1.0f/60.0f;
43  nEpisodes = 1;
44  nSteps = 60000;
45  nSegments = 7;
46  nTypes = 3;
47 
48  startX = 0;
49  startY = 40; //May need adjustment
50  startZ = 0;
51  startAngle = 0;
52 
53  suffix = "default";
54  lowerPath = "default";
55 
56  handleOptions(argc, argv);
57 }
58 
60 {
61  // First create the world
62  world = createWorld();
63 
64  // Second create the view
65  if (use_graphics)
66  view = createGraphicsView(world); // For visual experimenting on one tensegrity
67  else
68  view = createView(world); // For running multiple episodes
69 
70  // Third create the simulation
71  simulation = new tgSimulation(*view);
72 
73  // Fourth create the models with their controllers and add the models to the
74  // simulation
76  //FlemonsSpineModelContact* myModel =
77  //new FlemonsSpineModelContact(nSegments);
78 
79  //Parameters for the structure:
80  const int segments = 7;
81  const int hips = 4;
82  const int legs = 4;
83  const int feet = 4;
84 
85  BigPuppySymmetricSpiral2* myModel = new BigPuppySymmetricSpiral2(segments, hips, legs, feet);
86 
87  // Fifth create the controllers, attach to model
88  if (add_controller)
89  {
90  Json::Value root;
91  Json::Reader reader;
92 
93  std::string resourcePath = "bgigous/AppQuadSimpleActuation/";
94  std::string controlFilePath = FileHelpers::getResourcePath(resourcePath);
95  std::string controlFilename = controlFilePath + suffix;
96 
97  bool parsingSuccessful = reader.parse( FileHelpers::getFileString(controlFilename.c_str()), root );
98  if ( !parsingSuccessful )
99  {
100  // report to the user the failure and their locations in the document.
101  std::cout << "Failed to parse configuration\n"
102  << reader.getFormattedErrorMessages();
103  throw std::invalid_argument("Bad filename for JSON, check that resource path exists");
104  }
105  // Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
106  // such member.
107  Json::Value impedenceVals = root.get("impedenceVals", "UTF-8");
108  impedenceVals = impedenceVals.get("params", "UTF-8");
109 
110  // Keep drilling if necessary
111  if (impedenceVals[0].isArray())
112  {
113  impedenceVals = impedenceVals[0];
114  }
115 
116  const double impedanceMax = 2000.0;
117 
118  const int segmentSpan = 3; //Not sure what this will be for mine!
119  const int numMuscles = 16; //This may be ok, but confirm.
120  const int numParams = 2;
121  const int segNumber = 0; // For learning results
122  const double controlTime = .01;
123  const double lowPhase = -1*M_PI;
124  const double highPhase = M_PI;
125  const double lowAmplitude = 0.0;
126  const double highAmplitude = 300.0;
127  //const double kt = 0.0; //May need to retune kt, kp, and kv
128  //const double kp = 2000.0;
129  //const double kv = 200.0;
130  int j = 0;
131  const double kt = impedanceMax * (impedenceVals.get(j, 0.0)).asDouble();
132  const double kp = impedanceMax * (impedenceVals.get(1, 0.0)).asDouble();
133  const double kv = impedanceMax * (impedenceVals.get(2, 0.0)).asDouble();
134  const bool def = false;
135 
136  // Overridden by def being true
137  const double cl = 10.0;
138  const double lf = 0.0;
139  const double hf = 1.5;
140 
141  // Feedback parameters... may need to retune
142  const double ffMin = 0.0;
143  const double ffMax = 1;
144  const double afMin = 0.0;
145  const double afMax = 200; //200
146  const double pfMin = -0.5;//-0.5;
147  const double pfMax = 6.28; //6.28;
148 
149  const double maxH = 300.0;
150  const double minH = 1.0;
151 
152  JSONQuadFeedbackControl::Config control_config(segmentSpan,
153  numMuscles,
154  numMuscles,
155  numParams,
156  segNumber,
157  controlTime,
158  lowAmplitude,
159  highAmplitude,
160  lowPhase,
161  highPhase,
162  kt,
163  kp,
164  kv,
165  def,
166  cl,
167  lf,
168  hf,
169  ffMin,
170  ffMax,
171  afMin,
172  afMax,
173  pfMin,
174  pfMax,
175  maxH,
176  minH);
178  myControl =
179  new JSONQuadFeedbackControl(control_config, suffix, lowerPath);
180 
181 #if (0)
182  tgCPGJSONLogger* const myLogger =
183  new tgCPGJSONLogger("logs/CPGValues.txt");
184 
185  myControl->attach(myLogger);
186 #endif
187  myModel->attach(myControl);
188  }
189 
190  // Sixth add model & controller to simulation
191  simulation->addModel(myModel);
192 
193  if (add_blocks)
194  {
195  tgModel* blockField = getBlocks();
196  simulation->addObstacle(blockField);
197  }
198 
199  bSetup = true;
200  return bSetup;
201 }
202 
203 void AppQuadSimpleActuation::handleOptions(int argc, char **argv)
204 {
205  // Declare the supported options.
206  po::options_description desc("Allowed options");
207  desc.add_options()
208  ("help,h", "produce help message")
209  ("graphics,G", po::value<bool>(&use_graphics), "Test using graphical view")
210  ("controller,c", po::value<bool>(&add_controller), "Attach the controller to the model.")
211  ("blocks,b", po::value<bool>(&add_blocks)->implicit_value(false), "Add a block field as obstacles.")
212  ("hills,H", po::value<bool>(&add_hills)->implicit_value(false), "Use hilly terrain.")
213  ("all_terrain,A", po::value<bool>(&all_terrain)->implicit_value(false), "Alternate through terrain types. Only works with graphics off")
214  ("phys_time,p", po::value<double>(), "Physics timestep value (Hz). Default=1000")
215  ("graph_time,g", po::value<double>(), "Graphics timestep value a.k.a. render rate (Hz). Default = 60")
216  ("episodes,e", po::value<int>(&nEpisodes), "Number of episodes to run. Default=1")
217  ("steps,s", po::value<int>(&nSteps), "Number of steps per episode to run. Default=60K (60 seconds)")
218  ("segments,S", po::value<int>(&nSegments), "Number of segments in the tensegrity spine. Default=6")
219  ("start_x,x", po::value<double>(&startX), "X Coordinate of starting position for robot. Default = 0")
220  ("start_y,y", po::value<double>(&startY), "Y Coordinate of starting position for robot. Default = 20")
221  ("start_z,z", po::value<double>(&startZ), "Z Coordinate of starting position for robot. Default = 0")
222  ("angle,a", po::value<double>(&startAngle), "Angle of starting rotation for robot. Degrees. Default = 0")
223  ("goal_angle,B", po::value<double>(&goalAngle), "Angle of starting rotation for goal box. Degrees. Default = 0")
224  ("learning_controller,l", po::value<std::string>(&suffix), "Which learned controller to write to or use. Default = default")
225  ("lower_path,P", po::value<std::string>(&lowerPath), "Which resources folder in which you want to store controllers. Default = default")
226  ;
227 
228  po::variables_map vm;
229  po::store(po::parse_command_line(argc, argv, desc), vm);
230 
231  if (vm.count("help"))
232  {
233  std::cout << desc << "\n";
234  exit(0);
235  }
236 
237  po::notify(vm);
238 
239  if (vm.count("phys_time"))
240  {
241  timestep_physics = 1/vm["phys_time"].as<double>();
242  std::cout << "Physics timestep set to: " << timestep_physics << " seconds.\n";
243  }
244 
245  if (vm.count("graph_time"))
246  {
247  timestep_graphics = 1/vm["graph_time"].as<double>();
248  std::cout << "Graphics timestep set to: " << timestep_graphics << " seconds.\n";
249  }
250 }
251 
252 const tgHillyGround::Config AppQuadSimpleActuation::getHillyConfig()
253 {
254  btVector3 eulerAngles = btVector3(0.0, 0.0, 0.0);
255  btScalar friction = 0.5;
256  btScalar restitution = 0.0;
257  // Size doesn't affect hilly terrain
258  btVector3 size = btVector3(0.0, 0.1, 0.0);
259  btVector3 origin = btVector3(0.0, 0.0, 0.0);
260  size_t nx = 100;
261  size_t ny = 100;
262  double margin = 0.5;
263  double triangleSize = 4.0;
264  double waveHeight = 2.0;
265  double offset = 0.0;
266  const tgHillyGround::Config hillGroundConfig(eulerAngles, friction, restitution,
267  size, origin, nx, ny, margin, triangleSize,
268  waveHeight, offset);
269  return hillGroundConfig;
270 }
271 
272 const tgBoxGround::Config AppQuadSimpleActuation::getBoxConfig()
273 {
274  const double yaw = 0.0;
275  const double pitch = 0.0;
276  const double roll = 0.0;
277  const double friction = 0.5;
278  const double restitution = 0.0;
279  const btVector3 size(1000.0, 1.5, 1000.0);
280 
281  const tgBoxGround::Config groundConfig(btVector3(yaw, pitch, roll),
282  friction,
283  restitution,
284  size );
285 
286  return groundConfig;
287 }
288 
289 tgModel* AppQuadSimpleActuation::getBlocks()
290 {
291  // Room to add a config
292  tgBlockField* myObstacle = new tgBlockField();
293  return myObstacle;
294 }
295 
296 tgWorld* AppQuadSimpleActuation::createWorld()
297 {
298  const tgWorld::Config config(
299  981 // gravity, cm/sec^2
300  );
301 
302  tgBulletGround* ground;
303 
304  if (add_hills)
305  {
306  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
307  ground = new tgHillyGround(hillGroundConfig);
308  }
309  else
310  {
311  const tgBoxGround::Config groundConfig = getBoxConfig();
312  ground = new tgBoxGround(groundConfig);
313  }
314 
315  return new tgWorld(config, ground);
316 }
317 
318 tgSimViewGraphics *AppQuadSimpleActuation::createGraphicsView(tgWorld *world)
319 {
320  return new tgSimViewGraphics(*world, timestep_physics, timestep_graphics);
321 }
322 
323 tgSimView *AppQuadSimpleActuation::createView(tgWorld *world)
324 {
325  return new tgSimView(*world, timestep_physics, timestep_graphics);
326 }
327 
329 {
330  if (!bSetup)
331  {
332  setup();
333  }
334 
335  if (use_graphics)
336  {
337  // Run until the user stops
338  simulation->run();
339  }
340  else
341  {
342  // or run for a specific number of steps
343  simulate(simulation);
344  }
345 
347  delete simulation;
348  delete view;
349  delete world;
350  delete myControl;
351 
352  return true;
353 }
354 
355 void AppQuadSimpleActuation::simulate(tgSimulation *simulation)
356 {
357  for (int i=0; i<nEpisodes; i++) {
358  fprintf(stderr,"Episode %d\n", i);
359  try
360  {
361  simulation->run(nSteps);
362  }
363  catch (std::runtime_error e)
364  {
365  // Nothing to do here, score will be set to -1
366  }
367 
368  // Don't change the terrain before the last episode to avoid leaks
369  if (all_terrain && i != nEpisodes - 1)
370  {
371  // Next run has Hills
372  if (i % nTypes == 0)
373  {
374 
375  const tgHillyGround::Config hillGroundConfig = getHillyConfig();
376  tgBulletGround* ground = new tgHillyGround(hillGroundConfig);
377  simulation->reset(ground);
378  }
379  // Flat
380  else if (i % nTypes == 1)
381  {
382  const tgBoxGround::Config groundConfig = getBoxConfig();
383  tgBulletGround* ground = new tgBoxGround(groundConfig);
384  simulation->reset(ground);
385  }
386  // Flat with blocks
387  else if (i % nTypes == 2)
388  {
389  simulation->reset();
390  tgModel* obstacle = getBlocks();
391  simulation->addObstacle(obstacle);
392  }
393  }
394  // Avoid resetting twice on the last run
395  else if (i != nEpisodes - 1)
396  {
397  simulation->reset();
398  }
399 
400  }
401 }
402 
409 int main(int argc, char** argv)
410 {
411  std::cout << "AppQuadSimpleActuation" << std::endl;
412  AppQuadSimpleActuation app (argc, argv);
413 
414  if (app.setup())
415  app.run();
416 
417  //Teardown is handled by delete, so that should be automatic
418  return 0;
419 }
420 
421 
void addObstacle(tgModel *pObstacle)
void addModel(tgModel *pModel)
A series of functions to assist with file input/output.
static std::string getResourcePath(std::string relPath)
Definition: FileHelpers.cpp:40
void run() const
int main(int argc, char **argv)
void attach(tgObserver< T > *pObserver)
Definition: tgSubject.h:91