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