NTRT Simulator  v1.1
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
RibModel.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 
28 #include "RibModel.h"
29 
30 #include "core/tgCast.h"
32 #include "core/tgString.h"
33 #include "tgcreator/tgBuildSpec.h"
35 #include "tgcreator/tgRodInfo.h"
36 #include "tgcreator/tgStructure.h"
38 #include "tgcreator/tgUtil.h"
39 
40 // Bullet Physics
41 #include "LinearMath/btVector3.h"
42 // The C++ Standard Library
43 #include <iostream>
44 
45 namespace
46 {
47  void addNodes(tgStructure& tetra, double v_size)
48  {
49  tetra.addNode(0,0,0); // center
50  tetra.addNode(0.0, v_size, v_size / 2.0); // top
51  tetra.addNode(-v_size, 0.0, -v_size); // left
52  tetra.addNode(v_size, 0.0, -v_size); // right
53  #if (0) // Attempt at compliant rib attachments
54  tetra.addNode(-v_size / 5.0, 0.0, 0.0); // right
55  tetra.addNode(v_size / 5.0, 0.0, 0.0); // right
56  #endif
57 
58  //tetra.addNode(v_size, -v_size, -v_size); // right
59 
60  //tetra.addNode(-v_size, -v_size, v_size); // left
61  }
62 
63  void ellipseNodes(tgStructure& tetra, double a, double b, double startT, double endT, size_t n)
64  {
65  double rodL = (endT - startT) / (double) n;
66 
67  for(size_t i = 0; i < n; i++)
68  {
69  double x = a * cos( startT + i * rodL);
70  double y = b * sin( startT + i * rodL);
71  // Just build it in xy, can rotate later
72  tgNode node( btVector3( x, y, 0.0));
73  tetra.addNode( node );
74  }
75  #if (0)
76  // Final Nodes for "feet"
77  double x = a * cos( startT + (n - 1) * rodL);
78  double y = b * sin( startT + (n - 1) * rodL) - 0.5;
79  tgNode node( btVector3( x, y, 0.0));
80  tetra.addNode( node );
81  #endif
82  }
83 
85  void addPairs(tgStructure& tetra)
86  {
87  tetra.addPair(0,1, "top rod");
88  tetra.addPair(0,2, "left rod");
89  tetra.addPair(0,3, "right rod");
90  #if (0) // extra connection points for muscles
91  tetra.addPair(0,4, "leftRib rod");
92  tetra.addPair(0,5, "rightRib rod");
93  #endif
94  //tetra.addPair(0,3, "back rod");
95  //tetra.addPair(0,4, "left rod");
96  }
97 
99  void makePairs(tgStructure& tetra)
100  {
101  size_t n = tetra.getNodes().size();
102  std::cout << "Nodes size is " << n << std::endl;
103  for(int i = 1; i < n; i++) {
104  tetra.addPair(i-1, i, "rod");
105  }
106  }
107 
108  void addSegments(tgStructure& snake, const tgStructure& tetra,
109  const tgStructure& ribs, double edge, size_t segmentCount)
110  {
111  const btVector3 offset(0, 0, -edge * 1.3);
112  const btVector3 rotAxis(0, 1.0, 0);
113  for (size_t i = 0; i < segmentCount; ++i)
114  {
115 
116  tgStructure* const t = new tgStructure(tetra);
117  // Need a new pointer for every rib
118  tgStructure* const r = new tgStructure(ribs);
119  tgStructure* const r2 = new tgStructure(ribs);
120  t->addChild(r);
121  t->addChild(r2);
122 
123  tgNodes r01 = r->getNodes();
124  tgNodes r02 = r2->getNodes();
125  tgNodes t01 = t->getNodes();
126 
127  size_t r02End = r02.getNodes().size();
128  #if (0)
129  r2->addRotation(t01[0], rotAxis, M_PI);
130  t->addPair(t01[0], r01[0], "multiMuscle connect");
131  t->addPair(t01[0], r02[0], "multiMuscle connect");
132  #else
133  t->addPair(t01[0], r01[0], "rod connect");
134  t->addPair(t01[0], r02[0], "rod connect");
135  r2->addRotation(r02[0], rotAxis, M_PI);
136  #endif
137 
138 
139  t->addTags(tgString("segment num", i + 1));
140  t->move((i + 1) * offset);
141  // Add a child to the snake
142  snake.addChild(t);
143  }
144  }
145 
146  // Add muscles that connect the segments
147  void addMuscles(tgStructure& snake)
148  {
149  const std::vector<tgStructure*> children = snake.getChildren();
150  for (size_t i = 1; i < children.size(); ++i)
151  {
152  tgNodes n0 = children[i-1]->getNodes();
153  tgNodes n1 = children[i ]->getNodes();
154 
155  const std::vector<tgStructure*> subChildren1 = children[i-1]->getChildren();
156  const std::vector<tgStructure*> subChildren2 = children[i]->getChildren();
157 
158  tgNodes r10 = subChildren1[0]->getNodes();
159  tgNodes r11 = subChildren1[1]->getNodes();
160  tgNodes r20 = subChildren2[0]->getNodes();
161  tgNodes r21 = subChildren2[1]->getNodes();
162 
163  snake.addPair(n0[1], n1[1], tgString("outer front muscleAct seg", i-1) + tgString(" seg", i));
164  snake.addPair(n0[2], n1[2], tgString("outer right muscleAct seg", i-1) + tgString(" seg", i));
165  snake.addPair(n0[3], n1[3], tgString("outer back muscleAct seg", i-1) + tgString(" seg", i));
166 
167  snake.addPair(n0[2], n1[1], tgString("inner front muscleAct seg", i-1) + tgString(" seg", i));
168  snake.addPair(n0[3], n1[1], tgString("inner right muscleAct seg", i-1) + tgString(" seg", i));
169 
170  snake.addPair(n0[2], r20[3], tgString("inner front muscleAct seg", i-1) + tgString(" seg", i));
171  snake.addPair(n0[3], r21[3], tgString("inner right muscleAct seg", i-1) + tgString(" seg", i));
172 
173  snake.addPair(r10[5], r20[12], tgString("intercostal muscle seg", i-1) + tgString(" seg", i));
174  snake.addPair(r11[5], r21[12], tgString("intercostal muscle seg", i-1) + tgString(" seg", i));
175  snake.addPair(r10[12], r20[5], tgString("intercostal muscle seg", i-1) + tgString(" seg", i));
176  snake.addPair(r11[12], r21[5], tgString("intercostal muscle seg", i-1) + tgString(" seg", i));
177  }
178  }
179 
180  void trace(const tgStructureInfo& structureInfo, tgModel& model)
181  {
182  std::cout << "StructureInfo:" << std::endl
183  << structureInfo << std::endl
184  << "Model: " << std::endl
185  << model << std::endl;
186  // Showing the find function
187  const std::vector<tgSpringCableActuator*> outerMuscles =
188  model.find<tgSpringCableActuator>("outer");
189  for (size_t i = 0; i < outerMuscles.size(); ++i)
190  {
191  const tgSpringCableActuator* const pMuscle = outerMuscles[i];
192  assert(pMuscle != NULL);
193  std::cout << "Outer muscle: " << *pMuscle << std::endl;
194  }
195  }
196 
197 } // namespace
198 
199 RibModel::RibModel(int segments) :
200  BaseSpineModelLearning(segments)
201 {
202 }
203 
204 RibModel::~RibModel()
205 {
206 }
207 
209 {
210  double v_size = 3.0;
211 
212  // Create the spinal processes
213  tgStructure vertebrae;
214  addNodes(vertebrae, v_size);
215  addPairs(vertebrae);
216 
217  // Move the first one so we can create a longer snake.
218  // Or you could move the snake at the end, up to you.
219  vertebrae.move(btVector3(0.0, 2 * v_size, v_size * m_segments));
220 
221  // Create ribs and add them to the vertebrae
222  double majorAxis = 6.0;
223  double minorAxis = 4.0;
224  double startTheta = M_PI / 2.0;
225  double endTheta = 5.0 * M_PI / 4.0;
226  size_t segs = 15;
227 
228  tgStructure ribs;
229  ellipseNodes(ribs, majorAxis, minorAxis, startTheta, endTheta, segs);
230  makePairs(ribs);
231 
232  #if (0) // Attempt at compliant rib attachments
233  ribs.move(btVector3(v_size / 3.0, 2 * v_size - minorAxis, v_size * m_segments));
234  #else
235  ribs.move(btVector3(0.0, 2 * v_size - minorAxis -.3, v_size * m_segments));
236  #endif
237  // Create our snake segments
238  tgStructure snake;
239  addSegments(snake, vertebrae, ribs, v_size, m_segments);
240 
241  snake.move(btVector3(0.0, majorAxis, 0.0));
242 
243  addMuscles(snake);
244 
245  // Create the build spec that uses tags to turn the structure into a real model
246  // Note: This needs to be high enough or things fly apart...
247  const double density = 4.2 / 300.0;
248  const double radius = 0.5;
249  const double friction = 0.5; // Default is 0.5
250  const double rollFriction = 0.5; // Default is 0.0
251  const double restitution = 0.0; // Default
252 
253  const tgRod::Config rodConfig(radius, density, friction, rollFriction, restitution);
254  tgBuildSpec spec;
255  spec.addBuilder("rod", new tgRodInfo(rodConfig));
256 
257  const double pretension = 0.0;
258  const bool hist = false;
259 
260  tgSpringCableActuator::Config muscleConfig(500, 5, pretension, hist);
261  spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));
263  tgSpringCableActuator::Config muscleConfigAct(1000, 10, pretension, hist, 7000, 24);
264  spec.addBuilder("muscleAct", new tgBasicActuatorInfo(muscleConfigAct));
265 
266  #if (0) // Compliant Rib Attachments
267  const double stiffness = 1000;
268  const double damping = .01 * stiffness;
269 
270  tgSpringCableActuator::Config muscleConfig1(stiffness, damping, -M_PI / 2.0);
271  tgSpringCableActuator::Config muscleConfig2(stiffness, damping, M_PI / 2.0);
272  tgSpringCableActuator::Config muscleConfig3(stiffness, damping, M_PI);
273  tgSpringCableActuator::Config muscleConfig4(stiffness, damping, 0);
274 
275  spec.addBuilder("multiMuscle", new tgBasicActuatorInfo(muscleConfig1));
276  spec.addBuilder("multiMuscle", new tgBasicActuatorInfo(muscleConfig2));
277  spec.addBuilder("multiMuscle", new tgBasicActuatorInfo(muscleConfig3));
278  spec.addBuilder("multiMuscle", new tgBasicActuatorInfo(muscleConfig4));
279  #endif
280  // Create your structureInfo
281  tgStructureInfo structureInfo(snake, spec);
282 
283  // Use the structureInfo to build ourselves
284  structureInfo.buildInto(*this, world);
285 
286  // We could now use tgCast::filter or similar to pull out the models (e.g. muscles)
287  // that we want to control.
288  m_allMuscles = find<tgSpringCableActuator> ("muscleAct");
289  m_allSegments = find<tgModel> ("segment");
290 
291  #if (0)
292  trace(structureInfo, *this);
293  #endif
294 
295  // Actually setup the children
297 }
299 {
300 
302 
303 }
304 
305 void RibModel::step(double dt)
306 {
307 
308  if (dt < 0.0)
309  {
310  throw std::invalid_argument("dt is not positive");
311  }
312  else
313  {
314  /* CPG update occurs in the controller so that we can decouple it
315  * from the physics update
316  */
317 
318  BaseSpineModelLearning::step(dt); // Step any children
319  }
320 }
const std::vector< tgStructure * > & getChildren() const
Definition: tgStructure.h:131
void addChild(tgStructure *child)
Definition of class tgRodInfo.
Implements a spine model with a rib cage.
virtual void setup(tgWorld &world)
Definition: RibModel.cpp:208
Convenience function for combining strings with ints, mostly for naming structures.
Utility class for class casting and filtering collections by type.
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...
void addRotation(const btVector3 &fixedPoint, const btVector3 &axis, double angle)
Definition: tgStructure.cpp:99
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.
Contains the definition of class tgUtil and overloaded operator<<() free functions.
virtual void teardown()
Definition: RibModel.cpp:298
Definition of class tgBuildSpec.
virtual void step(double dt)
virtual void step(double dt)
Definition: RibModel.cpp:305
void addNode(double x, double y, double z, std::string tags="")
Definition: tgStructure.cpp:56