NTRT Simulator  Version: Master
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
tgConnectorInfo.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 #include "tgConnectorInfo.h"
28 
29 #include "tgPair.h"
30 #include "tgPairs.h"
31 #include "tgRigidInfo.h"
32 
33 #include "core/tgTagSearch.h"
34 
35 #include "LinearMath/btVector3.h"
36 #include "BulletDynamics/Dynamics/btRigidBody.h"
37 
38 
39 tgConnectorInfo* tgConnectorInfo::createConnectorInfo(const tgPair& pair, const tgTagSearch& tagSearch)
40 {
41  // Our subclasses may not be able to create connectorInfos based on nodes. Also, the
42  // tags may not match our search. Make sure both work, or return 0.
43  tgConnectorInfo* connectorInfo = 0;
44  if(tagSearch.matches(pair.getTags())) {
45  connectorInfo = createConnectorInfo(pair);
46  }
47  return connectorInfo;
48 }
49 
50 std::vector<tgConnectorInfo*> tgConnectorInfo::createConnectorInfos(const tgPairs& pairs, const tgTagSearch& tagSearch)
51 {
52  std::vector<tgConnectorInfo*> result;
53  for(int i = 0; i < pairs.size(); i++) {
54  tgConnectorInfo* r = createConnectorInfo(pairs[i], tagSearch);
55  if(r != 0) {
56  result.push_back(r);
57  }
58  }
59  return result;
60 }
61 
62 void tgConnectorInfo::chooseRigids(std::set<tgRigidInfo*> rigids)
63 {
64 
65  // @todo: find and set pointers to appropriate rigids from the set provided.
66  // @todo: should we throw an exception if no appropriate rigid is found?
67  if(getFromRigidInfo() == 0) { // if it hasn't already been set
68  tgRigidInfo* fromRigidInfo = chooseRigid(rigids, getFrom());
69  //std::cout << " chosen fromRigidInfo is " << fromRigidInfo << std::endl;
70  setFromRigidInfo(fromRigidInfo);
71  //std::cout << " getFromRigidInfo is " << getFromRigidInfo() << std::endl;
72  }
73 
74  if(getToRigidInfo() == 0) { // if it hasn't already been set
75  tgRigidInfo* toRigidInfo = chooseRigid(rigids, getTo());
76  //std::cout << " chosen toRigidInfo is " << toRigidInfo << std::endl;
77  setToRigidInfo(toRigidInfo);
78  //std::cout << " getToRigidInfo is " << getToRigidInfo() << std::endl;
79  }
80 }
81 
82 tgRigidInfo* tgConnectorInfo::chooseRigid(std::set<tgRigidInfo*> rigids, const btVector3& v) {
83 
84  std::set<tgRigidInfo*> candidateRigids = findRigidsContaining(rigids, v);
85 
86  tgRigidInfo* chosenRigid;
87  if (candidateRigids.size() == 1) {
88  // Choose the first element since there's only one
89  chosenRigid = *(candidateRigids.begin());
90  }
91  else if (candidateRigids.size() > 1 ){
92  // find the best candidate (if more than one rigid, use the rigid whose center of mass is closest to v. This seems like a reasonable approach...)
93  // Note that this isn't well-defined behavior. The situation in which this
94  // would happen is if two rigids met at a point, and a connector was made
95  // between that point and somewhere else. Since the auto-compounder will
96  // combine those shapes automatically, it shouldn't technically matter
97  // which of those shapes the connector is attached to, but for other
98  // applications (such as placing tonnectors on the surfaces of rigid bodies
99  // instead of just at the nods in tgPair), it would be better to prioritize
100  // points inside the pair than just whatever is closest to the center of mass.
101  // Otherwise this may break in the situation where one rigid body is created
102  // next to another, and the connector is supposed to be from one body at a
103  // node, but ends up getting connected at the surface of the other rigid body.
104  //DEBUGGING:
105  if( 0 ) {
106  std::cout << std::endl << "WARNING: A connector is being created that has more than one potential connecting point. This behavior is not well defined. If your model does not behave as you expect, try moving these multiple rigid bodies apart by some distance, and having the connector attach to only one node." << std::endl
107  << std::endl;
108  }
109  chosenRigid = findClosestCenterOfMass(candidateRigids, v);
110  }
111  else if (candidateRigids.size() == 0) {
112  //DEBUGGING:
113  std::cout << std::endl << "WARNING: A connector is being created without a connecting point on one end. This WILL cause the simulator to crash when its pointer to a tgRigidInfo is called, since no rigid body can be associated with this point, and so no tgRigidBody can be created." << std::endl << std::endl;
114  }
115 
116  return chosenRigid;
117 };
118 
119 btRigidBody* tgConnectorInfo::getToRigidBody() {
120  // Check if the tgRigidInfo is set, if not, throw an exception.
121  if( getToRigidInfo() == NULL ){
122  std::cout << std::endl << "Error in tgConnectorInfo::getToRigidBody. "
123  << "The toRigidInfo for tgConnector with pair "
124  << getFrom() << ", " << getTo() << " has not been assigned yet, "
125  << "but its getToRigidBody method is being called." << std::endl;
126  throw std::runtime_error("getToRigidInfo == NULL, cannot return rigid body.");
127  }
128  if( getToRigidInfo()->getRigidInfoGroup() == NULL ){
129  std::cout << std::endl << "Error in tgConnectorInfo::getToRigidBody. "
130  << "The toRigidInfo for tgConnector with pair "
131  << getFrom() << ", " << getTo() << " has been assigned, but does "
132  << "not have a rigidInfoGroup from which to get a rigid body. "
133  << std::endl;
134  throw std::runtime_error("getToRigidInfo()->getRigidInfoGroup() == NULL, cannot return rigid body.");
135  }
136  return getToRigidInfo()->getRigidInfoGroup()->getRigidBody();
137 };
138 
139 btRigidBody* tgConnectorInfo::getFromRigidBody() {
140  // Check if the tgRigidInfo is set, if not, throw an exception.
141  if( getFromRigidInfo() == NULL ){
142  std::cout << std::endl << "Error in tgConnectorInfo::getFromRigidBody. "
143  << "The fromRigidInfo for tgConnector with pair "
144  << getFrom() << ", " << getTo() << " has not been assigned yet, "
145  << "but its getFromRigidBody method is being called." << std::endl;
146  throw std::runtime_error("getFromRigidInfo == NULL, cannot return rigid body.");
147  }
148  if( getFromRigidInfo()->getRigidInfoGroup() == NULL ){
149  std::cout << std::endl << "Error in tgConnectorInfo::getFromRigidBody. "
150  << "The fromRigidInfo for tgConnector with pair "
151  << getFrom() << ", " << getTo() << " has been assigned, but does "
152  << "not have a rigidInfoGroup from which to get a rigid body. "
153  << std::endl;
154  throw std::runtime_error("getFromRigidInfo()->getRigidInfoGroup() == NULL, cannot return rigid body.");
155  }
156  return getFromRigidInfo()->getRigidInfoGroup()->getRigidBody();
157 };
158 
159 
160 // Protected:
161 
162 
163 tgRigidInfo* tgConnectorInfo::findClosestCenterOfMass(std::set<tgRigidInfo*> rigids, const btVector3& v) {
164  if (rigids.size() == 0) {
165  return NULL;
166  }
167  std::set<tgRigidInfo*>::iterator it;
168  it = rigids.begin();
169  tgRigidInfo* closest = *it; // First member
170  it++;
171  for(; it != rigids.end(); ++it) {
172  btVector3 com = (*it)->getCenterOfMass();
173  if(com.distance(v) < closest->getCenterOfMass().distance(v)) {
174  closest = *it;
175  }
176  }
177  return closest;
178 }
179 
180 
181 std::set<tgRigidInfo*> tgConnectorInfo::findRigidsContaining(std::set<tgRigidInfo*> rigids, const btVector3& toFind) {
182  std::set<tgRigidInfo*> found;
183  std::set<tgRigidInfo*>::iterator it;
184  for(it=rigids.begin(); it != rigids.end(); ++it) {
185  if ((*it)->containsNode(toFind)) {
186  found.insert(*it);
187  }
188  }
189  return found;
190 };
191 
192 // @todo: Remove this? Is it used by anything? It's protected...
193 bool tgConnectorInfo::rigidFoundIn(std::set<tgRigidInfo*> rigids, tgRigidInfo* rigid) {
194  //return (std::find(rigids.begin(), rigids.end(), rigid) != rigids.end()); // Doesn't work on some compilers (RDA 2014-Jan-28)
195  std::set<tgRigidInfo*>::iterator it;
196  for(it = rigids.begin(); it != rigids.end(); ++it) {
197  if(*it == rigid)
198  return true;
199  }
200  return false;
201 };
Contains the definition of class tgTagSearch.
Definition of abstract class tgRigidInfo.
virtual tgRigidInfo * getRigidInfoGroup()
Definition: tgRigidInfo.h:149
Definition of class tgPair.
Definition of class tgPairs.
Definition of class tgConnectorInfo.
virtual btRigidBody * getRigidBody()
const bool matches(const tgTags &tags) const
Definition: tgTagSearch.h:62
virtual btVector3 getCenterOfMass() const =0
Definition: tgPair.h:48