753 lines
24 KiB
C++
753 lines
24 KiB
C++
|
/*
|
||
|
* Copyright (C) 2012 Open Source Robotics Foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
// Ensure that Winsock2.h is included before Windows.h, which can get
|
||
|
// pulled in by anybody (e.g., Boost).
|
||
|
#include <Winsock2.h>
|
||
|
#endif
|
||
|
|
||
|
#include "gazebo/transport/Node.hh"
|
||
|
#include "gazebo/transport/TransportIface.hh"
|
||
|
#include "gazebo/gui/GuiIface.hh"
|
||
|
#include "gazebo/gui/JointControlWidget.hh"
|
||
|
#include "gazebo/gui/JointControlWidgetPrivate.hh"
|
||
|
|
||
|
using namespace gazebo;
|
||
|
using namespace gui;
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointForceControl::JointForceControl(const std::string &_name,
|
||
|
QGridLayout *_layout, QWidget *_parent, int _index)
|
||
|
: QWidget(_parent),
|
||
|
dataPtr(new JointForceControlPrivate())
|
||
|
{
|
||
|
this->dataPtr->name = _name;
|
||
|
this->dataPtr->forceSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->forceSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->forceSpin->setSingleStep(0.001);
|
||
|
this->dataPtr->forceSpin->setDecimals(3);
|
||
|
this->dataPtr->forceSpin->setValue(0.000);
|
||
|
|
||
|
_layout->addWidget(this->dataPtr->forceSpin, _index, 2);
|
||
|
|
||
|
connect(this->dataPtr->forceSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnChanged(double)));
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointForceControl::~JointForceControl()
|
||
|
{
|
||
|
this->hide();
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointForceControl::Reset()
|
||
|
{
|
||
|
this->dataPtr->forceSpin->setValue(0.0);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointForceControl::OnChanged(double _value)
|
||
|
{
|
||
|
emit changed(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointPIDPosControl::JointPIDPosControl(const std::string &_name,
|
||
|
QGridLayout *_layout, QWidget *_parent, int _index)
|
||
|
: QWidget(_parent),
|
||
|
dataPtr(new JointPIDPosControlPrivate())
|
||
|
{
|
||
|
this->dataPtr->name = _name;
|
||
|
this->dataPtr->posSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->posSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->posSpin->setSingleStep(0.001);
|
||
|
this->dataPtr->posSpin->setDecimals(3);
|
||
|
this->dataPtr->posSpin->setValue(0.000);
|
||
|
|
||
|
this->dataPtr->pGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->pGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->pGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->pGainSpin->setDecimals(3);
|
||
|
this->dataPtr->pGainSpin->setValue(1.000);
|
||
|
|
||
|
this->dataPtr->iGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->iGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->iGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->iGainSpin->setDecimals(3);
|
||
|
this->dataPtr->iGainSpin->setValue(0.100);
|
||
|
|
||
|
this->dataPtr->dGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->dGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->dGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->dGainSpin->setDecimals(3);
|
||
|
this->dataPtr->dGainSpin->setValue(0.010);
|
||
|
|
||
|
_layout->addWidget(this->dataPtr->posSpin, _index, 2);
|
||
|
_layout->addWidget(this->dataPtr->pGainSpin, _index, 3);
|
||
|
_layout->addWidget(this->dataPtr->iGainSpin, _index, 4);
|
||
|
_layout->addWidget(this->dataPtr->dGainSpin, _index, 5);
|
||
|
|
||
|
connect(this->dataPtr->posSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnChanged(double)));
|
||
|
connect(this->dataPtr->pGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnPChanged(double)));
|
||
|
connect(this->dataPtr->iGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnIChanged(double)));
|
||
|
connect(this->dataPtr->dGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnDChanged(double)));
|
||
|
|
||
|
this->dataPtr->radians = true;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointPIDPosControl::~JointPIDPosControl()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::Reset()
|
||
|
{
|
||
|
this->dataPtr->posSpin->setValue(0.0);
|
||
|
this->dataPtr->pGainSpin->setValue(1.000);
|
||
|
this->dataPtr->iGainSpin->setValue(0.100);
|
||
|
this->dataPtr->dGainSpin->setValue(0.010);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::SetToDegrees()
|
||
|
{
|
||
|
if (this->dataPtr->radians)
|
||
|
{
|
||
|
this->dataPtr->radians = false;
|
||
|
this->dataPtr->posSpin->setValue(GZ_RTOD(this->dataPtr->posSpin->value()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::SetToRadians()
|
||
|
{
|
||
|
if (!this->dataPtr->radians)
|
||
|
{
|
||
|
this->dataPtr->radians = true;
|
||
|
this->dataPtr->posSpin->setValue(GZ_DTOR(this->dataPtr->posSpin->value()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::OnChanged(double _value)
|
||
|
{
|
||
|
if (this->dataPtr->radians)
|
||
|
emit changed(_value, this->dataPtr->name);
|
||
|
else
|
||
|
emit changed(GZ_DTOR(_value), this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::OnPChanged(double _value)
|
||
|
{
|
||
|
emit pChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::OnIChanged(double _value)
|
||
|
{
|
||
|
emit iChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDPosControl::OnDChanged(double _value)
|
||
|
{
|
||
|
emit dChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointPIDVelControl::JointPIDVelControl(const std::string &_name,
|
||
|
QGridLayout *_layout, QWidget *_parent, int _index)
|
||
|
: QWidget(_parent),
|
||
|
dataPtr(new JointPIDVelControlPrivate())
|
||
|
{
|
||
|
this->dataPtr->name = _name;
|
||
|
this->dataPtr->posSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->posSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->posSpin->setSingleStep(0.001);
|
||
|
this->dataPtr->posSpin->setDecimals(3);
|
||
|
this->dataPtr->posSpin->setValue(0.000);
|
||
|
|
||
|
this->dataPtr->pGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->pGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->pGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->pGainSpin->setDecimals(3);
|
||
|
this->dataPtr->pGainSpin->setValue(1.000);
|
||
|
|
||
|
this->dataPtr->iGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->iGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->iGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->iGainSpin->setDecimals(3);
|
||
|
this->dataPtr->iGainSpin->setValue(0.100);
|
||
|
|
||
|
this->dataPtr->dGainSpin = new QDoubleSpinBox;
|
||
|
this->dataPtr->dGainSpin->setRange(-IGN_DBL_MAX, IGN_DBL_MAX);
|
||
|
this->dataPtr->dGainSpin->setSingleStep(0.01);
|
||
|
this->dataPtr->dGainSpin->setDecimals(3);
|
||
|
this->dataPtr->dGainSpin->setValue(0.010);
|
||
|
|
||
|
_layout->addWidget(this->dataPtr->posSpin, _index, 2);
|
||
|
_layout->addWidget(this->dataPtr->pGainSpin, _index, 3);
|
||
|
_layout->addWidget(this->dataPtr->iGainSpin, _index, 4);
|
||
|
_layout->addWidget(this->dataPtr->dGainSpin, _index, 5);
|
||
|
|
||
|
connect(this->dataPtr->posSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnChanged(double)));
|
||
|
connect(this->dataPtr->pGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnPChanged(double)));
|
||
|
connect(this->dataPtr->iGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnIChanged(double)));
|
||
|
connect(this->dataPtr->dGainSpin, SIGNAL(valueChanged(double)),
|
||
|
this, SLOT(OnDChanged(double)));
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointPIDVelControl::~JointPIDVelControl()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDVelControl::Reset()
|
||
|
{
|
||
|
this->dataPtr->posSpin->setValue(0.0);
|
||
|
this->dataPtr->pGainSpin->setValue(1.000);
|
||
|
this->dataPtr->iGainSpin->setValue(0.100);
|
||
|
this->dataPtr->dGainSpin->setValue(0.010);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDVelControl::OnChanged(double _value)
|
||
|
{
|
||
|
emit changed(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDVelControl::OnPChanged(double _value)
|
||
|
{
|
||
|
emit pChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDVelControl::OnIChanged(double _value)
|
||
|
{
|
||
|
emit iChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointPIDVelControl::OnDChanged(double _value)
|
||
|
{
|
||
|
emit dChanged(_value, this->dataPtr->name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::SetModelName(const std::string &_modelName)
|
||
|
{
|
||
|
if (this->dataPtr->jointPub)
|
||
|
{
|
||
|
this->dataPtr->jointPub->Fini();
|
||
|
this->dataPtr->jointPub.reset();
|
||
|
}
|
||
|
|
||
|
msgs::Model modelMsg;
|
||
|
|
||
|
this->dataPtr->modelLabel->setText(
|
||
|
QString::fromStdString(std::string("Model: ")));
|
||
|
|
||
|
// Only request info if the model has a name.
|
||
|
if (!_modelName.empty())
|
||
|
{
|
||
|
this->dataPtr->jointPub = this->dataPtr->node->Advertise<msgs::JointCmd>(
|
||
|
std::string("~/") + _modelName + "/joint_cmd");
|
||
|
|
||
|
boost::shared_ptr<msgs::Response> response = transport::request(
|
||
|
gui::get_world(), "entity_info", _modelName);
|
||
|
|
||
|
if (response->response() != "error" &&
|
||
|
response->type() == modelMsg.GetTypeName())
|
||
|
{
|
||
|
modelMsg.ParseFromString(response->serialized_data());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->dataPtr->modelLabel->setText(QString::fromStdString(
|
||
|
std::string("Model: ") + modelMsg.name()));
|
||
|
|
||
|
this->LayoutForceTab(modelMsg);
|
||
|
|
||
|
this->LayoutPositionTab(modelMsg);
|
||
|
|
||
|
this->LayoutVelocityTab(modelMsg);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointControlWidget::JointControlWidget(QWidget *_parent)
|
||
|
: QWidget(_parent),
|
||
|
dataPtr(new JointControlWidgetPrivate())
|
||
|
{
|
||
|
this->setObjectName("jointControl");
|
||
|
|
||
|
this->setWindowTitle("Joint Control");
|
||
|
this->dataPtr->node = transport::NodePtr(new transport::Node());
|
||
|
this->dataPtr->node->TryInit(common::Time::Maximum());
|
||
|
|
||
|
this->dataPtr->tabWidget = new QTabWidget;
|
||
|
this->dataPtr->tabWidget->setObjectName("embeddedTab");
|
||
|
|
||
|
// Create the Force control scroll area
|
||
|
this->dataPtr->forceGridLayout = new QGridLayout;
|
||
|
this->AddScrollTab(
|
||
|
this->dataPtr->tabWidget, this->dataPtr->forceGridLayout, tr("Force"));
|
||
|
|
||
|
// Create a PID Pos scroll area
|
||
|
this->dataPtr->positionGridLayout = new QGridLayout;
|
||
|
this->AddScrollTab(this->dataPtr->tabWidget,
|
||
|
this->dataPtr->positionGridLayout, tr("Position"));
|
||
|
|
||
|
// Create a PID Vel scroll area
|
||
|
this->dataPtr->velocityGridLayout = new QGridLayout;
|
||
|
this->AddScrollTab(this->dataPtr->tabWidget,
|
||
|
this->dataPtr->velocityGridLayout, tr("Velocity"));
|
||
|
|
||
|
// Add the the force and pid scroll areas to the tab
|
||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||
|
|
||
|
QHBoxLayout *hboxLayout = new QHBoxLayout;
|
||
|
|
||
|
this->dataPtr->modelLabel = new QLabel(tr("Model: "));
|
||
|
hboxLayout->addWidget(this->dataPtr->modelLabel);
|
||
|
|
||
|
hboxLayout->addItem(new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Minimum));
|
||
|
QPushButton *resetButton = new QPushButton(tr("Reset"));
|
||
|
connect(resetButton, SIGNAL(clicked()), this, SLOT(OnReset()));
|
||
|
|
||
|
hboxLayout->addWidget(resetButton);
|
||
|
|
||
|
mainLayout->addLayout(hboxLayout);
|
||
|
mainLayout->addWidget(this->dataPtr->tabWidget);
|
||
|
mainLayout->setContentsMargins(4, 4, 4, 4);
|
||
|
|
||
|
this->setLayout(mainLayout);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
JointControlWidget::~JointControlWidget()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnReset()
|
||
|
{
|
||
|
for (std::map<std::string, JointForceControl*>::iterator iter =
|
||
|
this->dataPtr->sliders.begin();
|
||
|
iter != this->dataPtr->sliders.end(); ++iter)
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(iter->first);
|
||
|
msg.set_reset(true);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
iter->second->Reset();
|
||
|
}
|
||
|
|
||
|
for (std::map<std::string, JointPIDPosControl*>::iterator iter =
|
||
|
this->dataPtr->pidPosSliders.begin();
|
||
|
iter != this->dataPtr->pidPosSliders.end(); ++iter)
|
||
|
{
|
||
|
iter->second->Reset();
|
||
|
}
|
||
|
|
||
|
for (std::map<std::string, JointPIDVelControl*>::iterator iter =
|
||
|
this->dataPtr->pidVelSliders.begin();
|
||
|
iter != this->dataPtr->pidVelSliders.end(); ++iter)
|
||
|
{
|
||
|
iter->second->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnForceChanged(double _value, const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointForceControl*>::iterator iter;
|
||
|
iter = this->dataPtr->sliders.find(_name);
|
||
|
if (iter != this->dataPtr->sliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.set_force(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnPIDPosChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDPosControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidPosSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidPosSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_position()->set_target(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnPPosGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDPosControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidPosSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidPosSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_position()->set_p_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnDPosGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDPosControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidPosSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidPosSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_position()->set_d_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnIPosGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDPosControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidPosSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidPosSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_position()->set_i_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnPIDPosUnitsChanged(int _index)
|
||
|
{
|
||
|
std::map<std::string, JointPIDPosControl*>::iterator iter;
|
||
|
for (iter = this->dataPtr->pidPosSliders.begin();
|
||
|
iter != this->dataPtr->pidPosSliders.end(); ++iter)
|
||
|
{
|
||
|
if (_index == 0)
|
||
|
iter->second->SetToRadians();
|
||
|
else
|
||
|
iter->second->SetToDegrees();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnPIDVelChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDVelControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidVelSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidVelSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_velocity()->set_target(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnPVelGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDVelControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidVelSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidVelSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_velocity()->set_p_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnDVelGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDVelControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidVelSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidVelSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_velocity()->set_d_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::OnIVelGainChanged(double _value,
|
||
|
const std::string &_name)
|
||
|
{
|
||
|
std::map<std::string, JointPIDVelControl*>::iterator iter;
|
||
|
iter = this->dataPtr->pidVelSliders.find(_name);
|
||
|
if (iter != this->dataPtr->pidVelSliders.end())
|
||
|
{
|
||
|
msgs::JointCmd msg;
|
||
|
msg.set_name(_name);
|
||
|
msg.mutable_velocity()->set_i_gain(_value);
|
||
|
this->dataPtr->jointPub->Publish(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::AddScrollTab(QTabWidget *_tabPane,
|
||
|
QGridLayout *_tabLayout, const QString &_name)
|
||
|
{
|
||
|
_tabLayout->setSizeConstraint(QLayout::SetMinimumSize);
|
||
|
|
||
|
QScrollArea *scrollArea = new QScrollArea(this);
|
||
|
scrollArea->setLineWidth(0);
|
||
|
scrollArea->setFrameShape(QFrame::NoFrame);
|
||
|
scrollArea->setFrameShadow(QFrame::Plain);
|
||
|
scrollArea->setSizePolicy(QSizePolicy::Minimum,
|
||
|
QSizePolicy::Minimum);
|
||
|
|
||
|
// Make the scroll area automatically resize to the containing widget.
|
||
|
scrollArea->setWidgetResizable(true);
|
||
|
|
||
|
QFrame *frame = new QFrame(scrollArea);
|
||
|
frame->setObjectName("pidControl");
|
||
|
frame->setLineWidth(0);
|
||
|
frame->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||
|
frame->setLayout(_tabLayout);
|
||
|
|
||
|
scrollArea->setWidget(frame);
|
||
|
_tabPane->addTab(scrollArea, _name);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::LayoutForceTab(msgs::Model &_modelMsg)
|
||
|
{
|
||
|
// Remove the old widgets;
|
||
|
QLayoutItem *wItem;
|
||
|
while ((wItem = this->dataPtr->forceGridLayout->takeAt(0)) != NULL)
|
||
|
{
|
||
|
if (wItem->widget())
|
||
|
delete wItem->widget();
|
||
|
delete wItem;
|
||
|
}
|
||
|
this->dataPtr->sliders.clear();
|
||
|
|
||
|
// Don't add any widget if there are no joints
|
||
|
if (_modelMsg.joint_size() == 0)
|
||
|
return;
|
||
|
|
||
|
this->dataPtr->forceGridLayout->addItem(new QSpacerItem(
|
||
|
10, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 0, 2);
|
||
|
this->dataPtr->forceGridLayout->addWidget(new QLabel(
|
||
|
"Newton-meter", this), 0, 2);
|
||
|
|
||
|
int i = 0;
|
||
|
for (; i < _modelMsg.joint_size(); ++i)
|
||
|
{
|
||
|
std::string jointName = _modelMsg.joint(i).name();
|
||
|
|
||
|
// Get the joint name minus the model name
|
||
|
int modelNameIndex = jointName.find("::") + 2;
|
||
|
std::string shortName = jointName.substr(modelNameIndex,
|
||
|
jointName.size() - modelNameIndex);
|
||
|
|
||
|
this->dataPtr->forceGridLayout->addWidget(new QLabel(
|
||
|
tr(shortName.c_str())), i+1, 0);
|
||
|
this->dataPtr->forceGridLayout->addItem(new QSpacerItem(
|
||
|
10, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), i+1, 1);
|
||
|
|
||
|
JointForceControl *slider = new JointForceControl(jointName,
|
||
|
this->dataPtr->forceGridLayout, this, i+1);
|
||
|
|
||
|
this->dataPtr->sliders[jointName] = slider;
|
||
|
connect(slider, SIGNAL(changed(double, const std::string &)),
|
||
|
this, SLOT(OnForceChanged(double, const std::string &)));
|
||
|
}
|
||
|
|
||
|
// Add a space at the bottom of the grid layout to consume extra space.
|
||
|
this->dataPtr->forceGridLayout->addItem(new QSpacerItem(
|
||
|
10, 20, QSizePolicy::Expanding, QSizePolicy::Expanding), i+1, 0);
|
||
|
this->dataPtr->forceGridLayout->setRowStretch(i+1, 2);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::LayoutPositionTab(msgs::Model &_modelMsg)
|
||
|
{
|
||
|
// Remove the old widgets;
|
||
|
QLayoutItem *wItem;
|
||
|
while ((wItem = this->dataPtr->positionGridLayout->takeAt(0)) != NULL)
|
||
|
{
|
||
|
if (wItem->widget())
|
||
|
delete wItem->widget();
|
||
|
delete wItem;
|
||
|
}
|
||
|
this->dataPtr->pidPosSliders.clear();
|
||
|
|
||
|
// Don't add any widget if there are no joints
|
||
|
if (_modelMsg.joint_size() == 0)
|
||
|
return;
|
||
|
|
||
|
this->dataPtr->positionGridLayout->addItem(new QSpacerItem(10, 20,
|
||
|
QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 0, 2);
|
||
|
|
||
|
QComboBox *unitsCombo = new QComboBox;
|
||
|
unitsCombo->addItem("Radians");
|
||
|
unitsCombo->addItem("Degrees");
|
||
|
connect(unitsCombo, SIGNAL(currentIndexChanged(int)),
|
||
|
this, SLOT(OnPIDPosUnitsChanged(int)));
|
||
|
|
||
|
this->dataPtr->positionGridLayout->addWidget(unitsCombo, 0, 2);
|
||
|
this->dataPtr->positionGridLayout->addWidget(new QLabel(
|
||
|
"P Gain", this), 0, 3);
|
||
|
this->dataPtr->positionGridLayout->addWidget(new QLabel(
|
||
|
"I Gain", this), 0, 4);
|
||
|
this->dataPtr->positionGridLayout->addWidget(new QLabel(
|
||
|
"D Gain", this), 0, 5);
|
||
|
|
||
|
int i = 0;
|
||
|
for (; i < _modelMsg.joint_size(); ++i)
|
||
|
{
|
||
|
std::string jointName = _modelMsg.joint(i).name();
|
||
|
|
||
|
// Get the joint name minus the model name
|
||
|
int modelNameIndex = jointName.find("::") + 2;
|
||
|
std::string shortName = jointName.substr(modelNameIndex,
|
||
|
jointName.size() - modelNameIndex);
|
||
|
|
||
|
this->dataPtr->positionGridLayout->addWidget(
|
||
|
new QLabel(tr(shortName.c_str())), i+1, 0);
|
||
|
this->dataPtr->positionGridLayout->addItem(
|
||
|
new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Minimum), i+1, 1);
|
||
|
|
||
|
JointPIDPosControl *slider = new JointPIDPosControl(jointName,
|
||
|
this->dataPtr->positionGridLayout, this, i+1);
|
||
|
|
||
|
this->dataPtr->pidPosSliders[jointName] = slider;
|
||
|
connect(slider, SIGNAL(changed(double, const std::string &)),
|
||
|
this, SLOT(OnPIDPosChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(pChanged(double, const std::string &)),
|
||
|
this, SLOT(OnPPosGainChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(iChanged(double, const std::string &)),
|
||
|
this, SLOT(OnIPosGainChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(dChanged(double, const std::string &)),
|
||
|
this, SLOT(OnDPosGainChanged(double, const std::string &)));
|
||
|
}
|
||
|
|
||
|
// Add a space at the bottom of the grid layout to consume extra space.
|
||
|
this->dataPtr->positionGridLayout->addItem(
|
||
|
new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Expanding), i+1, 0);
|
||
|
this->dataPtr->positionGridLayout->setRowStretch(i+1, 2);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
void JointControlWidget::LayoutVelocityTab(msgs::Model &_modelMsg)
|
||
|
{
|
||
|
// Remove the old widgets;
|
||
|
QLayoutItem *wItem;
|
||
|
while ((wItem = this->dataPtr->velocityGridLayout->takeAt(0)) != NULL)
|
||
|
{
|
||
|
if (wItem->widget())
|
||
|
delete wItem->widget();
|
||
|
delete wItem;
|
||
|
}
|
||
|
this->dataPtr->pidVelSliders.clear();
|
||
|
|
||
|
// Don't add any widget if there are no joints
|
||
|
if (_modelMsg.joint_size() == 0)
|
||
|
return;
|
||
|
|
||
|
this->dataPtr->velocityGridLayout->addItem(
|
||
|
new QSpacerItem(10, 27, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Minimum), 0, 0, 2);
|
||
|
|
||
|
// Set fixed height for the label to make the tabs stay a consistent size.
|
||
|
QLabel *label = new QLabel("m/s", this);
|
||
|
label->setFixedHeight(27);
|
||
|
|
||
|
this->dataPtr->velocityGridLayout->addWidget(label, 0, 2);
|
||
|
this->dataPtr->velocityGridLayout->addWidget(new QLabel(
|
||
|
"P Gain", this), 0, 3);
|
||
|
this->dataPtr->velocityGridLayout->addWidget(new QLabel(
|
||
|
"I Gain", this), 0, 4);
|
||
|
this->dataPtr->velocityGridLayout->addWidget(new QLabel(
|
||
|
"D Gain", this), 0, 5);
|
||
|
|
||
|
int i = 0;
|
||
|
for (; i < _modelMsg.joint_size(); ++i)
|
||
|
{
|
||
|
std::string jointName = _modelMsg.joint(i).name();
|
||
|
|
||
|
// Get the joint name minus the model name
|
||
|
int modelNameIndex = jointName.find("::") + 2;
|
||
|
std::string shortName = jointName.substr(modelNameIndex,
|
||
|
jointName.size() - modelNameIndex);
|
||
|
|
||
|
this->dataPtr->velocityGridLayout->addWidget(
|
||
|
new QLabel(tr(shortName.c_str())), i+1, 0);
|
||
|
this->dataPtr->velocityGridLayout->addItem(
|
||
|
new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Minimum), i+1, 1);
|
||
|
|
||
|
JointPIDVelControl *slider = new JointPIDVelControl(
|
||
|
jointName, this->dataPtr->velocityGridLayout, this, i+1);
|
||
|
|
||
|
this->dataPtr->pidVelSliders[jointName] = slider;
|
||
|
connect(slider, SIGNAL(changed(double, const std::string &)),
|
||
|
this, SLOT(OnPIDVelChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(pChanged(double, const std::string &)),
|
||
|
this, SLOT(OnPVelGainChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(iChanged(double, const std::string &)),
|
||
|
this, SLOT(OnIVelGainChanged(double, const std::string &)));
|
||
|
connect(slider, SIGNAL(dChanged(double, const std::string &)),
|
||
|
this, SLOT(OnDVelGainChanged(double, const std::string &)));
|
||
|
}
|
||
|
|
||
|
// Add a space at the bottom of the grid layout to consume extra space.
|
||
|
this->dataPtr->velocityGridLayout->addItem(
|
||
|
new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
||
|
QSizePolicy::Expanding), i+1, 0);
|
||
|
this->dataPtr->velocityGridLayout->setRowStretch(i+1, 2);
|
||
|
}
|