collision_matrix_model.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, CITEC, Bielefeld University
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Robert Haschke */
36 
37 #include "collision_matrix_model.h"
38 #include <boost/unordered_map.hpp>
39 #include <boost/assign.hpp>
40 #include <QVector>
41 #include <QBrush>
42 #include <QColor>
43 #include <QPalette>
44 #include <QApplication>
45 #include <QItemSelection>
46 #include <QtCore/QRegularExpression>
47 
49 static const boost::unordered_map<moveit_setup_assistant::DisabledReason, QVariant> LONG_REASONS_TO_BRUSH =
50  boost::assign::map_list_of // clang-format off
51  ( moveit_setup_assistant::NEVER, QBrush(QColor("lightgreen")) )
52  ( moveit_setup_assistant::DEFAULT, QBrush(QColor("lightpink")) )
53  ( moveit_setup_assistant::ADJACENT, QBrush(QColor("powderblue")) )
54  ( moveit_setup_assistant::ALWAYS, QBrush(QColor("tomato")) )
55  ( moveit_setup_assistant::USER, QBrush(QColor("yellow")) )
56  ( moveit_setup_assistant::NOT_DISABLED, QBrush()); // clang-format on
57 
58 CollisionMatrixModel::CollisionMatrixModel(const srdf::SRDFWriterPtr& srdf, const std::vector<std::string>& names,
59  QObject* parent)
60  : QAbstractTableModel(parent), srdf(srdf), std_names(names)
61 {
62  int idx = 0;
63  for (std::vector<std::string>::const_iterator it = names.begin(), end = names.end(); it != end; ++it, ++idx)
64  {
65  visual_to_index << idx;
66  q_names << QString::fromStdString(*it);
67  }
68 }
69 
70 int CollisionMatrixModel::rowCount(const QModelIndex& /*parent*/) const
71 {
72  return visual_to_index.size();
73 }
74 
75 int CollisionMatrixModel::columnCount(const QModelIndex& /*parent*/) const
76 {
77  return visual_to_index.size();
78 }
79 
81 {
82  PairMatcher(const std::string& link1, const std::string& link2)
83  : search(link1 < link2 ? std::make_pair(std::cref(link1), std::cref(link2)) :
84  std::make_pair(std::cref(link2), std::cref(link1)))
85  {
86  }
87 
88  bool operator()(const srdf::Model::CollisionPair& pair) const
89  {
90  return (pair.link1_ == search.first && pair.link2_ == search.second) ||
91  (pair.link2_ == search.first && pair.link1_ == search.second);
92  }
93 
94  std::pair<const std::string&, const std::string&> search;
95 };
96 
97 template <typename Container>
98 auto find(Container& pairs, const std::string& link1, const std::string& link2)
99 {
100  return std::find_if(pairs.begin(), pairs.end(), PairMatcher(link1, link2));
101 }
102 
103 bool CollisionMatrixModel::disabledByDefault(const std::string& link1, const std::string& link2) const
104 {
105  for (const auto& name : srdf->no_default_collision_links_)
106  if (name == link1 || name == link2)
107  return true;
108  return false;
109 }
110 
111 QVariant CollisionMatrixModel::data(const QModelIndex& index, int role) const
112 {
113  static std::string enabled = "Explicitly enabled";
114  static std::string disabled = "Disabled by default";
115  static QBrush default_collision_brush(QColor("lightpink").darker(110));
116 
117  if (index.isValid() && index.row() == index.column())
118  {
119  switch (role)
120  {
121  case Qt::BackgroundRole:
122  return QApplication::palette().window();
123  default:
124  return QVariant();
125  }
126  }
127 
128  const std::string* reason = nullptr;
129  int r = visual_to_index[index.row()], c = visual_to_index[index.column()];
130  auto it = find(srdf->disabled_collision_pairs_, std_names[r], std_names[c]);
131  if (it != srdf->disabled_collision_pairs_.end())
132  reason = &it->reason_;
133  else if (find(srdf->enabled_collision_pairs_, std_names[r], std_names[c]) != srdf->enabled_collision_pairs_.end())
134  reason = &enabled;
135  else if (disabledByDefault(std_names[r], std_names[c]))
136  reason = &disabled;
137 
138  switch (role)
139  {
140  case Qt::CheckStateRole:
141  return (!reason || reason == &enabled) ? Qt::Unchecked : Qt::Checked;
142  case Qt::ToolTipRole:
143  return reason ? QString::fromStdString(*reason) : QString();
144  case Qt::BackgroundRole:
145  if (!reason || reason == &enabled)
146  return QVariant();
147  else if (reason == &disabled)
148  return default_collision_brush;
149  else
151  }
152  return QVariant();
153 }
154 
155 bool CollisionMatrixModel::setData(const QModelIndex& index, const QVariant& value, int role)
156 {
157  if (role != Qt::CheckStateRole)
158  return false;
159 
160  bool new_value = (value.toInt() == Qt::Checked);
162  std::string() };
163  if (p.link1_ > p.link2_)
164  std::swap(p.link1_, p.link2_);
165 
166  auto enabled = find(srdf->enabled_collision_pairs_, p.link1_, p.link2_);
167  auto disabled = find(srdf->disabled_collision_pairs_, p.link1_, p.link2_);
168  bool changed = true;
169  if (disabledByDefault(p.link1_, p.link2_))
170  {
171  assert(disabled == srdf->disabled_collision_pairs_.end());
172  auto& pairs = srdf->enabled_collision_pairs_;
173  if (new_value)
174  {
175  if (enabled != pairs.end()) // delete all matching pairs, starting with enabled
176  pairs.erase(std::remove_if(enabled, pairs.end(), PairMatcher(p.link1_, p.link2_)), pairs.end());
177  else
178  changed = false;
179  }
180  else
181  {
183  if (enabled == pairs.end())
184  srdf->enabled_collision_pairs_.push_back(p);
185  else
186  changed = false;
187  }
188  }
189  else
190  {
191  assert(enabled == srdf->enabled_collision_pairs_.end());
192  auto& pairs = srdf->disabled_collision_pairs_;
193  if (new_value)
194  {
196  if (disabled == pairs.end())
197  pairs.push_back(p);
198  else
199  changed = false;
200  }
201  else
202  {
203  if (disabled != pairs.end()) // delete all matching pairs, starting with disabled
204  pairs.erase(std::remove_if(disabled, pairs.end(), PairMatcher(p.link1_, p.link2_)), pairs.end());
205  else
206  changed = false;
207  }
208  }
209 
210  if (changed)
211  {
212  QModelIndex mirror = this->index(index.column(), index.row());
213  Q_EMIT dataChanged(index, index);
214  Q_EMIT dataChanged(mirror, mirror);
215  }
216  return changed;
217 }
218 
219 void CollisionMatrixModel::setEnabled(const QItemSelection& selection, bool value)
220 {
221  // perform changes without signalling
222  QItemSelection changes;
223  blockSignals(true);
224  for (const auto& range : selection)
225  {
226  setEnabled(range.indexes(), value);
227 
228  const QModelIndex& top_left = range.topLeft();
229  const QModelIndex& bottom_right = range.bottomRight();
230  changes.select(top_left, bottom_right);
231  changes.select(createIndex(top_left.column(), top_left.row()),
232  createIndex(bottom_right.column(), bottom_right.row()));
233  }
234  blockSignals(false);
235 
236  // emit changes
237  for (const auto& range : changes)
238  Q_EMIT dataChanged(range.topLeft(), range.bottomRight());
239 }
240 
241 void CollisionMatrixModel::setEnabled(const QModelIndexList& indexes, bool value)
242 {
243  for (const auto idx : indexes)
244  setData(idx, value ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
245 }
246 
247 void CollisionMatrixModel::setFilterRegExp(const QString& filter)
248 {
249  beginResetModel();
250  QRegularExpression regexp(filter);
251  visual_to_index.clear();
252  for (int idx = 0, end = q_names.size(); idx != end; ++idx)
253  {
254  if (q_names[idx].contains(regexp))
255  visual_to_index << idx;
256  }
257  endResetModel();
258 }
259 
260 QVariant CollisionMatrixModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
261 {
262  if (role == Qt::DisplayRole)
263  return q_names[visual_to_index[section]];
264  return QVariant();
265 }
266 
267 Qt::ItemFlags CollisionMatrixModel::flags(const QModelIndex& index) const
268 {
269  if (!index.isValid())
270  return Qt::NoItemFlags;
271 
272  Qt::ItemFlags f = QAbstractTableModel::flags(index);
273  if (index.row() != index.column())
274  f |= Qt::ItemIsUserCheckable;
275  return f;
276 }
moveit_setup_assistant::NEVER
@ NEVER
Definition: compute_default_collisions.h:54
CollisionMatrixModel::headerData
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Definition: collision_matrix_model.cpp:260
CollisionMatrixModel::setFilterRegExp
void setFilterRegExp(const QString &filter)
Definition: collision_matrix_model.cpp:247
r
r
moveit_setup_assistant::ALWAYS
@ ALWAYS
Definition: compute_default_collisions.h:57
CollisionMatrixModel::setEnabled
void setEnabled(const QItemSelection &selection, bool value)
Definition: collision_matrix_model.cpp:219
PairMatcher::PairMatcher
PairMatcher(const std::string &link1, const std::string &link2)
Definition: collision_matrix_model.cpp:82
moveit_setup_assistant::DEFAULT
@ DEFAULT
Definition: compute_default_collisions.h:55
CollisionMatrixModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: collision_matrix_model.cpp:70
moveit_setup_assistant::USER
@ USER
Definition: compute_default_collisions.h:58
moveit_setup_assistant::ADJACENT
@ ADJACENT
Definition: compute_default_collisions.h:56
CollisionMatrixModel::setData
bool setData(const QModelIndex &, const QVariant &value, int role) override
Definition: collision_matrix_model.cpp:155
CollisionMatrixModel::disabledByDefault
bool disabledByDefault(const std::string &link1, const std::string &link2) const
Definition: collision_matrix_model.cpp:103
collision_matrix_model.h
srdf::Model::CollisionPair::link2_
std::string link2_
PairMatcher::operator()
bool operator()(const srdf::Model::CollisionPair &pair) const
Definition: collision_matrix_model.cpp:88
LONG_REASONS_TO_BRUSH
static const boost::unordered_map< moveit_setup_assistant::DisabledReason, QVariant > LONG_REASONS_TO_BRUSH
Boost mapping of reasons to a background color.
Definition: collision_matrix_model.cpp:49
c
c
moveit_setup_assistant::NOT_DISABLED
@ NOT_DISABLED
Definition: compute_default_collisions.h:59
value
float value
CollisionMatrixModel::std_names
const std::vector< std::string > std_names
Definition: collision_matrix_model.h:73
name
name
CollisionMatrixModel::q_names
QList< QString > q_names
Definition: collision_matrix_model.h:74
CollisionMatrixModel::visual_to_index
QList< int > visual_to_index
Definition: collision_matrix_model.h:75
moveit_setup_assistant::disabledReasonToString
const std::string disabledReasonToString(DisabledReason reason)
Converts a reason for disabling a link pair into a string.
Definition: compute_default_collisions.cpp:685
f
f
PairMatcher::search
std::pair< const std::string &, const std::string & > search
Definition: collision_matrix_model.cpp:94
std
srdf
index
unsigned int index
PairMatcher
Definition: collision_matrix_model.cpp:80
CollisionMatrixModel::flags
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: collision_matrix_model.cpp:267
find
auto find(Container &pairs, const std::string &link1, const std::string &link2)
Definition: collision_matrix_model.cpp:98
CollisionMatrixModel::data
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: collision_matrix_model.cpp:111
CollisionMatrixModel::CollisionMatrixModel
CollisionMatrixModel(const srdf::SRDFWriterPtr &srdf, const std::vector< std::string > &names, QObject *parent=nullptr)
Definition: collision_matrix_model.cpp:58
srdf::Model::CollisionPair
moveit_setup_assistant::disabledReasonFromString
DisabledReason disabledReasonFromString(const std::string &reason)
Converts a string reason for disabling a link pair into a struct data type.
Definition: compute_default_collisions.cpp:693
CollisionMatrixModel::columnCount
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: collision_matrix_model.cpp:75
srdf::Model::CollisionPair::link1_
std::string link1_
srdf::SRDFWriterPtr
std::shared_ptr< SRDFWriter > SRDFWriterPtr


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Sat May 3 2025 02:28:04