40 #include "ui_motion_planning_rviz_plugin_frame_joints.h"
44 #include <QMouseEvent>
50 : QAbstractTableModel(parent), robot_state_(robot_state), jmg_(nullptr)
52 if (robot_state_.
getRobotModel()->hasJointModelGroup(group_name))
53 jmg_ = robot_state_.
getRobotModel()->getJointModelGroup(group_name);
76 return Qt::ItemFlags();
78 Qt::ItemFlags
f = QAbstractTableModel::flags(index);
82 f.setFlag(Qt::ItemIsEnabled, is_editable);
83 if (index.column() == 1)
84 f.setFlag(Qt::ItemIsEditable, is_editable);
94 switch (index.column())
101 case Qt::TextAlignmentRole:
102 return Qt::AlignLeft;
111 case Qt::DisplayRole:
123 return QPointF(bounds->min_position_, bounds->max_position_);
125 case Qt::TextAlignmentRole:
126 return Qt::AlignLeft;
135 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
136 return section == 0 ?
"Joint Name" :
"Value";
137 return QAbstractTableModel::headerData(section, orientation, role);
142 if (index.column() != 1 || role != Qt::EditRole)
147 if (!value.canConvert<
double>())
151 double v = value.toDouble(&ok);
161 dataChanged(index, index);
167 if (!index.isValid())
170 return robot_state_.
getRobotModel()->getJointOfVariable(var_idx);
174 const QModelIndex& index)
const
190 dataChanged(index(0, 1), index(
rowCount() - 1, 1));
194 : QWidget(parent), ui_(new
Ui::MotionPlanningFrameJointsUI()), planning_display_(display)
200 svd_.setThreshold(0.001);
210 ui_->joints_view_->setModel(
nullptr);
211 start_state_handler_.reset();
212 goal_state_handler_.reset();
213 start_state_model_.reset();
214 goal_state_model_.reset();
218 const std::string& group_name,
const robot_interaction::InteractionHandlerPtr& start_state_handler,
219 const robot_interaction::InteractionHandlerPtr& goal_state_handler)
224 start_state_handler_ = start_state_handler;
225 goal_state_handler_ = goal_state_handler;
226 start_state_model_ = std::make_unique<JMGItemModel>(*start_state_handler_->getState(), group_name,
this);
227 goal_state_model_ = std::make_unique<JMGItemModel>(*goal_state_handler_->getState(), group_name,
this);
230 connect(start_state_model_.get(), &JMGItemModel::dataChanged,
this, [
this]() {
231 if (!ignore_state_changes_)
232 planning_display_->setQueryStartState(start_state_model_->getRobotState());
234 connect(goal_state_model_.get(), &JMGItemModel::dataChanged,
this, [
this]() {
235 if (!ignore_state_changes_)
236 planning_display_->setQueryGoalState(goal_state_model_->getRobotState());
246 if (!start_state_model_ || !start_state_handler_)
248 ignore_state_changes_ =
true;
249 start_state_model_->updateRobotState(*start_state_handler_->getState());
250 ignore_state_changes_ =
false;
257 if (!goal_state_model_ || !goal_state_handler_)
259 ignore_state_changes_ =
true;
260 goal_state_model_->updateRobotState(*goal_state_handler_->getState());
261 ignore_state_changes_ =
false;
268 ui_->joints_view_->setModel(model);
269 ui_->joints_view_label_->setText(
270 QString(
"Group joints of %1 state").arg(model == start_state_model_.get() ?
"start" :
"goal"));
275 if (model == start_state_model_.get())
288 static Eigen::Index findMatching(
const Eigen::VectorXd& key,
const Eigen::MatrixXd& haystack,
289 const Eigen::VectorXi& available,
double& sign)
291 Eigen::Index result = available.array().maxCoeff();
292 double best_match = 0.0;
293 for (
unsigned int i = 0; i < available.rows(); ++i)
295 int index = available[i];
298 if (index >= haystack.cols())
300 double match = haystack.col(available[i]).transpose() * key;
301 double abs_match = std::abs(match);
302 if (abs_match > 0.5 && abs_match > best_match)
304 best_match = abs_match;
306 sign = match > 0 ? 1.0 : -1.0;
319 Eigen::MatrixXd jacobian;
322 Eigen::Vector3d::Zero(), jacobian,
false))
325 svd_.compute(jacobian, Eigen::ComputeFullV);
326 Eigen::Index rank = svd_.rank();
327 std::size_t ns_dim = svd_.cols() - rank;
328 Eigen::MatrixXd ns(svd_.cols(), ns_dim);
329 Eigen::VectorXi available(ns_dim);
330 for (std::size_t j = 0; j < ns_dim; ++j)
333 ns_sliders_.reserve(ns_dim);
335 for (; i < ns_dim; ++i)
337 if (i >= ns_sliders_.size())
339 ns_sliders_[i]->show();
343 const Eigen::VectorXd& current = svd_.matrixV().col(rank + i);
344 Eigen::Index index = findMatching(current, nullspace_, available, sign);
345 ns.col(index).noalias() = sign * current;
346 available[index] = -1;
353 nullspace_.resize(0, 0);
356 ui_->dummy_ns_slider_->setVisible(i == 0);
359 for (; i < ns_sliders_.size(); ++i)
360 ns_sliders_[i]->hide();
366 slider->setOrientation(Qt::Horizontal);
368 slider->setToolTip(QString(
"Nullspace dim #%1").arg(i));
369 ui_->nullspace_layout_->addWidget(slider);
370 connect(slider, SIGNAL(triggered(
double)),
this, SLOT(
jogNullspace(
double)));
379 std::size_t index = std::find(ns_sliders_.begin(), ns_sliders_.end(), sender()) - ns_sliders_.begin();
380 if (
static_cast<int>(index) >= nullspace_.cols())
387 Eigen::VectorXd values;
389 values += value * nullspace_.col(index);
398 QStyle* style = option.widget ? option.widget->style() : QApplication::style();
399 QStyleOptionViewItem style_option = option;
400 initStyleOption(&style_option, index);
402 if (index.column() == 1)
405 double value = index.data().toDouble();
406 if (joint_type.isValid())
408 switch (joint_type.toInt())
411 style_option.text = option.locale.toString(value * 180 / M_PI,
'f', 0).append(
"°");
414 style_option.text = option.locale.toString(value,
'f', 3).append(
"m");
422 if (vbounds.isValid())
424 QPointF bounds = vbounds.toPointF();
425 const double min = bounds.x();
426 const double max = bounds.y();
428 QStyleOptionProgressBar opt;
429 opt.rect = option.rect;
432 opt.progress = 1000. * (value - min) / (max - min);
433 opt.text = style_option.text;
434 opt.textAlignment = style_option.displayAlignment;
435 opt.textVisible =
true;
436 style->drawControl(QStyle::CE_ProgressBar, &opt, painter);
441 style->drawControl(QStyle::CE_ItemViewItem, &style_option, painter, option.widget);
445 const QModelIndex& index)
const
448 if (index.column() == 1)
451 if (vbounds.isValid())
453 QPointF bounds = vbounds.toPointF();
454 double min = bounds.x();
455 double max = bounds.y();
465 const_cast<QAbstractItemModel*
>(index.model())->setData(index, value, Qt::EditRole);
470 return QStyledItemDelegate::createEditor(parent, option, index);
473 void ProgressBarDelegate::commitAndCloseEditor()
486 if (event->type() == QEvent::MouseButtonPress)
488 QAbstractItemView*
view = qobject_cast<QAbstractItemView*>(parent());
489 QModelIndex index =
view->indexAt(
static_cast<QMouseEvent*
>(event)->pos());
490 if (index.flags() & Qt::ItemIsEditable)
492 view->setCurrentIndex(index);
501 : QWidget(parent), min_(min), max_(max), digits_(digits)
504 if (QApplication::mouseButtons() & Qt::LeftButton)
510 QPainter painter(
this);
512 QStyleOptionProgressBar opt;
514 opt.palette = palette();
517 opt.progress = 1000. * (value_ - min_) / (max_ - min_);
518 opt.text = QLocale().toString(value_,
'f', digits_);
519 opt.textAlignment = Qt::AlignRight;
520 opt.textVisible =
true;
521 style()->drawControl(QStyle::CE_ProgressBar, &opt, &painter);
526 if (event->button() == Qt::LeftButton)
532 double v = std::min(max_, std::max(min_, min_ + event->x() * (max_ - min_) / width()));
544 if (event->button() == Qt::LeftButton)
560 timer_interval_ = ms;
565 QSlider::setRange(-resolution, +resolution);
575 QSlider::timerEvent(event);
576 if (event->timerId() == timer_id_)
582 QSlider::mousePressEvent(event);
583 timer_id_ = startTimer(timer_interval_);
588 killTimer(timer_id_);
589 QSlider::mouseReleaseEvent(event);
bool isChain() const
Check if this group is a linear chain.
const std::vector< const LinkModel * > & getLinkModels() const
Get the links that are part of this joint group.
unsigned int getVariableCount() const
Get the number of variables that describe this joint group. This includes variables necessary for mim...
const std::vector< int > & getVariableIndexList() const
Get the index locations in the complete robot state for all the variables in this group.
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
size_t getFirstVariableIndex() const
Get the index of this joint's first variable within the full robot state.
bool isPassive() const
Check if this joint is passive.
bool enforcePositionBounds(double *values) const
Force the specified values to be inside bounds and normalized. Quaternions are normalized,...
const VariableBounds & getVariableBounds(const std::string &variable) const
Get the bounds for a variable. Throw an exception if the variable was not found.
JointType getType() const
Get the type of joint.
const JointModel * getMimic() const
Get the joint this one is mimicking.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
void setVariablePositions(const double *position)
It is assumed positions is an array containing the new positions for all variables in this state....
bool getJacobian(const JointModelGroup *group, const LinkModel *link, const Eigen::Vector3d &reference_point_position, Eigen::MatrixXd &jacobian, bool use_quaternion_representation=false) const
Compute the Jacobian with reference to a particular point on a given link, for a specified group.
void setVariablePosition(const std::string &variable, double value)
Set the position of a single variable. An exception is thrown if the variable name is not known.
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
Given positions for the variables that make up a group, in the order found in the group (including va...
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
For a given group, copy the position values of the variables that make up the group into another loca...
const RobotModelConstPtr & getRobotModel() const
Get the robot model this state is constructed for.
void harmonizePositions()
Call harmonizePosition() for all joints / all joints in group / given joint.
double * getVariablePositions()
Get a raw pointer to the positions of the variables stored in this state. Use carefully....
void updateLinkTransforms()
Update the reference frame transforms for links. This call is needed before using the transforms of l...
double getVariablePosition(const std::string &variable) const
Get the position of a particular variable. An exception is thrown if the variable is not known.
std::size_t getVariableCount() const
Get the number of variables that make up this state.
const std::vector< std::string > & getVariableNames() const
Get the names of the variables that make up this state, in the order they are stored in memory.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
JMGItemModel(const moveit::core::RobotState &robot_state, const std::string &group_name, QObject *parent=nullptr)
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant data(const QModelIndex &index, int role) const override
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
const moveit::core::JointModelGroup * getJointModelGroup() const
moveit::core::RobotState & getRobotState()
void updateRobotState(const moveit::core::RobotState &state)
call this on any external change of the RobotState
int rowCount(const QModelIndex &parent=QModelIndex()) const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Slider that jumps back to zero.
void setResolution(unsigned int resolution)
void setTimerInterval(int ms)
void triggered(double value)
JogSlider(QWidget *parent=nullptr)
void mousePressEvent(QMouseEvent *event) override
void mouseReleaseEvent(QMouseEvent *event) override
void setMaximum(double value)
void timerEvent(QTimerEvent *event) override
void setQueryGoalState(const moveit::core::RobotState &goal)
void setQueryStartState(const moveit::core::RobotState &start)
Delegate to show the joint value as with a progress bar indicator between min and max.
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Number editor via progress bar dragging.
void mouseMoveEvent(QMouseEvent *event) override
ProgressBarEditor(QWidget *parent=nullptr, double min=-1.0, double max=0.0, int digits=0)
Create a progressbar-like slider for editing values in range mix..max.
void mouseReleaseEvent(QMouseEvent *event) override
void paintEvent(QPaintEvent *event) override
void valueChanged(double value)
void mousePressEvent(QMouseEvent *event) override
void update(moveit::core::RobotState *self, bool force, std::string &category)