NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
pidTestRig.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 
25 // This module
26 #include "pidTestRig.h"
27 // This library
30 #include "examples/learningSpines/tgSCASineControl.h"
33 
34 
35 #include "core/tgBasicActuator.h"
37 #include "core/tgRod.h"
38 #include "tgcreator/tgBuildSpec.h"
40 #include "tgcreator/tgRodInfo.h"
41 #include "tgcreator/tgStructure.h"
43 // The Bullet Physics library
44 #include "LinearMath/btVector3.h"
45 // The C++ Standard Library
46 #include <stdexcept>
47 
52 namespace
53 {
58  const struct Config
59  {
60  double density;
61  double radius;
62  double stiffness;
63  double damping;
64  double triangle_length;
65  double triangle_height;
66  double prism_height;
67  double pretension;
68  } c =
69  {
70  2, // density (mass / length^3)
71  0.31, // radius (length)
72  1000.0, // stiffness (mass / sec^2)
73  0.0, // damping (mass / sec)
74  10.0, // triangle_length (length)
75  10.0, // triangle_height (length)
76  20.0, // prism_height (length)
77  0.05 // Pretension (percentage)
78  };
79 } // namespace
80 
81 pidTestRig::pidTestRig(bool kinematic) :
82 tgModel(),
83 useKinematic(kinematic),
84 p_ipc(NULL)
85 {
86 }
87 
89 {
90  for(std::size_t i = 0; i < m_tgSCASineControllers.size(); i++)
91  {
92  delete m_tgSCASineControllers[i];
93  }
94  m_tgSCASineControllers.clear();
95  delete p_ipc;
96 }
97 
98 void pidTestRig::addNodes(tgStructure& s)
99 {
100  s.addNode(0.0, -1.0, 0.0); // 0
101  s.addNode(0.0, 0.0, 0.0); // 1
102  s.addNode( 0.0, 10.0, 0.0); // 2
103  s.addNode(0.0, 11.0, 0.0); // 3
104 
105 }
106 
107 void pidTestRig::addRods(tgStructure& s)
108 {
109  s.addPair( 0, 1, "rod");
110  s.addPair( 2, 3, "rod2");
111 }
112 
113 void pidTestRig::addMuscles(tgStructure& s)
114 {
115 
116  s.addPair(1, 2, "muscle");
117 
118 }
119 
120 void pidTestRig::setupControl()
121 {
122  // Ensure this is called at correct time in setup
123  assert(allMuscles.size() > 0);
124 
125  const double controlStep = 0.01;
126  tgPIDController::Config pidConfig(100.0, 0.0, 10.0, true);
127  tgImpedanceController* p_ipc = new tgImpedanceController(200.0, 100.0, 100.0);
128  const double amplitude = 0.0;
129  const double frequency = 0.2;
130  const double phase = 0.0;
131  const double offset = 0.0;
132  double length = 5.0;
133 
134  for (std::size_t i = 0; i < allMuscles.size(); i++)
135  {
136  tgKinematicActuator* kinString = tgCast::cast<tgSpringCableActuator, tgKinematicActuator>(allMuscles[i]);
137  assert(kinString);
138 
139  tgSCASineControl* sineController = new tgSCASineControl(controlStep,
140  p_ipc,
141  pidConfig,
142  amplitude,
143  frequency,
144  phase,
145  offset,
146  length);
147  kinString->attach(sineController);
148 
149  m_tgSCASineControllers.push_back(sineController);
150  }
151 }
152 
154 {
155  // Define the configurations of the rods and strings
156  const tgRod::Config rodConfig(c.radius, c.density);
157  const tgRod::Config rodConfig2(c.radius, 0.0);
158  // String config needs to be inside boolean switch
159 
160  // Create a structure that will hold the details of this model
161  tgStructure s;
162 
163  // Add nodes to the structure
164  addNodes(s);
165 
166  // Add rods to the structure
167  addRods(s);
168 
169  // Add muscles to the structure
170  addMuscles(s);
171 
172  // Move the structure so it doesn't start in the ground
173  s.move(btVector3(0, 5, 0));
174 
175  // Create the build spec that uses tags to turn the structure into a real model
176  // The top rod will be massless - fixed in space
177  tgBuildSpec spec;
178  spec.addBuilder("rod", new tgRodInfo(rodConfig));
179  spec.addBuilder("rod2", new tgRodInfo(rodConfig2));
180 
181  if (useKinematic)
182  {
183  // Stiffness, damping, pretension, radius, friction
184  const tgKinematicActuator::Config muscleConfig(c.stiffness, c.damping, 0.0, 1.0, 0.0, 1.0, true, true);
185  spec.addBuilder("muscle", new tgKinematicActuatorInfo(muscleConfig));
186  }
187  else
188  {
189  const tgBasicActuator::Config muscleConfig(c.stiffness, c.damping);
190  spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));
191  }
192 
193  // Create your structureInfo
194  tgStructureInfo structureInfo(s, spec);
195 
196  // Use the structureInfo to build ourselves
197  structureInfo.buildInto(*this, world);
198 
199  // We could now use tgCast::filter or similar to pull out the
200  // models (e.g. muscles) that we want to control.
201  allMuscles = tgCast::filter<tgModel, tgSpringCableActuator> (getDescendants());
202 
203  if (useKinematic)
204  {
205  setupControl();
206  }
207  // Notify controllers that setup has finished.
208  notifySetup();
209 
210  // Actually setup the children
211  tgModel::setup(world);
212 
213  std::vector<tgBaseRigid*> myRigids = tgCast::filter<tgModel, tgBaseRigid> (getDescendants());
214 #if (1)
215  for (int i =0; i < myRigids.size(); i++)
216  {
217  std::cout << myRigids[i]->mass() << " " <<myRigids[i]->getPRigidBody() << std::endl;
218  }
219 #endif
220 
221  std::cout << "Starting Length: " << allMuscles[0]->getCurrentLength() << std::endl;
222  std::cout << "Starting Rest Length: " << allMuscles[0]->getRestLength() << std::endl;
223 
224  totalTime = 0.0;
225  reached = false;
226 }
227 
228 void pidTestRig::step(double dt)
229 {
230  // Precondition
231  if (dt <= 0.0)
232  {
233  throw std::invalid_argument("dt is not positive");
234  }
235  else
236  {
237  totalTime += dt;
238  // Notify observers (controllers) of the step so that they can take action
239  notifyStep(dt);
240  tgModel::step(dt); // Step any children
241 
242  if (allMuscles[0]->getRestLength() <= 5.0 && !reached)
243  {
244  std::cout << "Rest length below 5.0 at: " << totalTime << std::endl;
245  reached = true;
246  }
247  //std::cout << allMuscles[0]->getRestLength() << std::endl;
248  }
249 
250 }
251 
253 {
254  // Example: m_rod->getRigidBody()->dosomething()...
255  tgModel::onVisit(r);
256 }
257 
258 const std::vector<tgSpringCableActuator*>& pidTestRig::getAllMuscles() const
259 {
260  return allMuscles;
261 }
262 
264 {
265  notifyTeardown();
266 
267  std::vector<tgSpringCableActuator* > tmpStrings = this->getAllMuscles();
268 
269  tgSpringCableActuator::SpringCableActuatorHistory stringHist = tmpStrings[0]->getHistory();
270 
271  std::size_t histSize = stringHist.tensionHistory.size();
272 
273  double dt = totalTime / (double)histSize;
274 
275  double totalEnergySpent = 0;
276 
277 
278  std::cout << "Ending Length: " << allMuscles[0]->getCurrentLength() << std::endl;
279  std::cout << "Ending Rest Length: " << allMuscles[0]->getRestLength() << std::endl;
280  std::cout << "Ending Tension: " <<allMuscles[0]->getTension() << std::endl;
281 
282  std::vector<tgBaseRigid*> myRigids = tgCast::filter<tgModel, tgBaseRigid> (getDescendants());
283 
284  btRigidBody* body0 = myRigids[0]->getPRigidBody();
285 
286  btVector3 velocity = body0->getLinearVelocity();
287 
288  std::cout << "Final Velocity: " << velocity.length() << std::endl;
289 
290  #if (0)
291 
292  for(std::size_t j=1; j<stringHist.tensionHistory.size(); j++)
293  {
294  const double previousTension = stringHist.tensionHistory[j-1];
295  const double previousLength = stringHist.restLengths[j-1];
296  const double currentLength = stringHist.restLengths[j];
297  //TODO: examine this assumption - free spinning motor may require more power
298  double motorSpeed = (currentLength-previousLength);
299  if(motorSpeed > 0) // Vestigial code
300  motorSpeed = 0;
301  const double workDone = previousTension * motorSpeed;
302  totalEnergySpent += workDone;
303  }
304 
305  #else
306  for(std::size_t j=0; j < histSize; j++)
307  {
308  const double previousTension = stringHist.tensionHistory[j];
309  double motorSpeed = stringHist.lastVelocities[j];
310  // Integrating power over time
311  const double workDone = previousTension * motorSpeed * dt;
312  totalEnergySpent += workDone;
313  }
314  #endif
315 
316  std::cout << "Motor Speed " << stringHist.lastVelocities[histSize - 1] << std::endl;
317 
318  std::cout << "Energy Spent: " << totalEnergySpent << std::endl;
319 
321 }
Contains the definition of class ImpedanceControl. $Id$.
virtual void teardown()
Definition: tgModel.cpp:68
pidTestRig(bool kinematic=true)
Definition: pidTestRig.cpp:81
virtual void setup(tgWorld &world)
Definition: tgModel.cpp:57
Definition of class tgRodInfo.
virtual ~pidTestRig()
Definition: pidTestRig.cpp:88
const std::vector< tgSpringCableActuator * > & getAllMuscles() const
Definition: pidTestRig.cpp:258
virtual void onVisit(tgModelVisitor &r)
Definition: pidTestRig.cpp:252
virtual void step(double dt)
Definition: tgModel.cpp:84
Definition of class tgBasicActuatorInfo.
virtual void onVisit(const tgModelVisitor &r) const
Definition: tgModel.cpp:107
void addPair(int fromNodeIdx, int toNodeIdx, std::string tags="")
Definition: tgStructure.cpp:80
Contains the definition of abstract base class tgSpringCableActuator. Assumes that the string is line...
virtual void teardown()
Definition: pidTestRig.cpp:263
virtual void setup(tgWorld &world)
Definition: pidTestRig.cpp:153
Contains the definition of class tgBasicActuator.
Definition of class tgStructure.
Definition of class tgStructureInfo.
Defines a 3 strut 9 string tensegrity model.
Contains the definition of class tgKinematicActuator.
Definition of class tgKinematicActuatorInfo.
virtual void step(double dt)
Definition: pidTestRig.cpp:228
Contains the definition of class tgRod.
void attach(tgObserver< T > *pObserver)
Definition: tgSubject.h:91
Definition of class tgBuildSpec.
Definition of the tgPIDController class.
void notifyStep(double dt)
std::vector< tgModel * > getDescendants() const
Definition: tgModel.cpp:170
void buildInto(tgModel &model, tgWorld &world)
void addNode(double x, double y, double z, std::string tags="")
Definition: tgStructure.cpp:70