interaction_mesh.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 #include <exotica_core/server.h>
32 
34 
35 namespace exotica
36 {
39 
41 {
42  int M = eff_size_;
43 
44  if (phi.rows() != M * 3) ThrowNamed("Wrong size of Phi!");
45 
46  Eigen::VectorXd eff_Phi;
47  for (int i = 0; i < M; ++i)
48  {
49  eff_Phi(i * 3) = kinematics[0].Phi(i).p[0];
50  eff_Phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
51  eff_Phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
52  }
53  phi = ComputeLaplace(eff_Phi, weights_);
54 
55  if (debug_) Debug(phi);
56 }
57 
59 {
60  int M = eff_size_;
61  int N = kinematics[0].jacobian[0].data.cols();
62 
63  if (phi.rows() != M * 3) ThrowNamed("Wrong size of Phi!");
64  if (jacobian.rows() != M * 3 || jacobian.cols() != N) ThrowNamed("Wrong size of jacobian! " << N);
65 
66  Eigen::MatrixXd dist;
67  Eigen::VectorXd wsum;
68  Eigen::VectorXd eff_Phi(M * 3);
69  for (int i = 0; i < M; ++i)
70  {
71  eff_Phi(i * 3) = kinematics[0].Phi(i).p[0];
72  eff_Phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
73  eff_Phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
74  }
75  phi = ComputeLaplace(eff_Phi, weights_, &dist, &wsum);
76 
77  double A, _A, Sk, Sl, w, _w;
78  int i, j, k, l;
79  Eigen::Vector3d distance, _distance = Eigen::Vector3d::Zero(3, 1);
80  for (i = 0; i < N; ++i)
81  {
82  for (j = 0; j < M; ++j)
83  {
84  if (j < M)
85  jacobian.block(3 * j, i, 3, 1) = kinematics[0].jacobian[j].data.block(0, i, 3, 1);
86  for (l = 0; l < M; ++l)
87  {
88  if (j != l)
89  {
90  if (dist(j, l) > 0 && wsum(j) > 0 && weights_(j, l) > 0)
91  {
92  A = dist(j, l) * wsum(j);
93  w = weights_(j, l) / A;
94 
95  _A = 0;
96  distance = eff_Phi.segment(j * 3, 3) - eff_Phi.segment(l * 3, 3);
97  _distance = kinematics[0].jacobian[j].data.block(0, i, 3, 1) - kinematics[0].jacobian[l].data.block(0, i, 3, 1);
98 
99  Sl = distance.dot(_distance) / dist(j, l);
100  for (k = 0; k < M; ++k)
101  {
102  if (j != k && dist(j, k) > 0 && weights_(j, k) > 0)
103  {
104  distance = eff_Phi.segment(j * 3, 3) - eff_Phi.segment(k * 3, 3);
105  _distance = kinematics[0].jacobian[j].data.block(0, i, 3, 1) - kinematics[0].jacobian[k].data.block(0, i, 3, 1);
106  Sk = distance.dot(_distance) / dist(j, k);
107  _A += weights_(j, k) * (Sl * dist(j, k) - Sk * dist(j, l)) / (dist(j, k) * dist(j, k));
108  }
109  }
110  _w = -weights_(j, l) * _A / (A * A);
111  }
112  else
113  {
114  _w = 0;
115  w = 0;
116  }
117  jacobian.block(3 * j, i, 3, 1) -= eff_Phi.segment(l * 3, 3) * _w + kinematics[0].jacobian[l].data.block(0, i, 3, 1) * w;
118  }
119  }
120  }
121  }
122 
123  if (debug_) Debug(phi);
124 }
125 
127 {
128  return weights_;
129 }
130 
131 void InteractionMesh::InitializeDebug(std::string ref)
132 {
133  imesh_mark_.header.frame_id = ref;
134  imesh_mark_.ns = GetObjectName();
135  imesh_mark_pub_ = Server::Advertise<visualization_msgs::Marker>(ns_ + "/InteractionMesh", 1, true);
136  if (debug_) HIGHLIGHT("InteractionMesh connectivity is published on ROS topic " << imesh_mark_pub_.getTopic() << ", in reference frame " << ref);
137 }
138 
139 void InteractionMesh::Instantiate(const InteractionMeshInitializer& init)
140 {
141  if (debug_)
142  {
143  InitializeDebug(init.ReferenceFrame);
144  }
145  eff_size_ = frames_.size();
146  weights_.setOnes(eff_size_, eff_size_);
147  if (init.Weights.rows() == eff_size_ * eff_size_)
148  {
149  weights_.array() = init.Weights.array();
150  HIGHLIGHT("Loading iMesh weights.\n"
151  << weights_);
152  }
153 }
154 
156 {
157  scene_ = scene;
158 }
159 
161 {
162  static int textid = 0;
163  {
164  imesh_mark_.scale.x = 0.005;
165  imesh_mark_.color.a = imesh_mark_.color.r = 1;
166  imesh_mark_.type = visualization_msgs::Marker::LINE_LIST;
167  imesh_mark_.pose = geometry_msgs::Pose();
168  imesh_mark_.ns = GetObjectName();
169  imesh_mark_.points.clear();
170  std::vector<geometry_msgs::Point> points(eff_size_);
171  for (int i = 0; i < eff_size_; ++i)
172  {
173  points[i].x = kinematics[0].Phi(i).p[0];
174  points[i].y = kinematics[0].Phi(i).p[1];
175  points[i].z = kinematics[0].Phi(i).p[2];
176  }
177 
178  for (int i = 0; i < eff_size_; ++i)
179  {
180  for (int j = i + 1; j < eff_size_; ++j)
181  {
182  if (weights_(i, j) > 0.0)
183  {
184  imesh_mark_.points.push_back(points[i]);
185  imesh_mark_.points.push_back(points[j]);
186  }
187  }
188  }
189  imesh_mark_.header.stamp = ros::Time::now();
191  }
192  {
193  imesh_mark_.ns = GetObjectName() + "Raw";
194  imesh_mark_.points.clear();
195  std::vector<geometry_msgs::Point> points(eff_size_);
196  for (int i = 0; i < eff_size_; ++i)
197  {
198  points[i].x = phi(i * 3);
199  points[i].y = phi(i * 3 + 1);
200  points[i].z = phi(i * 3 + 2);
201  }
202 
203  for (int i = 0; i < eff_size_; ++i)
204  {
205  for (int j = i + 1; j < eff_size_; ++j)
206  {
207  if (weights_(i, j) > 0.0)
208  {
209  imesh_mark_.points.push_back(points[i]);
210  imesh_mark_.points.push_back(points[j]);
211  }
212  }
213  }
214  imesh_mark_.header.stamp = ros::Time::now();
216 
217  imesh_mark_.points.clear();
218  imesh_mark_.scale.z = 0.05;
219  imesh_mark_.color.a = imesh_mark_.color.r = imesh_mark_.color.g = imesh_mark_.color.b = 1;
220  imesh_mark_.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
221  imesh_mark_.text = std::to_string(textid);
222  imesh_mark_.pose.position = points[textid];
223  imesh_mark_.pose.position.z += 0.05;
224  imesh_mark_.ns = GetObjectName() + "Id";
225  imesh_mark_.header.stamp = ros::Time::now();
227 
228  textid = (textid + 1) % eff_size_;
229  }
230 }
231 
233 {
234  imesh_mark_.points.clear();
235  imesh_mark_.action = visualization_msgs::Marker::DELETE;
236  imesh_mark_.header.stamp = ros::Time::now();
238 }
239 
241 {
242  return 3 * eff_size_;
243 }
244 
245 Eigen::VectorXd InteractionMesh::ComputeLaplace(Eigen::VectorXdRefConst eff_Phi, Eigen::MatrixXdRefConst weights, Eigen::MatrixXd* dist_ptr, Eigen::VectorXd* wsum_ptr)
246 {
247  int N = eff_Phi.rows() / 3;
248  Eigen::VectorXd Phi = Eigen::VectorXd::Zero(N * 3);
249  Eigen::MatrixXd dist = Eigen::MatrixXd::Zero(N, N);
250  Eigen::VectorXd wsum = Eigen::VectorXd::Zero(N);
252  for (int j = 0; j < N; ++j)
253  {
254  for (int l = j + 1; l < N; ++l)
255  {
256  if (!(j >= N && l >= N))
257  {
258  dist(j, l) = dist(l, j) = (eff_Phi.segment(j * 3, 3) - eff_Phi.segment(l * 3, 3)).norm();
259  }
260  }
261  }
263  for (int j = 0; j < N; ++j)
264  {
265  for (int l = 0; l < N; ++l)
266  {
267  if (dist(j, l) > 0 && j != l)
268  {
269  wsum(j) += weights(j, l) / dist(j, l);
270  }
271  }
272  }
274  for (int j = 0; j < N; ++j)
275  {
276  Phi.segment(j * 3, 3) = eff_Phi.segment(j * 3, 3);
277  for (int l = 0; l < N; ++l)
278  {
279  if (j != l)
280  {
281  if (dist(j, l) > 0 && wsum(j) > 0)
282  {
283  Phi.segment(j * 3, 3) -= eff_Phi.segment(l * 3, 3) * weights(j, l) / (dist(j, l) * wsum(j));
284  }
285  }
286  }
287  }
288  if (dist_ptr) *dist_ptr = dist;
289  if (wsum_ptr) *wsum_ptr = wsum;
290  return Phi;
291 }
292 
293 void InteractionMesh::ComputeGoalLaplace(const std::vector<KDL::Frame>& nodes, Eigen::VectorXd& goal, Eigen::MatrixXdRefConst weights)
294 {
295  int N = nodes.size();
296  Eigen::VectorXd eff_Phi(3 * N);
297  for (int i = 0; i < N; ++i)
298  {
299  eff_Phi(i * 3) = nodes[i].p[0];
300  eff_Phi(i * 3 + 1) = nodes[i].p[1];
301  eff_Phi(i * 3 + 2) = nodes[i].p[2];
302  }
303  goal = ComputeLaplace(eff_Phi, weights);
304 }
305 
306 void InteractionMesh::ComputeGoalLaplace(const Eigen::VectorXd& x, Eigen::VectorXd& goal)
307 {
308  scene_->Update(x);
309  Eigen::VectorXd eff_Phi;
310  for (int i = 0; i < eff_size_; ++i)
311  {
312  eff_Phi(i * 3) = kinematics[0].Phi(i).p[0];
313  eff_Phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
314  eff_Phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
315  }
316  goal = ComputeLaplace(eff_Phi, weights_);
317 }
318 
319 void InteractionMesh::SetWeight(int i, int j, double weight)
320 {
321  int M = weights_.cols();
322  if (i < 0 || i >= M || j < 0 || j >= M)
323  {
324  ThrowNamed("Invalid weight element (" << i << "," << j << "). Weight matrix " << M << "x" << M);
325  }
326  if (weight < 0)
327  {
328  ThrowNamed("Invalid weight: " << weight);
329  }
330  weights_(i, j) = weight;
331 }
332 
333 void InteractionMesh::SetWeights(const Eigen::MatrixXd& weights)
334 {
335  int M = weights_.cols();
336  if (weights.rows() != M || weights.cols() != M)
337  {
338  ThrowNamed("Invalid weight matrix (" << weights.rows() << "X" << weights.cols() << "). Has to be" << M << "x" << M);
339  }
340  weights_ = weights;
341 }
342 } // namespace exotica
std::string GetObjectName()
#define HIGHLIGHT(x)
void Debug(Eigen::VectorXdRefConst phi)
void SetWeight(int i, int j, double weight)
void publish(const boost::shared_ptr< M > &message) const
Eigen::MatrixXd GetWeights()
std::vector< KinematicFrameRequest > frames_
Eigen::Ref< Eigen::VectorXd > VectorXdRef
visualization_msgs::Marker imesh_mark_
std::shared_ptr< Scene > ScenePtr
ros::Publisher imesh_mark_pub_
std::string ns_
const Eigen::Ref< const Eigen::MatrixXd > & MatrixXdRefConst
#define ThrowNamed(m)
void Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi) override
void SetWeights(const Eigen::MatrixXd &weights)
const Eigen::Ref< const Eigen::VectorXd > & VectorXdRefConst
void AssignScene(ScenePtr scene) override
void Instantiate(const InteractionMeshInitializer &init) override
TFSIMD_FORCE_INLINE const tfScalar & w() const
Eigen::Ref< Eigen::MatrixXd > MatrixXdRef
void ComputeGoalLaplace(const Eigen::VectorXd &x, Eigen::VectorXd &goal)
static Eigen::VectorXd ComputeLaplace(Eigen::VectorXdRefConst eff_Phi, Eigen::MatrixXdRefConst weights, Eigen::MatrixXd *dist=nullptr, Eigen::VectorXd *wsum=nullptr)
static Time now()
std::string getTopic() const
void InitializeDebug(std::string ref)
REGISTER_TASKMAP_TYPE("InteractionMesh", exotica::InteractionMesh)
double distance(const urdf::Pose &transform)


exotica_core_task_maps
Author(s): Yiming Yang, Michael Camilleri
autogenerated on Sat Apr 10 2021 02:36:09