NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
VerticalSpineModelCableCollision.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 
26 // This module
28 // This library
29 #include "core/tgCast.h"
30 //#include "core/tgBasicActuator.h"
31 //replaced
33 //added
34 #include "core/tgSphere.h"
35 #include "core/tgString.h"
36 #include "tgcreator/tgBuildSpec.h"
37 //#include "tgcreator/tgBasicActuatorInfo.h"
38 //added
41 #include "tgcreator/tgRodInfo.h"
42 //added
43 #include "tgcreator/tgSphereInfo.h"
44 #include "tgcreator/tgStructure.h"
46 #include "tgcreator/tgUtil.h"
47 // The Bullet Physics library
48 #include "btBulletDynamicsCommon.h"
49 // The C++ Standard Library
50 #include <iostream>
51 #include <stdexcept>
52 
53 // @todo move hard-coded parameters into config
54 
55 //m_segments(segments),
56 //tgModel()
57 VerticalSpineModelCableCollision::VerticalSpineModelCableCollision(size_t segments) :
58  BaseSpineModelLearning(segments)
59 {
60 }
61 
62 VerticalSpineModelCableCollision::~VerticalSpineModelCableCollision()
63 {
64 }
69 namespace
70 {
71  const struct Config
72  {
73  double densityA;
74  double densityB;
75  double radius;
76  double edge;
77  double height;
78  double stiffness;
79  double damping;
80  double friction;
81  double rollFriction;
82  double restitution;
83  double pretension;
84  bool hist;
85  double maxTens;
86  double targetVelocity;
87  } c =
88  {
89  0.026, // densityA (kg / length^3)
90  0.0, // densityB (kg / length^3)
91  0.5, // radius (length)
92  20.0, // edge (length)
93  tgUtil::round(c.edge / std::sqrt(2.0)), // height (length)
94  1000.0, // stiffness (kg / sec^2)
95  10.0, // damping (kg / sec)
96  0.99, // friction (unitless)
97  0.01, // rollFriction (unitless)
98  0.0, // restitution (?)
99  2452.0, // pretension
100  0, // History logging (boolean)
101  100000*1000000, // maxTens
102  10000, // targetVelocity
103 
104  };
105 
106 
107 
108  // Helper functions, with explicit scopes, moved from implicit namespace.
109  void trace(const tgStructureInfo& structureInfo, tgModel& model)
110  {
111  std::cout << "StructureInfo:" << std::endl
112  << structureInfo << std::endl
113  << "Model: " << std::endl
114  << model << std::endl;
115  }
116 
117  void addNodes(tgStructure& tetra, double edge, double height)
118  {
119  // right
120  tetra.addNode( c.edge / 2.0, 0, 0, "sphere"); // node 0
121  // left
122  tetra.addNode( -c.edge / 2.0, 0, 0, "sphere"); // node 1
123  // top
124  tetra.addNode(0, c.height, -edge / 2.0, "sphere"); // node 2
125  // front
126  tetra.addNode(0, c.height, edge / 2.0, "sphere"); // node 3
127  // middle
128  tetra.addNode(0, c.height/2, 0, "sphere"); // node 4
129 
130  //right holder
131  tetra.addNode(c.edge / 2.0, 0, 0.5, "sphere"); // node 5
132  tetra.addNode( c.edge / 2.0, 0, -0.5, "sphere"); // node 6
133  tetra.addNode( 0.5+c.edge / 2.0, 0, 0.5, "sphere"); // node 7
134  tetra.addNode( 0.5+c.edge / 2.0, 0, -0.5, "sphere"); // node 8
135  //left holder
136  tetra.addNode(-c.edge / 2.0, 0, 0.5, "sphere"); // node 9
137  tetra.addNode(-c.edge / 2.0, 0, -0.5, "sphere"); // node 10
138  tetra.addNode(-0.5 + -c.edge / 2.0, 0, 0.5, "sphere"); // node 11
139  tetra.addNode(-0.5 + -c.edge / 2.0, 0, -0.5, "sphere"); // node 12
140  //top holder
141  tetra.addNode(0.5, c.height, -edge / 2.0, "sphere"); // node 13
142  tetra.addNode(-0.5, c.height, -edge / 2.0, "sphere"); // node 14
143  tetra.addNode(0.5, c.height, -0.5 + -edge / 2.0, "sphere"); // node 15
144  tetra.addNode(-0.5, c.height, -0.5 + -edge / 2.0, "sphere"); // node 16
145  //front holder
146  tetra.addNode(0.5, c.height, edge / 2.0, "sphere"); // node 17
147  tetra.addNode(-0.5, c.height, edge / 2.0, "sphere"); // node 18
148  tetra.addNode(0.5, c.height, 0.5 + edge / 2.0, "sphere"); // node 19
149  tetra.addNode(-0.5, c.height, 0.5 + edge / 2.0, "sphere"); // node 20
150  }
151 
152  void addNodesB(tgStructure& tetra, double edge, double height)
153  {
154 
155  // right
156  tetra.addNode( c.edge / 2.0, 0, 0); // node 0
157  // left
158  tetra.addNode( -c.edge / 2.0, 0, 0); // node 1
159  // top
160  tetra.addNode(0, c.height, -edge / 2.0); // node 2
161  // front
162  tetra.addNode(0, c.height, edge / 2.0); // node 3
163  // middle
164  tetra.addNode(0, c.height/2, 0); // node 4
165  /*
166  //right holder
167  tetra.addNode(c.edge / 2.0, 0, 0.5, "sphereB"); // node 5
168  tetra.addNode( c.edge / 2.0, 0, -0.5, "sphereB"); // node 6
169  tetra.addNode( 0.5+c.edge / 2.0, 0, 0.5, "sphereB"); // node 7
170  tetra.addNode( 0.5+c.edge / 2.0, 0, -0.5, "sphereB"); // node 8
171  //left holder
172  tetra.addNode(-c.edge / 2.0, 0, 0.5, "sphereB"); // node 9
173  tetra.addNode(-c.edge / 2.0, 0, -0.5, "sphereB"); // node 10
174  tetra.addNode(-0.5 + -c.edge / 2.0, 0, 0.5, "sphereB"); // node 11
175  tetra.addNode(-0.5 + -c.edge / 2.0, 0, -0.5, "sphereB"); // node 12
176  //top holder
177  tetra.addNode(0.5, c.height, -edge / 2.0, "sphereB"); // node 13
178  tetra.addNode(-0.5, c.height, -edge / 2.0, "sphereB"); // node 14
179  tetra.addNode(0.5, c.height, -0.5 + -edge / 2.0, "sphereB"); // node 15
180  tetra.addNode(-0.5, c.height, -0.5 + -edge / 2.0, "sphereB"); // node 16
181  //front holder
182  tetra.addNode(0.5, c.height, edge / 2.0, "sphereB"); // node 17
183  tetra.addNode(-0.5, c.height, edge / 2.0, "sphereB"); // node 18
184  tetra.addNode(0.5, c.height, 0.5 + edge / 2.0, "sphereB"); // node 19
185  tetra.addNode(-0.5, c.height, 0.5 + edge / 2.0, "sphereB"); // node 20
186  */
187  }
188 
189  void addPairs(tgStructure& tetra)
190  {
191  tetra.addPair(0, 4, "rod");
192  tetra.addPair(1, 4, "rod");
193  tetra.addPair(2, 4, "rod");
194  tetra.addPair(3, 4, "rod");
195 
196  for (double i = 0; i<=3; i++)
197  {
198  tetra.addPair(i,i*4+5, "holder");
199  tetra.addPair(i,i*4+6, "holder");
200  tetra.addPair(i*4+5,i*4+7, "holder");
201  tetra.addPair(i*4+6,i*4+8, "holder");
202  tetra.addPair(i*4+7,i*4+8, "holder");
203  }
204  /*
205  //holder
206  tetra.addPair(0,5, "holder");
207  tetra.addPair(0,6, "holder");
208  tetra.addPair(5,7, "holder");
209  tetra.addPair(6,8, "holder");
210  tetra.addPair(7,8, "holder");
211  */
212  }
213 
214  void addPairsB(tgStructure& tetra)
215  {
216  tetra.addPair(0, 4, "rodB");
217  tetra.addPair(1, 4, "rodB");
218  tetra.addPair(2, 4, "rodB");
219  tetra.addPair(3, 4, "rodB");
220  /*
221  for (double i = 0; i<=3; i++)
222  {
223  tetra.addPair(i,i*4+5, "holderB");
224  tetra.addPair(i,i*4+6, "holderB");
225  tetra.addPair(i*4+6,i*4+8, "holderB");
226  tetra.addPair(i*4+5,i*4+7, "holderB");
227  tetra.addPair(i*4+7,i*4+8, "holderB");
228  }
229 
230  //holder
231  tetra.addPair(0,5, "holderB");
232  tetra.addPair(0,6, "holderB");
233  tetra.addPair(5,7, "holderB");
234  tetra.addPair(6,8, "holderB");
235  tetra.addPair(7,8, "holderB");
236  */
237  }
238 
239  void addSegments(tgStructure& snake, const tgStructure& tetra,
240  double edge, size_t segmentCount)
241  {
242  //const btVector3 offset(0, 0, -edge * 1.15);
243  const btVector3 offset(0, 7.5, 0);
244  for (size_t i = 1; i < segmentCount; ++i)
245  {
246  tgStructure* const t = new tgStructure(tetra);
247  t->addTags(tgString("segment", i + 1));
248  t->move((i + 1) * offset);
249  // Add a child to the snake
250  snake.addChild(t);
251  }
252 
253  }
254 
255  // Add muscles that connect the segments
256  // Underactuated Model Structure
257  void addMuscles(tgStructure& snake)
258  {
259  const std::vector<tgStructure*> children = snake.getChildren();
260  for (size_t i = 1; i < children.size(); ++i)
261  {
262  tgNodes vn0 = children[0]->getNodes();
263  tgNodes vn1 = children[i ]->getNodes();
264 
265  // vertical muscles
266  snake.addPair(vn0[0], vn1[0], "vertical muscle a");
267  snake.addPair(vn0[1], vn1[1], "vertical muscle b");
268  snake.addPair(vn0[2], vn1[2], "vertical muscle c");
269  snake.addPair(vn0[3], vn1[3], "vertical muscle d");
270 
271  tgNodes sn0 = children[i-1]->getNodes();
272  tgNodes sn1 = children[i ]->getNodes();
273  // saddle muscles
274  snake.addPair(sn0[2], sn1[1], tgString("saddle muscle seg", i-1));
275  snake.addPair(sn0[3], sn1[1], tgString("saddle muscle seg", i-1));
276  snake.addPair(sn0[2], sn1[0], tgString("saddle muscle seg", i-1));
277  snake.addPair(sn0[3], sn1[0], tgString("saddle muscle seg", i-1));
278  }
279  }
280 
281  void mapMuscles(VerticalSpineModelCableCollision::MuscleMap& muscleMap,
282  tgModel& model, size_t segmentCount)
283  {
284  // create names for muscles (for getMuscles function)
285 
286  // vertical muscles
287  muscleMap["vertical a"] = model.find<tgSpringCableActuator>("vertical muscle a");
288  muscleMap["vertical b"] = model.find<tgSpringCableActuator>("vertical muscle b");
289  muscleMap["vertical c"] = model.find<tgSpringCableActuator>("vertical muscle c");
290  muscleMap["vertical d"] = model.find<tgSpringCableActuator>("vertical muscle d");
291 
292  // saddle muscles
293  for (size_t i = 1; i < segmentCount ; ++i)
294  {
295  muscleMap[tgString("saddle", i-1)] = model.find<tgSpringCableActuator>(tgString("saddle muscle seg", i-1));
296 
297  }
298  }
299 } // end namespace
300 
301 /***************************************
302  * The primary functions., called from other classes.
303  **************************************/
305 {
306  // debugging output: edge and height length
307  std::cout << "edge: " << c.edge << "; height: " << c.height << std::endl;
308 
309  // Create the first fixed snake segment
310  // @todo move these hard-coded parameters into config
311  tgStructure tetraB;
312  addNodesB(tetraB, c.edge, c.height);
313  addPairsB(tetraB);
314  tetraB.move(btVector3(0.0, 2, 0));
315 
316  // Create our snake segments
317  tgStructure snake;
318 
319  // add 1st child to snake
320  tgStructure* const tB = new tgStructure(tetraB);
321  snake.addChild(tB);
322  tB->addTags(tgString("segment", 1));
323 
324  // Create the first non-fixed tetrahedra
325  tgStructure tetra;
326  addNodes(tetra, c.edge, c.height);
327  addPairs(tetra);
328 
329  // Move the first tetrahedra
330  // @todo move these hard-coded parameters into config
331  tetra.move(btVector3(0.0, -6, 0));
332 
333  // add rest of segments using original tetra configuration
334  addSegments(snake, tetra, c.edge, m_segments);
335 
336  addMuscles(snake);
337 
338  // Create the build spec that uses tags to turn the structure into a real model
339  // Note: This needs to be high enough or things fly apart...
340 
341  // length of inner strut = 12.25 cm
342  // m = 1 kg
343  // volume of 1 rod = 9.62 cm^3
344  // total volume = 38.48 cm^3
345  //const double density = 1/38.48; = 0.026 // kg / length^3 - see app for length
346  const tgRod::Config rodConfigA(c.radius, c.densityA, c.friction,
347  c.rollFriction, c.restitution);
348  const tgRod::Config rodConfigB(c.radius, c.densityB, c.friction,
349  c.rollFriction, c.restitution);
350  //holder
351  const tgRod::Config holderConfigA(0.15, c.densityA, c.friction,
352  c.rollFriction, c.restitution);
353  const tgRod::Config holderConfigB(0.15, c.densityB, c.friction,
354  c.rollFriction, c.restitution);
355 
356  //welding holders
357  const tgSphere::Config weldingConfigA(0.25, c.densityA);
358  //const tgSphere::Config weldingConfigB(0.3, c.densityA);
359 
360  tgBuildSpec spec;
361  spec.addBuilder("rod", new tgRodInfo(rodConfigA));
362  spec.addBuilder("rodB", new tgRodInfo(rodConfigB));
363 
364  // holder---------------------------------------------
365  spec.addBuilder("holder", new tgRodInfo(holderConfigA));
366  spec.addBuilder("holderB", new tgRodInfo(holderConfigB));
367  //----------------------------------------------------
368 
369  // welding
370  spec.addBuilder("sphere", new tgSphereInfo(weldingConfigA));
371  //spec.addBuilder("sphereB", new tgSphereInfo(weldingConfigB));
372  //-------------
373 
374  // set muscle (string) parameters
375  // @todo replace acceleration constraint with tgKinematicActuator if needed...
376  tgSpringCableActuator::Config muscleConfig(c.stiffness, c.damping, c.pretension,
377  false, c.maxTens, c.targetVelocity, 1.0,0.1,0.0);
378  spec.addBuilder("muscle", new tgBasicContactCableInfo(muscleConfig));
379  //spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));
380 
381  // Create your structureInfo
382  tgStructureInfo structureInfo(snake, spec);
383  // Use the structureInfo to build ourselves
384  structureInfo.buildInto(*this, world);
385 
386  // We could now use tgCast::filter or similar to pull out the models (e.g. muscles)
387  // that we want to control.
388  //m_allMuscles = tgCast::filter<tgModel, tgSpringCableActuator> (getDescendants());
389  //m_allSegments = tgCast::filter<tgModel,tgRod> (getDescendants());
390  m_allMuscles = this->find<tgSpringCableActuator> ("muscle");
391  m_allSegments = this->find<tgModel> ("segment");
392 
393  mapMuscles(m_muscleMap, *this, m_segments);
394 
395  trace(structureInfo, *this);
396  /*
397  // Actually setup the children
398  tgModel::setup(world);*/
400 }
401 
403 {
405 }
406 
408 {
409  if (dt < 0.0)
410  {
411  throw std::invalid_argument("dt is not positive");
412  }
413  else
414  {
415  /*
416  // Notify observers (controllers) of the step so that they can take action
417  notifyStep(dt);
418  // Step any children
419  tgModel::step(dt);
420  */
422  }
423 }
424 /*
425 const std::vector<tgSpringCableActuator*>&
426 VerticalSpineModel::getMuscles (const std::string& key) const
427 {
428  const MuscleMap::const_iterator it = muscleMap.find(key);
429  if (it == muscleMap.end())
430  {
431  throw std::invalid_argument("Key '" + key + "' not found in muscle map");
432  }
433  else
434  {
435  return it->second;
436  }
437 }
438 
439 const std::vector<tgSpringCableActuator*>& VerticalSpineModel::getAllMuscles() const
440 {
441  return allMuscles;
442 }
443 
444 */
const std::vector< tgStructure * > & getChildren() const
Definition: tgStructure.h:184
void addChild(tgStructure *child)
Definition of class tgRodInfo.
Definition of class tgSphereInfo.
Contains the definition of class VerticalSpineModel.
Convenience function for combining strings with ints, mostly for naming structures.
Contains the definition of class tgSphere.
Utility class for class casting and filtering collections by type.
virtual void setup(tgWorld &world)
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...
Definition of class tgBasicContactCableInfo.
std::string tgString(std::string s, int i)
Definition: tgString.h:33
Definition of class tgStructure.
std::vector< T * > find(const tgTagSearch &tagSearch)
Definition: tgModel.h:128
Definition of class tgStructureInfo.
Rand seeding simular to the evolution and terrain classes.
Definition of class tgBuildSpec.
virtual void step(double dt)
Definition of class tgRigidAutoCompound.
void buildInto(tgModel &model, tgWorld &world)
void addNode(double x, double y, double z, std::string tags="")
Definition: tgStructure.cpp:70