NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
T6Model.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 
25 // This module
26 #include "T6Model.h"
27 // This library
28 #include "core/tgBasicActuator.h"
29 #include "core/tgRod.h"
30 #include "core/abstractMarker.h"
31 #include "tgcreator/tgBuildSpec.h"
33 #include "tgcreator/tgRodInfo.h"
34 #include "tgcreator/tgStructure.h"
36 // The Bullet Physics library
37 #include "LinearMath/btVector3.h"
38 // The C++ Standard Library
39 #include <stdexcept>
40 
41 /*
42  * helper arrays for node and rod numbering schema
43  */
44 /*returns the number of the rod for a given node */
45 const int rodNumbersPerNode[13]={0,0,1,1,2,2,3,3,4,4,5,5,6};
46 
47 /*returns the node that is at the other end of the given node */
48 const int otherEndOfTheRod[13]={6,7,8,4,3,11,0,1,2,10,9,5,12};
49 
50 /*returns the node that is at the parallel rod
51  * and at the same end of the given node
52  */
53 const int parallelNode[13]={1,0,5,9,10,2,7,6,11,3,4,8,12};
54 
55 namespace
56 {
57  // Note: This current model of the SUPERball rod is 1.5m long by 4.5cm (0.045m) radius,
58  // which is 1.684m*pi*(0.040m)^2 = 0.008545132m^3.
59  // For SUPERball v1.5, mass = 3.5kg per strut, which density [kg/m^3] comes out to:
60  // density = 3.45kg/0.008545132m^3 = 403.738642402kg/m^3 = 0.403738642402 kg/dm^3
61 
62  // see tgBaseString.h for a descripton of some of these rod parameters
63  // (specifically, those related to the motor moving the strings.)
64  // NOTE that any parameter that depends on units of length will scale
65  // with the current gravity scaling. E.g., with gravity as 98.1
66  // Thus,
67  // Rod Length = 17.00
68  // Rod Radius = 0.40
69  // density = 0.40374 (length is cubed, so decimal moves 3 places)
70 
71  // similarly, frictional parameters are for the tgRod objects.
72  const struct Config
73  {
74  double density;
75  double radius;
76  double stiffness_passive;
77  double stiffness_active;
78  double damping;
79  double rod_length;
80  double rod_space;
81  double friction;
82  double rollFriction;
83  double restitution;
84  double pretension;
85  bool hist;
86  double maxTens;
87  double targetVelocity;
88  } c =
89  {
90  0.40374, // density (kg / length^3)
91  0.40, // radius (length)
92  998.25, // stiffness_passive (kg / sec^2)
93  3152.36, // stiffness_active (kg / sec^2)
94  50.0, // damping (kg / sec)
95  17.00, // rod_length (length)
96  17.00/4, // rod_space (length)
97  0.99, // friction (unitless)
98  0.01, // rollFriction (unitless)
99  0.0, // restitution (?)
100  0.0, // pretension (force)
101  true, // History logging (boolean)
102  100000, // maxTens
103  10000 // targetVelocity
104 #if (0)
105  20000 // maxAcc
106 #endif
107  };
108 } // namespace
109 
111 {
112 }
113 
115 {
116 }
117 
118 void T6Model::addNodes(tgStructure& s)
119 {
120  const double half_length = c.rod_length / 2;
121 
122  nodePositions.push_back(btVector3(-c.rod_space, -half_length, 0)); // 0
123  nodePositions.push_back(btVector3(-c.rod_space, half_length, 0)); // 1
124  nodePositions.push_back(btVector3( c.rod_space, -half_length, 0)); // 2
125  nodePositions.push_back(btVector3( c.rod_space, half_length, 0)); // 3
126  nodePositions.push_back(btVector3(0, -c.rod_space, -half_length)); // 4
127  nodePositions.push_back(btVector3(0, -c.rod_space, half_length)); // 5
128  nodePositions.push_back(btVector3(0, c.rod_space, -half_length)); // 6
129  nodePositions.push_back(btVector3(0, c.rod_space, half_length)); // 7
130  nodePositions.push_back(btVector3(-half_length, 0, c.rod_space)); // 8
131  nodePositions.push_back(btVector3( half_length, 0, c.rod_space)); // 9
132  nodePositions.push_back(btVector3(-half_length, 0, -c.rod_space)); // 10
133  nodePositions.push_back(btVector3( half_length, 0, -c.rod_space)); // 11
134 
135  for(int i=0;i<nodePositions.size();i++)
136  {
137  s.addNode(nodePositions[i][0],nodePositions[i][1],nodePositions[i][2]);
138  }
139 }
140 
141 void T6Model::addRods(tgStructure& s)
142 {
143  s.addPair( 0, 1, "rod");
144  s.addPair( 2, 3, "rod");
145  s.addPair( 4, 5, "rod");
146  s.addPair( 6, 7, "rod");
147  s.addPair( 8, 9, "rod");
148  s.addPair(10, 11, "rod");
149 }
150 
151 void T6Model::addMarkers(tgStructure &s) {
152  const int nNodes = 12; // 2*nRods
153  std::vector <tgRod*> rods=find<tgRod>("rod");
154 
155  for(int i=0;i<nNodes;i++) {
156  const btRigidBody* bt = rods[rodNumbersPerNode[i]]->getPRigidBody();
157  btTransform inverseTransform = bt->getWorldTransform().inverse();
158  btVector3 pos = inverseTransform * (nodePositions[i]);
159  abstractMarker tmp=abstractMarker(bt,pos,btVector3(0.08*i,1.0 - 0.08*i,.0),i);
160  this->addMarker(tmp);
161  }
162 }
163 
164 void T6Model::addMuscles(tgStructure& s)
165 {
166  // Added ability to have two muscles in a structure.
167  // Configuration currently is random, at the moment [27 June 2014]
168  s.addPair(0, 4, "muscle_active");
169  s.addPair(0, 5, "muscle_passive");
170  s.addPair(0, 8, "muscle_active");
171  s.addPair(0, 10, "muscle_passive");
172 
173  s.addPair(1, 6, "muscle_active");
174  s.addPair(1, 7, "muscle_passive");
175  s.addPair(1, 8, "muscle_passive");
176  s.addPair(1, 10, "muscle_active");
177 
178  s.addPair(2, 4, "muscle_passive");
179  s.addPair(2, 5, "muscle_active");
180  s.addPair(2, 9, "muscle_active");
181  s.addPair(2, 11, "muscle_passive");
182 
183  s.addPair(3, 7, "muscle_active");
184  s.addPair(3, 6, "muscle_passive");
185  s.addPair(3, 9, "muscle_passive");
186  s.addPair(3, 11, "muscle_active");
187 
188  s.addPair(4, 10, "muscle_active");
189  s.addPair(4, 11, "muscle_passive");
190 
191  s.addPair(5, 8, "muscle_active");
192  s.addPair(5, 9, "muscle_passive");
193 
194  s.addPair(6, 10, "muscle_passive");
195  s.addPair(6, 11, "muscle_active");
196 
197  s.addPair(7, 8, "muscle_passive");
198  s.addPair(7, 9, "muscle_active");
199 
200 }
201 
202 void T6Model::setup(tgWorld& world)
203 {
204 
205  const tgRod::Config rodConfig(c.radius, c.density, c.friction,
206  c.rollFriction, c.restitution);
207 
208  tgBasicActuator::Config muscleConfig_passive(c.stiffness_passive, c.damping, c.pretension, c.hist,
209  c.maxTens, c.targetVelocity);
210 
211  tgBasicActuator::Config muscleConfig_active(c.stiffness_active, c.damping, c.pretension, c.hist,
212  c.maxTens, c.targetVelocity);
213 
214  // Start creating the structure
215  tgStructure s;
216  addNodes(s);
217  addRods(s);
218  addMuscles(s);
219  s.move(btVector3(0, 10, 0));
220 
221  // Add a rotation. This is needed if the ground slopes too much,
222  // otherwise glitches put a rod below the ground.
223  btVector3 rotationPoint = btVector3(0, 0, 0); // origin
224  btVector3 rotationAxis = btVector3(0, 1, 0); // y-axis
225  double rotationAngle = M_PI/2;
226  s.addRotation(rotationPoint, rotationAxis, rotationAngle);
227 
228  // Create the build spec that uses tags to turn the structure into a real model
229  tgBuildSpec spec;
230  spec.addBuilder("rod", new tgRodInfo(rodConfig));
231  spec.addBuilder("muscle_passive", new tgBasicActuatorInfo(muscleConfig_passive));
232  spec.addBuilder("muscle_active", new tgBasicActuatorInfo(muscleConfig_active));
233 
234  // Create your structureInfo
235  tgStructureInfo structureInfo(s, spec);
236 
237  // Use the structureInfo to build ourselves
238  structureInfo.buildInto(*this, world);
239 
240  // We could now use tgCast::filter or similar to pull out the
241  // models (e.g. muscles) that we want to control.
242  allMuscles = tgCast::filter<tgModel, tgBasicActuator> (getDescendants());
243  // Not really sure how to use the find() function in tgModel.h
244  passiveMuscles = tgCast::find<tgModel, tgBasicActuator>(tgTagSearch("muscle_passive"), getDescendants());
245  activeMuscles = tgCast::find<tgModel, tgBasicActuator>(tgTagSearch("muscle_active"), getDescendants());
246 
247  // call the onSetup methods of all observed things e.g. controllers
248  notifySetup();
249 
250  // Actually setup the children
251  tgModel::setup(world);
252 
253  //map the rods and add the markers to them
254  addMarkers(s);
255 
256  btVector3 location(0.0,28.0,0); // Start above ground (positive y)
257  btVector3 rotation(0.0,0.6,0.8);
258  btVector3 speed(0,0,0);
259  this->moveModel(location,rotation,speed);
260 }
261 
262 void T6Model::step(double dt)
263 {
264  // Precondition
265  if (dt <= 0.0)
266  {
267  throw std::invalid_argument("dt is not positive");
268  }
269  else
270  {
271  // Notify observers (controllers) of the step so that they can take action
272  notifyStep(dt);
273  tgModel::step(dt); // Step any children
274  }
275 }
276 
278 {
279  tgModel::onVisit(r);
280 }
281 
282 // Return the center of mass of this model
283 // Pre-condition: This model has 6 rods
284 std::vector<double> T6Model::getBallCOM() {
285  std::vector <tgRod*> rods = find<tgRod>("rod");
286  assert(!rods.empty());
287 
288  btVector3 ballCenterOfMass(0, 0, 0);
289  double ballMass = 0.0;
290  for (std::size_t i = 0; i < rods.size(); i++) {
291  const tgRod* const rod = rods[i];
292  assert(rod != NULL);
293  const double rodMass = rod->mass();
294  const btVector3 rodCenterOfMass = rod->centerOfMass();
295  ballCenterOfMass += rodCenterOfMass * rodMass;
296  ballMass += rodMass;
297  }
298 
299  assert(ballMass > 0.0);
300  ballCenterOfMass /= ballMass;
301 
302  // Copy to the result std::vector
303  std::vector<double> result(3);
304  for (size_t i = 0; i < 3; ++i) { result[i] = ballCenterOfMass[i]; }
305  //std::cout<<"COM: (" << result[0] << ", " << result[1] << ", " << result[2] << ")\n";
306 
307  return result;
308 }
309 
310 const std::vector<tgBasicActuator*>& T6Model::getAllMuscles() const
311 {
312  return allMuscles;
313 }
314 
315 const std::vector<tgBasicActuator*>& T6Model::getPassiveMuscles() const
316 {
317  return passiveMuscles;
318 }
319 
320 const std::vector<tgBasicActuator*>& T6Model::getActiveMuscles() const
321 {
322  return activeMuscles;
323 }
324 
325 const double T6Model::muscleRatio()
326 {
327  return (c.stiffness_passive/c.stiffness_active);
328  //return 2.5;
329 }
330 
331 void T6Model::teardown()
332 {
334 }
335 
336 void T6Model::moveModel(btVector3 positionVector,btVector3 rotationVector,btVector3 speedVector) {
337  std::vector<tgRod *> rods=find<tgRod>("rod");
338 
339  btQuaternion initialRotationQuat;
340  initialRotationQuat.setEuler(rotationVector[0],rotationVector[1],rotationVector[2]);
341  btTransform initialTransform;
342  initialTransform.setIdentity();
343  initialTransform.setRotation(initialRotationQuat);
344  initialTransform.setOrigin(positionVector);
345  for(int i=0;i<rods.size();i++) {
346  rods[i]->getPRigidBody()->setLinearVelocity(speedVector);
347  rods[i]->getPRigidBody()->setWorldTransform(initialTransform * rods[i]->getPRigidBody()->getWorldTransform());
348  }
349 }
virtual void teardown()
Definition: tgModel.cpp:68
virtual void setup(tgWorld &world)
Definition: tgModel.cpp:57
Definition of class tgRodInfo.
std::vector< double > getBallCOM()
Definition: T6Model.cpp:284
virtual void step(double dt)
Definition: tgModel.cpp:84
virtual void onVisit(tgModelVisitor &r)
Definition: T6Model.cpp:242
Markers for specific places on a tensegrity.
virtual btVector3 centerOfMass() const
Definition: tgBaseRigid.cpp:74
const std::vector< tgBasicActuator * > & getAllMuscles() const
Definition: T6Model.cpp:247
const std::vector< tgBasicActuator * > & getPassiveMuscles() const
Definition: T6Model.cpp:252
Definition of class tgBasicActuatorInfo.
virtual void onVisit(const tgModelVisitor &r) const
Definition: tgModel.cpp:107
virtual void setup(tgWorld &world)
Definition: T6Model.cpp:174
void addPair(int fromNodeIdx, int toNodeIdx, std::string tags="")
Definition: tgStructure.cpp:80
void addRotation(const btVector3 &fixedPoint, const btVector3 &axis, double angle)
void teardown()
Definition: T6Model.cpp:268
Contains the definition of class tgBasicActuator.
virtual void step(double dt)
Definition: T6Model.cpp:227
virtual ~T6Model()
Definition: T6Model.cpp:104
Definition of class tgStructure.
Definition of class tgStructureInfo.
virtual double mass() const
Definition: tgBaseRigid.h:65
const std::vector< tgBasicActuator * > & getActiveMuscles() const
Definition: T6Model.cpp:257
T6Model()
Definition: T6Model.cpp:100
virtual const double muscleRatio()
Definition: T6Model.cpp:262
Contains the definition of class tgRod.
Definition of class tgBuildSpec.
Definition: tgRod.h:43
void notifyStep(double dt)
std::vector< tgModel * > getDescendants() const
Definition: tgModel.cpp:170
void addNode(double x, double y, double z, std::string tags="")
Definition: tgStructure.cpp:70