NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
tgRigidAutoCompound.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 
27 // This module
28 #include "tgRigidAutoCompound.h"
29 // Bullet Physics
30 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
31 #include "tgCompoundRigidInfo.h"
32 // The C++ standard library
33 #include <map>
34 #include <cstdlib> // for random number generator
35 #include <sstream> // for string streams, tags.
36 // Boost
37 #include <boost/random/random_device.hpp> // used for the random compound tag hash
38 #include <boost/random/uniform_int_distribution.hpp> // used for the random compound tag hash
39 
40 // Debugging
41 #include <iostream>
42 #include "tgUtil.h"
43 
44 using namespace std;
45 
46 
47 // @todo: we want to start using this and get rid of the set-based constructor, but until we can refactor...
48 tgRigidAutoCompound::tgRigidAutoCompound(std::vector<tgRigidInfo*> rigids)
49 {
50  m_rigids.insert(m_rigids.end(), rigids.begin(), rigids.end());
51 }
52 
53 tgRigidAutoCompound::tgRigidAutoCompound(std::deque<tgRigidInfo*> rigids) : m_rigids(rigids)
54 {}
55 
56 std::vector< tgRigidInfo* > tgRigidAutoCompound::execute() {
57 
58  // Determine the grouping of our rigids
59  groupRigids();
60 
61  // Create the compounds as necessary
63 
64  // Set the rigid body for the various groups
65  for(int i=0; i < m_groups.size(); i++) {
66  // Note: rigids that are not connected to anything else are placed
67  //into a group of their own, so they're represented here too
68  setRigidInfoForGroup(m_compounded[i], m_groups[i]);
69  }
70  // Need to return this so we can delete it at the appropreate time
71  return m_compounded;
72 };
73 
74 // @todo: we probably don't need this any more -- this will be taken care of in the tgRigidInfo => tgModel step
75 // @todo: NOTE: we need to have a way to check to see if a rigid has already been instantiated -- maybe just check get
76 void tgRigidAutoCompound::setRigidBodyForGroup(btCollisionObject* body, std::deque<tgRigidInfo*>& group) {
77  for(int i = 0; i < group.size(); i++) {
78  group[i]->setCollisionObject(body);
79  }
80 }
81 
82 void tgRigidAutoCompound::setRigidInfoForGroup(tgRigidInfo* rigidInfo, std::deque<tgRigidInfo*>& group) {
83  for(int i = 0; i < group.size(); i++) {
84  group[i]->setRigidInfoGroup(rigidInfo);
85  }
86 }
87 
88 void tgRigidAutoCompound::groupRigids()
89 {
90  std::deque<tgRigidInfo*> ungrouped = std::deque<tgRigidInfo*>(m_rigids); // Copy of m_rigids
91 
92  while(ungrouped.size() > 0) {
93  // go through each ungrouped element and find the groups for it
94  tgRigidInfo* elem = ungrouped[0]; // Note: the 0 element is removed by findGroup, so ungrouped[0] is different each iteration
95 
96  // Find all elements linked to the first item in ungrouped
97  // This will also remove the elements in the group from ungrouped
98  std::deque<tgRigidInfo*> group = findGroup(elem, ungrouped);
99 
100  // Add the group to the groups list
101  m_groups.push_back(group);
102  }
103 }
104 
105 // Find all rigids that should be in a group with the given rigid
106 // @todo: This may contain an off-by-one error (the last rigid may not be grouped properly...)
107 std::deque<tgRigidInfo*> tgRigidAutoCompound::findGroup(tgRigidInfo* rigid, std::deque<tgRigidInfo*>& ungrouped) {
108 
109  std::deque<tgRigidInfo*> group;
110 
111  // Add the rigid to the current group
112  group.push_back(rigid);
113 
114  // Remove the rigid from the ungrouped since it's now in a group
115  ungrouped.erase(std::remove(ungrouped.begin(), ungrouped.end(), rigid), ungrouped.end());
116 
117  // Recursively find linked elements
118  int i = 0;
119  while(i < ungrouped.size()) {
120  tgRigidInfo* other = ungrouped[i];
121  if(rigid->sharesNodesWith(*other)) {
122  std::deque<tgRigidInfo*> links = findGroup(other, ungrouped);
123  group.insert(group.end(), links.begin(), links.end());
124  i = 0;
125  } else {
126  i++;
127  }
128  }
129 
130  return group;
131 };
132 
134  for(int i=0; i < m_groups.size(); i++) {
135  std::deque<tgRigidInfo*>& group = m_groups[i];
136  if(group.size() == 1) {
137  // Only one, no compounding necessary
138  m_compounded.push_back(group[0]);
139  } else {
140  tgRigidInfo* compound = createCompound(group);
141  m_compounded.push_back(compound);
142  }
143  }
144 }
145 
146 tgRigidInfo* tgRigidAutoCompound::createCompound(std::deque<tgRigidInfo*> rigids) {
148  // Add an additional tag to this compound rigid info.
149  // This is of the form "compound_3qhA8L" for example.
150  std::stringstream newtag;
151  newtag << "compound_" << random_tag_hash();
152  for(int i = 0; i < rigids.size(); i++) {
153  rigids[i]->addTags(newtag.str());
154  c->addRigid(*rigids[i]);
155  }
156  return (tgRigidInfo*)c;
157 }
158 
159 bool tgRigidAutoCompound::rigidBelongsIn(tgRigidInfo* rigid, std::deque<tgRigidInfo*> group) {
160  for(int i = 0; i < group.size(); i++) {
161  tgRigidInfo* other = group[i];
162  if(rigid->sharesNodesWith(*other))
163  return true;
164  }
165  return false;
166 };
167 
177  // Create the string (character array) to put the random characters into
178  size_t length = 6;
179  char s[length];
180 
181  // The random number generator to pick characters out of the array
182  boost::random::random_device rng;
183 
184  // A constant variable for the chracters that will be chosen from
185  static const char alphanum[] =
186  "0123456789"
187  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
188  "0123456789"
189  "abcdefghijklmnopqrstuvwxyz";
190 
191  // A uniform distribution over the indices into the character array
192  boost::random::uniform_int_distribution<> alphanum_dist(0, sizeof(alphanum) - 1);
193 
194  // Insert a random one of these characters into the array
195  // Thanks to the Boost library random number generator tutorial,
196  // http://www.boost.org/doc/libs/1_62_0/doc/html/boost_random/tutorial.html
197  for (int i = 0; i < length; ++i) {
198  //s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
199  s[i] = alphanum[ alphanum_dist(rng) ];
200  }
201 
202  // set the string termination character
203  s[length] = 0;
204 
205  // Returning a character array is the same as returning a string.
206  return s;
207 }
virtual bool sharesNodesWith(const tgRigidInfo &other) const
Definition of class tgCompoundRigidInfo.
void addRigid(tgRigidInfo &rigid)
Rand seeding simular to the evolution and terrain classes.
Definition of class tgRigidAutoCompound.