pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/gui/ModelMaker.cc

430 lines
12 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 <sstream>
#include "gazebo/msgs/msgs.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/rendering/UserCamera.hh"
#include "gazebo/rendering/Visual.hh"
#include "gazebo/rendering/Scene.hh"
#include "gazebo/transport/Publisher.hh"
#include "gazebo/transport/Node.hh"
#include "gazebo/gui/ModelManipulator.hh"
#include "gazebo/gui/GuiIface.hh"
#include "gazebo/gui/MainWindow.hh"
#include "gazebo/gui/ModelMakerPrivate.hh"
#include "gazebo/gui/ModelMaker.hh"
using namespace gazebo;
using namespace gui;
/////////////////////////////////////////////////
ModelMaker::ModelMaker() : EntityMaker(*new ModelMakerPrivate)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
dPtr->clone = false;
dPtr->makerPub = dPtr->node->Advertise<msgs::Factory>("~/factory");
}
/////////////////////////////////////////////////
ModelMaker::~ModelMaker()
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
dPtr->makerPub.reset();
}
/////////////////////////////////////////////////
bool ModelMaker::InitFromModel(const std::string &_modelName)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
rendering::ScenePtr scene = gui::get_active_camera()->GetScene();
if (!scene)
return false;
if (dPtr->modelVisual)
{
scene->RemoveVisual(dPtr->modelVisual);
dPtr->modelVisual.reset();
dPtr->visuals.clear();
}
rendering::VisualPtr vis = scene->GetVisual(_modelName);
if (!vis)
{
gzerr << "Model: '" << _modelName << "' does not exist." << std::endl;
return false;
}
dPtr->modelVisual = vis->Clone(
_modelName + "_clone_tmp", scene->WorldVisual());
if (!dPtr->modelVisual)
{
gzerr << "Unable to clone\n";
return false;
}
dPtr->clone = true;
return true;
}
/////////////////////////////////////////////////
bool ModelMaker::InitFromFile(const std::string &_filename)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
dPtr->clone = false;
rendering::ScenePtr scene = gui::get_active_camera()->GetScene();
if (dPtr->modelVisual)
{
scene->RemoveVisual(dPtr->modelVisual);
dPtr->modelVisual.reset();
}
dPtr->modelSDF.reset(new sdf::SDF);
sdf::initFile("root.sdf", dPtr->modelSDF);
if (!sdf::readFile(_filename, dPtr->modelSDF))
{
gzerr << "Unable to load file[" << _filename << "]\n";
return false;
}
return this->Init();
}
/////////////////////////////////////////////////
bool ModelMaker::InitSimpleShape(SimpleShapes _shape)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
dPtr->clone = false;
rendering::ScenePtr scene = gui::get_active_camera()->GetScene();
if (!scene)
return false;
if (dPtr->modelVisual)
{
scene->RemoveVisual(dPtr->modelVisual);
dPtr->modelVisual.reset();
}
// Desired name (the server will append a number to generate a unique name
// in case of overlap.
std::string modelName;
if (_shape == BOX)
modelName = "unit_box";
else if (_shape == SPHERE)
modelName = "unit_sphere";
else if (_shape == CYLINDER)
modelName = "unit_cylinder";
// Model message
msgs::Model model;
model.set_name(modelName);
msgs::Set(model.mutable_pose(), ignition::math::Pose3d(0, 0, 0.5, 0, 0, 0));
if (_shape == BOX)
msgs::AddBoxLink(model, 1.0, ignition::math::Vector3d::One);
else if (_shape == SPHERE)
msgs::AddSphereLink(model, 1.0, 0.5);
else if (_shape == CYLINDER)
msgs::AddCylinderLink(model, 1.0, 0.5, 1.0);
model.mutable_link(0)->set_name("link");
// Model SDF
std::string modelString = "<sdf version='" + std::string(SDF_VERSION) + "'>"
+ msgs::ModelToSDF(model)->ToString("") + "</sdf>";
dPtr->modelSDF.reset(new sdf::SDF);
sdf::initFile("root.sdf", dPtr->modelSDF);
if (!sdf::readString(modelString, dPtr->modelSDF))
{
gzerr << "Unable to load SDF [" << modelString << "]" << std::endl;
return false;
}
return this->Init();
}
/////////////////////////////////////////////////
bool ModelMaker::Init()
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
rendering::ScenePtr scene = gui::get_active_camera()->GetScene();
if (!scene)
return false;
// Load the world file
std::string modelName;
ignition::math::Pose3d modelPose, linkPose, visualPose;
sdf::ElementPtr modelElem;
if (dPtr->modelSDF->Root()->HasElement("model"))
modelElem = dPtr->modelSDF->Root()->GetElement("model");
else if (dPtr->modelSDF->Root()->HasElement("light"))
modelElem = dPtr->modelSDF->Root()->GetElement("light");
else
{
gzerr << "No model or light in SDF\n";
return false;
}
if (modelElem->HasElement("pose"))
modelPose = modelElem->Get<ignition::math::Pose3d>("pose");
modelName = modelElem->Get<std::string>("name");
dPtr->modelVisual.reset(new rendering::Visual(
dPtr->node->GetTopicNamespace() + "::" + modelName,
scene->WorldVisual()));
dPtr->modelVisual->Load();
dPtr->modelVisual->SetPose(modelPose);
modelName = dPtr->modelVisual->GetName();
modelElem->GetAttribute("name")->Set(modelName);
if (modelElem->GetName() == "model")
{
this->CreateModelFromSDF(modelElem);
}
else if (modelElem->GetName() == "light")
{
dPtr->modelVisual->AttachMesh("unit_sphere");
}
else
{
return false;
}
return true;
}
/////////////////////////////////////////////////
void ModelMaker::CreateModelFromSDF(sdf::ElementPtr _modelElem)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
ignition::math::Pose3d linkPose, visualPose;
std::list<std::pair<sdf::ElementPtr, rendering::VisualPtr> > modelElemList;
std::pair<sdf::ElementPtr, rendering::VisualPtr> pair(
_modelElem, dPtr->modelVisual);
modelElemList.push_back(pair);
while (!modelElemList.empty())
{
sdf::ElementPtr modelElem = modelElemList.front().first;
rendering::VisualPtr modelVis = modelElemList.front().second;
modelElemList.pop_front();
std::string modelName = modelVis->GetName();
// create model
sdf::ElementPtr linkElem;
if (modelElem->HasElement("link"))
linkElem = modelElem->GetElement("link");
try
{
while (linkElem)
{
std::string linkName = linkElem->Get<std::string>("name");
if (linkElem->HasElement("pose"))
linkPose = linkElem->Get<ignition::math::Pose3d>("pose");
else
linkPose.Set(0, 0, 0, 0, 0, 0);
rendering::VisualPtr linkVisual(new rendering::Visual(modelName + "::" +
linkName, modelVis));
linkVisual->Load();
linkVisual->SetPose(linkPose);
dPtr->visuals.push_back(linkVisual);
int visualIndex = 0;
sdf::ElementPtr visualElem;
if (linkElem->HasElement("visual"))
visualElem = linkElem->GetElement("visual");
while (visualElem)
{
if (visualElem->HasElement("pose"))
visualPose = visualElem->Get<ignition::math::Pose3d>("pose");
else
visualPose.Set(0, 0, 0, 0, 0, 0);
std::ostringstream visualName;
visualName << modelName << "::" << linkName << "::Visual_"
<< visualIndex++;
rendering::VisualPtr visVisual(new rendering::Visual(visualName.str(),
linkVisual));
visVisual->Load(visualElem);
visVisual->SetPose(visualPose);
dPtr->visuals.push_back(visVisual);
visualElem = visualElem->GetNextElement("visual");
}
linkElem = linkElem->GetNextElement("link");
}
}
catch(common::Exception &_e)
{
this->Stop();
}
// append other model elems to the list
if (modelElem->HasElement("model"))
{
sdf::ElementPtr childElem = modelElem->GetElement("model");
while (childElem)
{
rendering::VisualPtr childVis;
std::string childName = childElem->Get<std::string>("name");
childVis.reset(new rendering::Visual(modelName + "::" + childName,
modelVis));
childVis->Load();
dPtr->visuals.push_back(childVis);
math::Pose childPose;
if (childElem->HasElement("pose"))
childPose = childElem->Get<math::Pose>("pose");
childVis->SetPose(childPose);
std::pair<sdf::ElementPtr, rendering::VisualPtr> childPair(
childElem, childVis);
modelElemList.push_back(childPair);
childElem = childElem->GetNextElement("model");
}
}
}
}
/////////////////////////////////////////////////
void ModelMaker::Stop()
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
// Remove the temporary visual from the scene
rendering::ScenePtr scene = gui::get_active_camera()->GetScene();
if (scene)
{
for (auto vis : dPtr->visuals)
{
auto v = vis.lock();
if (v)
scene->RemoveVisual(v);
}
scene->RemoveVisual(dPtr->modelVisual);
}
dPtr->modelVisual.reset();
dPtr->modelSDF.reset();
EntityMaker::Stop();
}
/////////////////////////////////////////////////
void ModelMaker::CreateTheEntity()
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
msgs::Factory msg;
if (!dPtr->clone)
{
sdf::ElementPtr modelElem;
if (dPtr->modelSDF->Root()->HasElement("model"))
{
modelElem = dPtr->modelSDF->Root()->GetElement("model");
}
else
{
gzerr << "Couldn't find model element in sdf, won't create entity."
<< std::endl;
return;
}
// The server will generate a unique name in case of name collision
std::string modelName = modelElem->Get<std::string>("name");
// Remove the topic namespace from the model name. This will get re-inserted
// by the World automatically
modelName.erase(0, dPtr->node->GetTopicNamespace().size()+2);
// The the SDF model's name
modelElem->GetAttribute("name")->Set(modelName);
modelElem->GetElement("pose")->Set(
dPtr->modelVisual->GetWorldPose().Ign());
// Spawn the model in the physics server
msg.set_sdf(dPtr->modelSDF->ToString());
}
else
{
msgs::Set(msg.mutable_pose(), dPtr->modelVisual->GetWorldPose().Ign());
msg.set_clone_model_name(dPtr->modelVisual->GetName().substr(0,
dPtr->modelVisual->GetName().find("_clone_tmp")));
}
dPtr->makerPub->Publish(msg);
}
/////////////////////////////////////////////////
ignition::math::Vector3d ModelMaker::EntityPosition() const
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
return dPtr->modelVisual->GetWorldPose().pos.Ign();
}
/////////////////////////////////////////////////
void ModelMaker::SetEntityPosition(const ignition::math::Vector3d &_pos)
{
ModelMakerPrivate *dPtr =
static_cast<ModelMakerPrivate *>(this->dataPtr);
dPtr->modelVisual->SetWorldPosition(_pos);
}