1046 lines
34 KiB
C++
1046 lines
34 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.
|
|
*
|
|
*/
|
|
#include <boost/filesystem.hpp>
|
|
#include <memory>
|
|
#include "gazebo/math/Helpers.hh"
|
|
#include "gazebo/msgs/msgs.hh"
|
|
#include "gazebo/transport/TransportIface.hh"
|
|
#include "gazebo/gui/GuiEvents.hh"
|
|
#include "gazebo/gui/GuiIface.hh"
|
|
#include "gazebo/gui/qtpropertybrowser/qttreepropertybrowser.h"
|
|
#include "gazebo/gui/qtpropertybrowser/qtvariantproperty.h"
|
|
#include "gazebo/gui/ModelListWidget.hh"
|
|
#include "gazebo/gui/ModelListWidget_TEST.hh"
|
|
|
|
#include "test_config.h"
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::TreeWidget()
|
|
{
|
|
QBENCHMARK
|
|
{
|
|
this->Load("worlds/empty.world");
|
|
|
|
gazebo::gui::ModelListWidget *modelListWidget
|
|
= new gazebo::gui::ModelListWidget;
|
|
QCoreApplication::processEvents();
|
|
|
|
// Get tree widget
|
|
QTreeWidget *modelTreeWidget = modelListWidget->findChild<QTreeWidget*>(
|
|
"modelTreeWidget");
|
|
|
|
QVERIFY(modelTreeWidget != NULL);
|
|
|
|
QList<QTreeWidgetItem *> treeSceneItems =
|
|
modelTreeWidget->findItems(tr("Scene"), Qt::MatchExactly);
|
|
QCOMPARE(treeSceneItems.size(), 1);
|
|
|
|
QList<QTreeWidgetItem *> treePhysicsItems =
|
|
modelTreeWidget->findItems(tr("Physics"), Qt::MatchExactly);
|
|
QCOMPARE(treePhysicsItems.size(), 1);
|
|
|
|
QList<QTreeWidgetItem *> treeLightItems =
|
|
modelTreeWidget->findItems(tr("Lights"), Qt::MatchExactly);
|
|
QCOMPARE(treeLightItems.size(), 1);
|
|
|
|
QList<QTreeWidgetItem *> treeModelItems =
|
|
modelTreeWidget->findItems(tr("Models"), Qt::MatchExactly);
|
|
QCOMPARE(treeModelItems.size(), 1);
|
|
|
|
QTreeWidgetItem *modelsItem = treeModelItems.front();
|
|
QVERIFY(modelsItem != NULL);
|
|
|
|
delete modelListWidget;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::OnResponse(ConstResponsePtr &_msg)
|
|
{
|
|
gazebo::msgs::Model_V modelVMsg;
|
|
if (_msg->has_type() && _msg->type() == modelVMsg.GetTypeName())
|
|
{
|
|
modelVMsg.ParseFromString(_msg->serialized_data());
|
|
for (int i = 0; i < modelVMsg.models_size(); i++)
|
|
{
|
|
gazebo::gui::Events::modelUpdate(modelVMsg.models(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::CheckVector3Property(QList<QtProperty *> _properties,
|
|
const ignition::math::Vector3d &_xyz)
|
|
{
|
|
QVERIFY(_properties.size() >= 3);
|
|
for (unsigned char c = 0; c < 3; ++c)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(_properties[c]);
|
|
Q_ASSERT(property);
|
|
std::string name(1, 'x' + c);
|
|
QCOMPARE(property->propertyName(), tr(name.c_str()));
|
|
QCOMPARE(property->value().toDouble(), _xyz[c]);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::CheckPoseProperty(QList<QtProperty *> _properties,
|
|
const gazebo::math::Pose &_pose)
|
|
{
|
|
QCOMPARE(_properties.size(), 6);
|
|
this->CheckVector3Property(_properties, _pose.pos.Ign());
|
|
QtVariantProperty *property;
|
|
property = static_cast<QtVariantProperty *>(_properties[3]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("roll"));
|
|
QCOMPARE(property->value().toDouble(), _pose.rot.GetAsEuler().x);
|
|
property = static_cast<QtVariantProperty *>(_properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("pitch"));
|
|
QCOMPARE(property->value().toDouble(), _pose.rot.GetAsEuler().y);
|
|
property = static_cast<QtVariantProperty *>(_properties[5]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("yaw"));
|
|
QCOMPARE(property->value().toDouble(), _pose.rot.GetAsEuler().z);
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::SetVector3Property(
|
|
QtTreePropertyBrowser *_propTreeBrowser,
|
|
QList<QtProperty *> _properties,
|
|
const ignition::math::Vector3d &_xyz)
|
|
{
|
|
QVERIFY(_properties.size() >= 3);
|
|
for (unsigned char c = 0; c < 3; ++c)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(_properties[c]);
|
|
Q_ASSERT(property);
|
|
std::string name(1, 'x' + c);
|
|
QCOMPARE(property->propertyName(), tr(name.c_str()));
|
|
QVERIFY(_propTreeBrowser->items(property).size() == 1);
|
|
_propTreeBrowser->setCurrentItem(_propTreeBrowser->items(property)[0]);
|
|
property->setValue(_xyz[c]);
|
|
}
|
|
QTest::qWait(500);
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::SetPoseProperty(
|
|
QtTreePropertyBrowser *_propTreeBrowser,
|
|
QList<QtProperty *> _properties,
|
|
const gazebo::math::Pose &_pose)
|
|
{
|
|
QCOMPARE(_properties.size(), 6);
|
|
this->SetVector3Property(_propTreeBrowser, _properties, _pose.pos.Ign());
|
|
QtVariantProperty *property;
|
|
property = static_cast<QtVariantProperty *>(_properties[3]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("roll"));
|
|
QVERIFY(_propTreeBrowser->items(property).size() == 1);
|
|
_propTreeBrowser->setCurrentItem(_propTreeBrowser->items(property)[0]);
|
|
property->setValue(_pose.rot.GetAsEuler().x);
|
|
property = static_cast<QtVariantProperty *>(_properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("pitch"));
|
|
QVERIFY(_propTreeBrowser->items(property).size() == 1);
|
|
_propTreeBrowser->setCurrentItem(_propTreeBrowser->items(property)[0]);
|
|
property->setValue(_pose.rot.GetAsEuler().y);
|
|
property = static_cast<QtVariantProperty *>(_properties[5]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("yaw"));
|
|
QVERIFY(_propTreeBrowser->items(property).size() == 1);
|
|
_propTreeBrowser->setCurrentItem(_propTreeBrowser->items(property)[0]);
|
|
property->setValue(_pose.rot.GetAsEuler().z);
|
|
QTest::qWait(500);
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::CheckLinkProperty(QList<QtProperty *> _properties,
|
|
const std::string &_name, bool _selfCollide, bool _gravity, bool _kinematic,
|
|
bool _canonical, const gazebo::math::Pose &_pose)
|
|
{
|
|
// ignore checking link id in _properties[0]
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(_properties[1]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("name"));
|
|
QCOMPARE(property->valueText(), tr(_name.c_str()));
|
|
property = static_cast<QtVariantProperty *>(_properties[2]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("self_collide"));
|
|
QCOMPARE(property->value().toBool(), _selfCollide);
|
|
property = static_cast<QtVariantProperty *>(_properties[3]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("gravity"));
|
|
QCOMPARE(property->value().toBool(), _gravity);
|
|
property = static_cast<QtVariantProperty *>(_properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("kinematic"));
|
|
QCOMPARE(property->value().toBool(), _kinematic);
|
|
property = static_cast<QtVariantProperty *>(_properties[5]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("canonical"));
|
|
QCOMPARE(property->value().toBool(), _canonical);
|
|
property = static_cast<QtVariantProperty *>(_properties[6]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("pose"));
|
|
CheckPoseProperty(property->subProperties(), _pose);
|
|
// pose settings for canonical links should be disabled
|
|
QCOMPARE(property->isEnabled(), !_canonical);
|
|
|
|
/// TODO check inertial, collision, visual properties
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::SetLinkProperty(
|
|
QtTreePropertyBrowser *propTreeBrowser, QList<QtProperty *> _properties,
|
|
const std::string &_name, bool _selfCollide, bool _gravity, bool _kinematic,
|
|
bool _canonical, const gazebo::math::Pose &_pose)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(_properties[1]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("name"));
|
|
QVERIFY(propTreeBrowser->items(property).size() == 1);
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
property->setValue(tr(_name.c_str()));
|
|
property = static_cast<QtVariantProperty *>(_properties[2]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("self_collide"));
|
|
QVERIFY(propTreeBrowser->items(property).size() == 1);
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
property->setValue(_selfCollide);
|
|
property = static_cast<QtVariantProperty *>(_properties[3]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("gravity"));
|
|
QVERIFY(propTreeBrowser->items(property).size() == 1);
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
property->setValue(_gravity);
|
|
property = static_cast<QtVariantProperty *>(_properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("kinematic"));
|
|
QVERIFY(propTreeBrowser->items(property).size() == 1);
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
property->setValue(_kinematic);
|
|
property = static_cast<QtVariantProperty *>(_properties[5]);
|
|
Q_ASSERT(property);
|
|
// only set the pose for non-canonical links
|
|
QCOMPARE(property->propertyName(), tr("canonical"));
|
|
QCOMPARE(property->value().toBool(), _canonical);
|
|
if (!property->value().toBool())
|
|
{
|
|
property = static_cast<QtVariantProperty *>(_properties[6]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("pose"));
|
|
QVERIFY(propTreeBrowser->items(property).size() == 1);
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
propTreeBrowser->setExpanded(propTreeBrowser->topLevelItem(property), true);
|
|
this->SetPoseProperty(propTreeBrowser, property->subProperties(), _pose);
|
|
}
|
|
QTest::qWait(1000);
|
|
/// TODO set inertial, collision, visual properties
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::ModelsTree()
|
|
{
|
|
gazebo::gui::ModelListWidget *modelListWidget
|
|
= new gazebo::gui::ModelListWidget;
|
|
QCoreApplication::processEvents();
|
|
|
|
this->Load("worlds/shapes.world");
|
|
|
|
gazebo::transport::NodePtr node;
|
|
node = gazebo::transport::NodePtr(new gazebo::transport::Node());
|
|
node->Init();
|
|
gazebo::transport::PublisherPtr requestPub =
|
|
node->Advertise<gazebo::msgs::Request>("~/request");
|
|
gazebo::transport::SubscriberPtr responseSub = node->Subscribe("~/response",
|
|
&ModelListWidget_TEST::OnResponse, this);
|
|
|
|
gazebo::msgs::Request *requestMsg =
|
|
gazebo::msgs::CreateRequest("entity_list");
|
|
requestPub->Publish(*requestMsg);
|
|
|
|
// Get tree widget
|
|
QTreeWidget *modelTreeWidget = modelListWidget->findChild<QTreeWidget *>(
|
|
"modelTreeWidget");
|
|
|
|
QList<QTreeWidgetItem *> treeModelItems =
|
|
modelTreeWidget->findItems(tr("Models"), Qt::MatchExactly);
|
|
QCOMPARE(treeModelItems.size(), 1);
|
|
|
|
QTreeWidgetItem *modelsItem = treeModelItems.front();
|
|
QVERIFY(modelsItem != NULL);
|
|
|
|
// verify that there are 4 models, ground plane, sphere, box, and cylinder
|
|
int modelCount = 4;
|
|
int maxSleep = 10;
|
|
int sleep = 0;
|
|
while (modelsItem->childCount() < modelCount && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(sleep < maxSleep);
|
|
|
|
// process more events and make sure the child count remain the same
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
QCOMPARE(modelsItem->childCount(), modelCount);
|
|
sleep++;
|
|
}
|
|
|
|
// find all models in the tree
|
|
QTreeWidgetItem *groundPlaneItem = NULL;
|
|
QTreeWidgetItem *boxItem = NULL;
|
|
QTreeWidgetItem *sphereItem = NULL;
|
|
QTreeWidgetItem *cylinderItem = NULL;
|
|
for (int i = 0; i < modelsItem->childCount(); ++i)
|
|
{
|
|
QTreeWidgetItem *item = modelsItem->child(i);
|
|
if (item->text(0) == "ground_plane")
|
|
groundPlaneItem = item;
|
|
else if (item->text(0) == "box")
|
|
boxItem = item;
|
|
else if (item->text(0) == "sphere")
|
|
sphereItem = item;
|
|
else if (item->text(0) == "cylinder")
|
|
cylinderItem = item;
|
|
}
|
|
|
|
// verify all models are present
|
|
QVERIFY(groundPlaneItem != NULL);
|
|
QVERIFY(boxItem != NULL);
|
|
QVERIFY(sphereItem != NULL);
|
|
QVERIFY(cylinderItem != NULL);
|
|
|
|
node.reset();
|
|
delete requestMsg;
|
|
delete modelListWidget;
|
|
modelListWidget = NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::ModelProperties()
|
|
{
|
|
gazebo::gui::ModelListWidget *modelListWidget
|
|
= new gazebo::gui::ModelListWidget;
|
|
modelListWidget->show();
|
|
QCoreApplication::processEvents();
|
|
|
|
this->Load("worlds/multilink_shape.world");
|
|
|
|
gazebo::transport::NodePtr node;
|
|
node = gazebo::transport::NodePtr(new gazebo::transport::Node());
|
|
node->Init();
|
|
gazebo::transport::PublisherPtr requestPub =
|
|
node->Advertise<gazebo::msgs::Request>("~/request");
|
|
gazebo::transport::SubscriberPtr responseSub = node->Subscribe("~/response",
|
|
&ModelListWidget_TEST::OnResponse, this);
|
|
|
|
gazebo::msgs::Request *requestMsg =
|
|
gazebo::msgs::CreateRequest("entity_list");
|
|
requestPub->Publish(*requestMsg);
|
|
|
|
// Get tree widget
|
|
QTreeWidget *modelTreeWidget = modelListWidget->findChild<QTreeWidget *>(
|
|
"modelTreeWidget");
|
|
|
|
QList<QTreeWidgetItem *> treeModelItems =
|
|
modelTreeWidget->findItems(tr("Models"), Qt::MatchExactly);
|
|
QCOMPARE(treeModelItems.size(), 1);
|
|
|
|
QTreeWidgetItem *modelsItem = treeModelItems.front();
|
|
QVERIFY(modelsItem != NULL);
|
|
|
|
// verify that there is only 1 model
|
|
int modelCount = 1;
|
|
int maxSleep = 10;
|
|
int sleep = 0;
|
|
while (modelsItem->childCount() < modelCount && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(sleep < maxSleep);
|
|
|
|
// Get the model item
|
|
QTreeWidgetItem *modelItem = modelsItem->child(0);
|
|
QVERIFY(modelItem != NULL);
|
|
std::string modelName = "multilink";
|
|
QCOMPARE(modelItem->text(0), tr(modelName.c_str()));
|
|
|
|
// Get propery browser widget
|
|
QObject *propTreeObj =
|
|
modelListWidget->findChild<QObject *>("propTreeBrowser");
|
|
QtTreePropertyBrowser *propTreeBrowser =
|
|
dynamic_cast<QtTreePropertyBrowser *>(propTreeObj);
|
|
|
|
QVERIFY(propTreeBrowser != NULL);
|
|
QCOMPARE(propTreeBrowser->properties().size(), 0);
|
|
|
|
// select the models item
|
|
QRect modelsRect = modelTreeWidget->visualItemRect(modelsItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
modelsRect.center() );
|
|
QCoreApplication::processEvents();
|
|
// wait for the model to be selected
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!modelsItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(modelsItem->isSelected());
|
|
|
|
// select the multi-link model
|
|
QRect modelRect = modelTreeWidget->visualItemRect(modelItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
modelRect.center() );
|
|
QCoreApplication::processEvents();
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!modelItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(modelItem->isSelected());
|
|
|
|
// wait for the model properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// check the model properties
|
|
bool hasName = false;
|
|
bool hasStatic = false;
|
|
bool hasPose = false;
|
|
int numLinks = 0;
|
|
int nameIndex = 1;
|
|
QList<QtProperty *> modelProperties = propTreeBrowser->properties();
|
|
for (int i = 0; i < modelProperties.size(); ++i)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(modelProperties[i]);
|
|
if (property->propertyName() == tr("name"))
|
|
{
|
|
QCOMPARE(property->valueText(), tr(modelName.c_str()));
|
|
hasName = true;
|
|
}
|
|
else if (property->propertyName() == tr("is_static"))
|
|
{
|
|
QCOMPARE(property->value().toBool(), false);
|
|
hasStatic = true;
|
|
}
|
|
else if (property->propertyName() == tr("pose"))
|
|
{
|
|
this->CheckPoseProperty(property->subProperties(),
|
|
gazebo::math::Pose(0, 0, 0.5, 0, 0, 0));
|
|
hasPose = true;
|
|
}
|
|
else if (property->propertyName() == tr("link"))
|
|
{
|
|
QVERIFY(property->subProperties().size() > 0);
|
|
if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("box_link") != std::string::npos)
|
|
{
|
|
this->CheckLinkProperty(property->subProperties(),
|
|
modelName + "::box_link", false, true, false, true,
|
|
gazebo::math::Pose(1.0, 0, 0, 0, 0, 0));
|
|
numLinks++;
|
|
}
|
|
else if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("sphere_link") != std::string::npos)
|
|
{
|
|
this->CheckLinkProperty(property->subProperties(),
|
|
modelName + "::sphere_link", false, true, false, false,
|
|
gazebo::math::Pose(-1.5, 0, 0, 0, 0, 1.57));
|
|
numLinks++;
|
|
}
|
|
}
|
|
}
|
|
QVERIFY(hasName);
|
|
QVERIFY(hasStatic);
|
|
QVERIFY(hasPose);
|
|
// there should be 2 links
|
|
QCOMPARE(numLinks, 2);
|
|
|
|
numLinks = 0;
|
|
// change model properties
|
|
for (int i = 0; i < modelProperties.size(); ++i)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(modelProperties[i]);
|
|
|
|
// TODO changing model name currently fails
|
|
// if (property->propertyName() == tr("name"))
|
|
// {
|
|
// propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
// property->setValue(true);
|
|
// }
|
|
if (property->propertyName() == tr("is_static"))
|
|
{
|
|
propTreeBrowser->setCurrentItem(propTreeBrowser->items(property)[0]);
|
|
property->setValue(true);
|
|
}
|
|
else if (property->propertyName() == tr("pose"))
|
|
{
|
|
this->SetPoseProperty(propTreeBrowser, property->subProperties(),
|
|
gazebo::math::Pose(0, 0, 1.0, 0, 0, 0));
|
|
}
|
|
else if (property->propertyName() == tr("link"))
|
|
{
|
|
QVERIFY(property->subProperties().size() > 0);
|
|
if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("box_link") != std::string::npos)
|
|
{
|
|
this->SetLinkProperty(propTreeBrowser, property->subProperties(),
|
|
modelName + "::box_link", true, false, true, true,
|
|
gazebo::math::Pose(1.5, 2.0, 3.2, 0.6, 0.7, 0.8));
|
|
numLinks++;
|
|
}
|
|
else if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("sphere_link") != std::string::npos)
|
|
{
|
|
this->SetLinkProperty(propTreeBrowser, property->subProperties(),
|
|
modelName + "::sphere_link", true, false, true, false,
|
|
gazebo::math::Pose(-2.0, 0.5, 1.0, 3.14, 0, 0));
|
|
numLinks++;
|
|
}
|
|
}
|
|
}
|
|
QCOMPARE(numLinks, 2);
|
|
|
|
// select the multi-link model again to refresh the property browser
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
modelRect.center() );
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(100);
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!modelItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(modelItem->isSelected());
|
|
// wait for the model properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
numLinks = 0;
|
|
// verify the model properties are sucessfully set
|
|
for (int i = 0; i < modelProperties.size(); ++i)
|
|
{
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(modelProperties[i]);
|
|
|
|
if (property->propertyName() == tr("is_static"))
|
|
{
|
|
QCOMPARE(property->value().toBool(), true);
|
|
}
|
|
else if (property->propertyName() == tr("pose"))
|
|
{
|
|
this->CheckPoseProperty(property->subProperties(),
|
|
gazebo::math::Pose(0, 0, 1.0, 0, 0, 0));
|
|
}
|
|
else if (property->propertyName() == tr("link"))
|
|
{
|
|
QVERIFY(property->subProperties().size() > 0);
|
|
if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("box_link") != std::string::npos)
|
|
{
|
|
// as this is the canonical link, the pose properties should remain
|
|
// unchanged
|
|
this->CheckLinkProperty(property->subProperties(),
|
|
modelName + "::box_link", true, false, true, true,
|
|
gazebo::math::Pose(1.0, 0, 0, 0, 0, 0));
|
|
numLinks++;
|
|
}
|
|
else if (property->subProperties()[nameIndex]->valueText().toStdString().
|
|
find("sphere_link") != std::string::npos)
|
|
{
|
|
this->CheckLinkProperty(property->subProperties(),
|
|
modelName + "::sphere_link", true, false, true, false,
|
|
gazebo::math::Pose(-2.0, 0.5, 1.0, 3.14, 0, 0));
|
|
numLinks++;
|
|
}
|
|
}
|
|
}
|
|
QCOMPARE(numLinks, 2);
|
|
|
|
modelListWidget->hide();
|
|
node.reset();
|
|
delete requestMsg;
|
|
delete modelListWidget;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::LinkProperties()
|
|
{
|
|
gazebo::gui::ModelListWidget *modelListWidget
|
|
= new gazebo::gui::ModelListWidget;
|
|
modelListWidget->show();
|
|
modelListWidget->setGeometry(0, 0, 400, 800);
|
|
QCoreApplication::processEvents();
|
|
|
|
this->Load("worlds/multilink_shape.world");
|
|
|
|
gazebo::transport::NodePtr node;
|
|
node = gazebo::transport::NodePtr(new gazebo::transport::Node());
|
|
node->Init();
|
|
gazebo::transport::PublisherPtr requestPub =
|
|
node->Advertise<gazebo::msgs::Request>("~/request");
|
|
gazebo::transport::SubscriberPtr responseSub = node->Subscribe("~/response",
|
|
&ModelListWidget_TEST::OnResponse, this);
|
|
|
|
gazebo::msgs::Request *requestMsg =
|
|
gazebo::msgs::CreateRequest("entity_list");
|
|
requestPub->Publish(*requestMsg);
|
|
|
|
// Get tree widget
|
|
QTreeWidget *modelTreeWidget = modelListWidget->findChild<QTreeWidget *>(
|
|
"modelTreeWidget");
|
|
|
|
QList<QTreeWidgetItem *> treeModelItems =
|
|
modelTreeWidget->findItems(tr("Models"), Qt::MatchExactly);
|
|
QCOMPARE(treeModelItems.size(), 1);
|
|
|
|
QTreeWidgetItem *modelsItem = treeModelItems.front();
|
|
QVERIFY(modelsItem != NULL);
|
|
|
|
// verify that there is only 1 model
|
|
int modelCount = 1;
|
|
int maxSleep = 10;
|
|
int sleep = 0;
|
|
while (modelsItem->childCount() < modelCount && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(sleep < maxSleep);
|
|
|
|
// Get the model item
|
|
QTreeWidgetItem *modelItem = modelsItem->child(0);
|
|
QVERIFY(modelItem != NULL);
|
|
std::string modelName = "multilink";
|
|
QCOMPARE(modelItem->text(0), tr(modelName.c_str()));
|
|
|
|
// Get propery browser widget
|
|
QObject *propTreeObj =
|
|
modelListWidget->findChild<QObject *>("propTreeBrowser");
|
|
QtTreePropertyBrowser *propTreeBrowser =
|
|
dynamic_cast<QtTreePropertyBrowser *>(propTreeObj);
|
|
|
|
QVERIFY(propTreeBrowser != NULL);
|
|
QCOMPARE(propTreeBrowser->properties().size(), 0);
|
|
|
|
// select the models item
|
|
QRect modelsRect = modelTreeWidget->visualItemRect(modelsItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
modelsRect.center() );
|
|
QCoreApplication::processEvents();
|
|
// wait for the models item to be selected
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!modelsItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(modelsItem->isSelected());
|
|
|
|
// select the multi-link model
|
|
QRect modelRect = modelTreeWidget->visualItemRect(modelItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
modelRect.center());
|
|
QCoreApplication::processEvents();
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!modelItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(modelItem->isSelected());
|
|
|
|
// wait for the model properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// select the box link
|
|
QTreeWidgetItem *boxLinkItem = modelItem->child(0);
|
|
QVERIFY(boxLinkItem != NULL);
|
|
std::string boxLinkName = "box_link";
|
|
QCOMPARE(boxLinkItem->text(0), tr(boxLinkName.c_str()));
|
|
|
|
QRect boxLinkRect = modelTreeWidget->visualItemRect(boxLinkItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
boxLinkRect.center() );
|
|
|
|
QCoreApplication::processEvents();
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!boxLinkItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(boxLinkItem->isSelected());
|
|
|
|
// wait for the box link properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// check the box link properties
|
|
this->CheckLinkProperty(propTreeBrowser->properties(),
|
|
modelName + "::" + boxLinkName, false, true, false, true,
|
|
gazebo::math::Pose(1.0, 0, 0, 0, 0, 0));
|
|
|
|
// change box link properties
|
|
// TODO changing link name currently fails.
|
|
this->SetLinkProperty(propTreeBrowser, propTreeBrowser->properties(),
|
|
modelName + "::" + boxLinkName, true, false, true, true,
|
|
gazebo::math::Pose(2.5, 1.0, 4.2, 0.8, 0.5, 0.1));
|
|
|
|
// select the box link again to refresh the property browser
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
boxLinkRect.center() );
|
|
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(100);
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!boxLinkItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(boxLinkItem->isSelected());
|
|
// wait for the box link properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// verify the link properties are sucessfully set
|
|
// the link is canonical so the pose should remain the same
|
|
this->CheckLinkProperty(propTreeBrowser->properties(),
|
|
modelName + "::" + boxLinkName, true, false, true, true,
|
|
gazebo::math::Pose(1.0, 0, 0, 0, 0, 0));
|
|
|
|
// select the sphere link
|
|
QTreeWidgetItem *sphereLinkItem = modelItem->child(1);
|
|
QVERIFY(sphereLinkItem != NULL);
|
|
std::string sphereLinkName = "sphere_link";
|
|
QCOMPARE(sphereLinkItem->text(0), tr(sphereLinkName.c_str()));
|
|
|
|
QRect sphereLinkRect = modelTreeWidget->visualItemRect(sphereLinkItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
sphereLinkRect.center() );
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(100);
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!sphereLinkItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(sphereLinkItem->isSelected());
|
|
|
|
// wait for the sphere link properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// check the sphere link properties
|
|
this->CheckLinkProperty(propTreeBrowser->properties(),
|
|
modelName + "::" + sphereLinkName, false, true, false, false,
|
|
gazebo::math::Pose(-1.5, 0, 0, 0, 0, 1.57));
|
|
|
|
// change sphere link properties
|
|
// TODO changing link name currently fails.
|
|
this->SetLinkProperty(propTreeBrowser, propTreeBrowser->properties(),
|
|
modelName + "::" + sphereLinkName, true, false, true, false,
|
|
gazebo::math::Pose(-2.0, 0.1, -1.2, 0, 1.57, 0));
|
|
|
|
// select the sphere link again to refresh the property browser
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
sphereLinkRect.center() );
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(100);
|
|
sleep = 0;
|
|
maxSleep = 5;
|
|
while (!sphereLinkItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(sphereLinkItem->isSelected());
|
|
// wait for the sphere link properties to appear
|
|
sleep = 0;
|
|
maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
|
|
// verify the link properties are sucessfully set
|
|
this->CheckLinkProperty(propTreeBrowser->properties(),
|
|
modelName + "::" + sphereLinkName, true, false, true, false,
|
|
gazebo::math::Pose(-2.0, 0.1, -1.2, 0, 1.57, 0));
|
|
|
|
modelListWidget->hide();
|
|
node.reset();
|
|
delete requestMsg;
|
|
delete modelListWidget;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void ModelListWidget_TEST::PhysicsProperties()
|
|
{
|
|
std::unique_ptr<gazebo::gui::ModelListWidget> modelListWidget(
|
|
new gazebo::gui::ModelListWidget);
|
|
modelListWidget->show();
|
|
modelListWidget->setGeometry(0, 0, 400, 800);
|
|
QCoreApplication::processEvents();
|
|
|
|
this->Load("worlds/empty.world");
|
|
|
|
// Verify that property browser widget is initially empty
|
|
QObject *propTreeObj =
|
|
modelListWidget->findChild<QObject *>("propTreeBrowser");
|
|
QtTreePropertyBrowser *propTreeBrowser =
|
|
dynamic_cast<QtTreePropertyBrowser *>(propTreeObj);
|
|
QVERIFY(propTreeBrowser != NULL);
|
|
QCOMPARE(propTreeBrowser->properties().size(), 0);
|
|
|
|
// Get the physics item from the model tree
|
|
QTreeWidget *modelTreeWidget = modelListWidget->findChild<QTreeWidget *>(
|
|
"modelTreeWidget");
|
|
QList<QTreeWidgetItem *> treePhysicsItems =
|
|
modelTreeWidget->findItems(tr("Physics"), Qt::MatchExactly);
|
|
QCOMPARE(treePhysicsItems.size(), 1);
|
|
QTreeWidgetItem *physicsItem = treePhysicsItems.front();
|
|
QVERIFY(physicsItem != NULL);
|
|
|
|
// select the physics item after giving it time to be rendered
|
|
QTest::qWait(10);
|
|
QRect physicsRect;
|
|
{
|
|
physicsRect = modelTreeWidget->visualItemRect(physicsItem);
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
physicsRect.center() );
|
|
QCoreApplication::processEvents();
|
|
// wait for the physics item to be selected
|
|
int sleep = 0;
|
|
int maxSleep = 5;
|
|
while (!physicsItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(physicsItem->isSelected());
|
|
}
|
|
|
|
// wait for the physics properties to appear
|
|
{
|
|
int sleep = 0;
|
|
int maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
}
|
|
|
|
// verify that there are 8 physics properties
|
|
QCOMPARE(propTreeBrowser->properties().size(), 8);
|
|
|
|
// check default values of each parameter
|
|
// physics engine type: ODE
|
|
{
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[0]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("physics engine"));
|
|
QCOMPARE(property->valueText(), tr("ODE"));
|
|
}
|
|
|
|
// physics enabled: true
|
|
{
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[1]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("enable physics"));
|
|
QCOMPARE(property->value().toBool(), true);
|
|
}
|
|
|
|
// real time update rate: 1000
|
|
{
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[2]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("real time update rate"));
|
|
QCOMPARE(property->value().toDouble(), 1e3);
|
|
}
|
|
|
|
// max step size: 0.001
|
|
{
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[3]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("max step size"));
|
|
QCOMPARE(property->value().toDouble(), 1e-3);
|
|
}
|
|
|
|
// gravity: 0 0 -9.8
|
|
{
|
|
const ignition::math::Vector3d gravity(0, 0, -9.8);
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("gravity"));
|
|
this->CheckVector3Property(property->subProperties(), gravity);
|
|
// set gravity to 0 0 0
|
|
this->SetVector3Property(propTreeBrowser, property->subProperties(),
|
|
ignition::math::Vector3d::Zero);
|
|
}
|
|
|
|
// magnetic field: 6e-6 2.3e-5 -4.2e-5
|
|
{
|
|
const ignition::math::Vector3d xyz(6e-6, 2.3e-5, -4.2e-5);
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[5]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("magnetic field"));
|
|
CheckVector3Property(property->subProperties(), xyz);
|
|
}
|
|
|
|
// select the box link again to refresh the property browser
|
|
QTest::mouseClick(modelTreeWidget->viewport(), Qt::LeftButton, 0,
|
|
physicsRect.center() );
|
|
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(100);
|
|
int sleep = 0;
|
|
int maxSleep = 5;
|
|
while (!physicsItem->isSelected() && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(10);
|
|
sleep++;
|
|
}
|
|
QVERIFY(physicsItem->isSelected());
|
|
}
|
|
|
|
// wait for the box link properties to appear
|
|
{
|
|
int sleep = 0;
|
|
int maxSleep = 10;
|
|
while (propTreeBrowser->properties().size() == 0 && sleep < maxSleep)
|
|
{
|
|
QCoreApplication::processEvents();
|
|
QTest::qWait(500);
|
|
sleep++;
|
|
}
|
|
QVERIFY(propTreeBrowser->properties().size() > 0);
|
|
}
|
|
|
|
// check gravity: 0 0 0
|
|
{
|
|
auto properties = propTreeBrowser->properties();
|
|
QtVariantProperty *property =
|
|
static_cast<QtVariantProperty *>(properties[4]);
|
|
Q_ASSERT(property);
|
|
QCOMPARE(property->propertyName(), tr("gravity"));
|
|
this->CheckVector3Property(property->subProperties(),
|
|
ignition::math::Vector3d::Zero);
|
|
}
|
|
|
|
modelListWidget->hide();
|
|
}
|
|
|
|
// Generate a main function for the test
|
|
QTEST_MAIN(ModelListWidget_TEST)
|