NTRT Simulator  v1.1
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
TetraSpineCollisions.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 
19 // This module
20 #include "TetraSpineCollisions.h"
21 // This library
22 #include "core/tgCast.h"
24 #include "core/tgString.h"
25 #include "core/tgSphere.h"
26 #include "core/abstractMarker.h"
27 #include "tgcreator/tgBuildSpec.h"
30 #include "tgcreator/tgRodInfo.h"
31 #include "tgcreator/tgSphereInfo.h"
32 #include "tgcreator/tgStructure.h"
34 #include "tgcreator/tgUtil.h"
35 
36 // The Bullet Physics library
37 #include "LinearMath/btVector3.h"
38 // The C++ Standard Library
39 #include <iostream>
40 #include <stdexcept>
41 
51 TetraSpineCollisions::TetraSpineCollisions(size_t segments) :
52  BaseSpineModelLearning(segments)
53 {
54 }
55 
56 TetraSpineCollisions::~TetraSpineCollisions()
57 {
58 }
59 namespace
60 {
61  void addNodes(tgStructure& tetra, double edge, double height)
62  {
63  // Front segment
64  // right
65  tetra.addNode(-edge / 2.0, 0, 0, "base");
66  // left
67  tetra.addNode( edge / 2.0, 0, 0, "base");
68  // top
69  tetra.addNode(0, height, 0, "base");
70  // front
71  tetra.addNode(0, edge / 2.0 * tan(M_PI / 6.0), 2.50 * 5.0, "tip");
72 
73  // Get the next two nodes from existing nodes:
74  tgNodes oldNodes = tetra.getNodes();
75  tgNode nn1 = (oldNodes[0] + oldNodes[2])/2.0; // 4 mid
76  nn1.addTags("PCB");
77  tetra.addNode(nn1);
78  tgNode nn2 = (oldNodes[1] + oldNodes[2])/2.0; // 5 mid
79  nn2.addTags("PCB");
80  tetra.addNode(nn2);
81 
82  std::cout << (oldNodes[3] - oldNodes[2]).length() << std::endl;
83  std::cout << (oldNodes[3] - oldNodes[1]).length() << std::endl;
84  std::cout << (oldNodes[3] - oldNodes[0]).length() << std::endl;
85 
86  }
87 
88  void addPairs(tgStructure& tetra)
89  {
90  tetra.addPair(0, 1, "back bottom rod");
91  tetra.addPair(0, 4, "back rightBottom rod");
92  tetra.addPair(4, 2, "back rightTop rod");
93  tetra.addPair(0, 3, "front right rod");
94  tetra.addPair(1, 5, "back leftBottom rod");
95  tetra.addPair(5, 2, "back leftTop rod");
96  tetra.addPair(1, 3, "front left rod");
97  tetra.addPair(2, 3, "front top rod");
98  }
99 
100 
101  void addSegments(tgStructure& snake, const tgStructure& tetra, double edge,
102  size_t segmentCount)
103  {
104  const btVector3 offset(0, 0, -2.30 * 5.0);
105  for (size_t i = 0; i < segmentCount; ++i)
106  {
109  tgStructure* const t = new tgStructure(tetra);
110  t->addTags(tgString("segment num", i )); // Use num0, num1, num2 as a tag!!
111 
112  t->move((i + 1) * offset);
113 
114  // Add a child to the snake
115  snake.addChild(t);
116 
117  }
118  }
119 
120  // Add muscles that connect the segments
121  void addMuscles(tgStructure& snake)
122  {
123  const std::vector<tgStructure*> children = snake.getChildren();
124  for (size_t i = 1; i < children.size(); ++i)
125  {
126  tgNodes n0 = children[i-1]->getNodes();
127  tgNodes n1 = children[i ]->getNodes();
128 
129  snake.addPair(n0[0], n1[0], tgString("outer right muscle seg", i));
130  snake.addPair(n0[1], n1[1], tgString("outer left muscle seg", i));
131  snake.addPair(n0[2], n1[2], tgString("outer top muscle seg", i));
132 
133  snake.addPair(n0[0], n1[3], tgString("inner right muscle seg", i));
134  snake.addPair(n0[1], n1[3], tgString("inner left muscle seg", i));
135  snake.addPair(n0[2], n1[3], tgString("inner top muscle seg", i));
136  }
137  }
138 
139  void mapMuscles(TetraSpineCollisions::MuscleMap& muscleMap,
140  tgModel& model)
141  {
142  // Note that tags don't need to match exactly, we could create
143  // supersets if we wanted to
144  muscleMap["inner left"] = model.find<tgSpringCableActuator>("inner left muscle");
145  muscleMap["inner right"] = model.find<tgSpringCableActuator>("inner right muscle");
146  muscleMap["inner top"] = model.find<tgSpringCableActuator>("inner top muscle");
147  muscleMap["outer left"] = model.find<tgSpringCableActuator>("outer left muscle");
148  muscleMap["outer right"] = model.find<tgSpringCableActuator>("outer right muscle");
149  muscleMap["outer top"] = model.find<tgSpringCableActuator>("outer top muscle");
150  }
151 
152  void addMarkers(tgStructure& structure, TetraSpineCollisions& model)
153  {
154 
155  const std::vector<tgStructure*> children = structure.getChildren();
156  tgNodes n0 = children[0]->getNodes();
157 
158  // TODO: consider using the segments vector here
159  btRigidBody* firstBody = model.getAllRigids()[0]->getPRigidBody();
160 
161  std::vector<tgBaseRigid*> myRigids = model.getAllRigids();
162 #if (0)
163  for (int i =0; i < myRigids.size(); i++)
164  {
165  std::cout << myRigids[i]->mass() << " " <<myRigids[i]->getPRigidBody() << std::endl;
166  }
167 #endif
168 
169  abstractMarker marker1(firstBody, n0[3] - firstBody->getCenterOfMassPosition (), btVector3(1, 0, 0), 0);
170 
171  model.addMarker(marker1);
172 
173  tgNodes n1 = children[1]->getNodes();
174 
175  btRigidBody* secondBody = model.getAllRigids()[15]->getPRigidBody();
176 
177  abstractMarker marker2(secondBody, n1[3] - secondBody->getCenterOfMassPosition (), btVector3(1, 0, 0), 0);
178 
179  model.addMarker(marker2);
180 
181  abstractMarker marker3(secondBody, n1[1] - secondBody->getCenterOfMassPosition (), btVector3(1, 0, 0), 0);
182 
183  model.addMarker(marker3);
184 
185  abstractMarker marker4(secondBody, n1[0] - secondBody->getCenterOfMassPosition (), btVector3(1, 0, 0), 0);
186 
187  model.addMarker(marker4);
188 
189  tgNodes n2 = children[2]->getNodes();
190 
191  btRigidBody* thirdBody = model.getAllRigids()[29]->getPRigidBody();
192 
193  abstractMarker marker5(thirdBody, n2[3] - thirdBody->getCenterOfMassPosition (), btVector3(1, 0, 0), 0);
194 
195  model.addMarker(marker5);
196  }
197 
198  void trace(const tgStructureInfo& structureInfo, tgModel& model)
199  {
200  std::cout << "StructureInfo:" << std::endl
201  << structureInfo << std::endl
202  << "Model: " << std::endl
203  << model << std::endl;
204  // Showing the find function
205  const std::vector<tgSpringCableActuator*> outerMuscles =
206  model.find<tgSpringCableActuator>("outer");
207  for (size_t i = 0; i < outerMuscles.size(); ++i)
208  {
209  const tgSpringCableActuator* const pMuscle = outerMuscles[i];
210  assert(pMuscle != NULL);
211  std::cout << "Outer muscle: " << *pMuscle << std::endl;
212  }
213  }
214 
215 } // namespace
216 
217 // This is basically a manual setup of a model.
218 // There are things that do this for us (@todo: reference the things that do this for us)
220 {
221  const double edge = 3.8 * 5.0;
222  const double height = tgUtil::round(std::sqrt(3.0)/2 * edge);
223  std::cout << "edge: " << edge << "; height: " << height << std::endl;
224 
225  // Create the tetrahedra
226  tgStructure tetra;
227  addNodes(tetra, edge, height);
228  addPairs(tetra);
229 
230  // Move the first one so we can create a longer snake.
231  // Or you could move the snake at the end, up to you.
232  tetra.move(btVector3(0.0, 8.0, 10.0));
233 
234  // Create our snake segments
235  tgStructure snake;
236  addSegments(snake, tetra, edge, m_segments);
237  addMuscles(snake);
238 
239  // Create the build spec that uses tags to turn the structure into a real model
240  // Note: This needs to be high enough or things fly apart...
241 
242 
243  // Params for In Won
244  const double radius = 0.635 / 2.0;
245  const double sphereRadius = 0.635 / 2.0;
246  const double density = .0201 / (pow(radius, 2) * M_PI * edge); // Mass divided by volume... should there be a way to set this automatically??
247  const double friction = 0.5;
248  const tgRod::Config rodConfig(radius, density, friction);
249  tgBuildSpec spec;
250  spec.addBuilder("rod", new tgRodInfo(rodConfig));
251 
252  // 1000 is so the units below can be in grams
253  const double sphereVolume1 = 1000.0 * 4.0 / 3.0 * M_PI * pow(sphereRadius, 3);
254  const double sphereVolume2 = 1000.0 * 4.0 / 3.0 * M_PI * pow(sphereRadius, 3);
255 
256  const double baseCornerMidD = 180.0 / sphereVolume1;
257  const tgSphere::Config baseCornerMidConfig(sphereRadius, baseCornerMidD, friction);
258  spec.addBuilder("base", new tgSphereInfo(baseCornerMidConfig));
259 
260  const double tipCornerMidD = 120.0 / sphereVolume1;
261  const tgSphere::Config tipCornerMidConfig(sphereRadius, tipCornerMidD, friction);
262  spec.addBuilder("tip", new tgSphereInfo(tipCornerMidConfig));
263 
264  const double PCBD = 70.0 / sphereVolume2;
265  const tgSphere::Config PCB_1_Config(radius, PCBD, friction);
266  spec.addBuilder("PCB", new tgSphereInfo(PCB_1_Config));
267 
268 
269  // Two different string configs
270  tgSpringCableActuator::Config muscleConfig(229.16 * 2.0, 20, 0.0, false, 500, 7.0, 0.1, 0.1);
271  tgSpringCableActuator::Config muscleConfig2(229.16, 20, 0.0, false, 500, 7.0, 0.1, 0.1);
272 #if (1)
273  spec.addBuilder("top muscle", new tgBasicContactCableInfo(muscleConfig));
274  spec.addBuilder("left muscle", new tgBasicContactCableInfo(muscleConfig2));
275  spec.addBuilder("right muscle", new tgBasicContactCableInfo(muscleConfig2));
276 #else
277  spec.addBuilder("top muscle", new tgBasicActuatorInfo(muscleConfig));
278  spec.addBuilder("left muscle", new tgBasicActuatorInfo(muscleConfig2));
279  spec.addBuilder("right muscle", new tgBasicActuatorInfo(muscleConfig2));
280 #endif
281  // Create your structureInfo
282  tgStructureInfo structureInfo(snake, spec);
283 
284  // Use the structureInfo to build ourselves
285  structureInfo.buildInto(*this, world);
286 
287  // We could now use tgCast::filter or similar to pull out the models (e.g. muscles)
288  // that we want to control.
289  m_allMuscles = this->find<tgSpringCableActuator> ("muscle");
290  m_allSegments = this->find<tgModel> ("segment");
291  mapMuscles(m_muscleMap, *this);
292 
293  addMarkers(snake, *this);
294 
295  #if (0)
296  trace(structureInfo, *this);
297  #endif
298 
299  // Actually setup the children
301 }
302 
304 {
305 
307 
308 }
309 
311 {
312  if (dt < 0.0)
313  {
314  throw std::invalid_argument("dt is not positive");
315  }
316  else
317  {
318  // Step any children, notify observers
320  }
321 }
const std::vector< tgStructure * > & getChildren() const
Definition: tgStructure.h:131
virtual void step(const double dt)
void addChild(tgStructure *child)
Definition of class tgRodInfo.
Definition of class tgSphereInfo.
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.
Markers for specific places on a tensegrity.
virtual void setup(tgWorld &world)
const tgNodes & getNodes() const
Definition: tgStructure.h:113
Definition of class tgBasicActuatorInfo.
void addPair(int fromNodeIdx, int toNodeIdx, std::string tags="")
Definition: tgStructure.cpp:66
Contains the definition of abstract base class tgSpringCableActuator. Assumes that the string is line...
Definition of class tgBasicContactCableInfo.
virtual void setup(tgWorld &world)
std::string tgString(std::string s, int i)
Definition: tgString.h:33
Definition: tgNode.h:45
Definition of class tgStructure.
std::vector< T * > find(const tgTagSearch &tagSearch)
Definition: tgModel.h:125
Definition of class tgStructureInfo.
Middle segment of In Won's robot reconfigured with tgBulletContactSpringCable and more segments...
Contains the definition of class tgUtil and overloaded operator<<() free functions.
Definition of class tgBuildSpec.
virtual void step(double dt)
void addNode(double x, double y, double z, std::string tags="")
Definition: tgStructure.cpp:56