40#include "ui_motion_planning_rviz_plugin_frame_joints.h"
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);
60 return robot_state_.getVariableCount();
64 return jmg_->getVariableCount();
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);
93 int idx = jmg_ ? jmg_->getVariableIndexList()[index.row()] : index.row();
94 switch (index.column())
100 return QString::fromStdString(robot_state_.getVariableNames()[idx]);
101 case Qt::TextAlignmentRole:
102 return Qt::AlignLeft;
107 double value = robot_state_.getVariablePosition(idx);
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)
145 int var_idx = jmg_ ? jmg_->getVariableIndexList()[index.row()] : index.row();
147 if (!value.canConvert<
double>())
151 double v = value.toDouble(&ok);
159 robot_state_.setVariablePosition(var_idx, v);
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())
277 planning_display_->setQueryStartState(model->
getRobotState());
281 planning_display_->setQueryGoalState(model->
getRobotState());
288static 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);
473void ProgressBarDelegate::commitAndCloseEditor()
486 if (event->type() == QEvent::MouseButtonPress)
488 QAbstractItemView* view = qobject_cast<QAbstractItemView*>(parent());
489#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
490 QModelIndex index = view->indexAt(
static_cast<QMouseEvent*
>(event)->position().toPoint());
492 QModelIndex index = view->indexAt(
static_cast<QMouseEvent*
>(event)->pos());
494 if (index.flags() & Qt::ItemIsEditable)
496 view->setCurrentIndex(index);
505 : QWidget(parent), min_(min), max_(max), digits_(digits)
508 if (QApplication::mouseButtons() & Qt::LeftButton)
514 QPainter painter(
this);
516 QStyleOptionProgressBar opt;
518 opt.palette = palette();
521 opt.progress = 1000. * (value_ - min_) / (max_ - min_);
522 opt.text = QLocale().toString(value_,
'f', digits_);
523 opt.textAlignment = Qt::AlignRight;
524 opt.textVisible =
true;
525 style()->drawControl(QStyle::CE_ProgressBar, &opt, &painter);
530 if (event->button() == Qt::LeftButton)
536#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
537 double v = std::min(max_, std::max(min_, min_ + event->position().x() * (max_ - min_) / width()));
539 double v = std::min(max_, std::max(min_, min_ + event->x() * (max_ - min_) / width()));
552 if (event->button() == Qt::LeftButton)
568 timer_interval_ = ms;
573 QSlider::setRange(-resolution, +resolution);
583 QSlider::timerEvent(event);
584 if (event->timerId() == timer_id_)
590 QSlider::mousePressEvent(event);
591 timer_id_ = startTimer(timer_interval_);
596 killTimer(timer_id_);
597 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.
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.
const JointModel * getMimic() const
Get the joint this one is mimicking.
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.
Representation of a robot's state. This includes position, velocity, acceleration and effort.
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 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...
void harmonizePositions()
Call harmonizePosition() for all joints / all joints in group / given joint.
const RobotModelConstPtr & getRobotModel() const
Get the robot model this state is constructed for.
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...
int columnCount(const QModelIndex &parent=QModelIndex()) const override
const moveit::core::JointModelGroup * getJointModelGroup() const
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
moveit::core::RobotState & getRobotState()
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
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
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