Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model editor #1231

Merged
merged 44 commits into from
Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
cebbedc
Model editor: Add links to model (#1165)
iche033 Nov 10, 2021
ba9403b
Support recreating model entities (#1170)
iche033 Nov 17, 2021
9d4cd24
Support editing air pressure sensor in the GUI (#1171)
nkoenig Nov 17, 2021
0cc0c56
Added altimeter sensor inspector (#1172)
nkoenig Nov 18, 2021
b1f8525
Added magnetometer inspector (#1173)
nkoenig Nov 19, 2021
5d7c95f
Add IMU component inspector (#1191)
nkoenig Nov 22, 2021
65cc189
Added lidar component inspector (#1203)
nkoenig Nov 22, 2021
d392d0f
Model Editor: Add Joints to model (#1196)
mjcarroll Dec 1, 2021
9d0471f
Allow user to modify joint type (#1198)
mjcarroll Dec 1, 2021
e427bed
merged with ign-gazebo6
Dec 1, 2021
93893f0
Add sensors to a link via the GUI (#1188)
nkoenig Dec 2, 2021
196b2f2
Merge branch 'ign-gazebo6' into model_editor
Dec 3, 2021
6ae8a65
Merge branch 'model_editor' of github.com:ignitionrobotics/ign-gazebo…
Dec 3, 2021
58d266e
Support setting pose on links, visuals, collision via the GUI (#1230)
nkoenig Dec 3, 2021
2644180
alphabetize
Dec 3, 2021
a9f9443
Pimplize a class and added units, and 'joint'
Dec 3, 2021
5da1ecd
remove laser
Dec 3, 2021
5a67d1a
Added extra note
Dec 3, 2021
770b64c
Addressing comments
Dec 3, 2021
55f4703
Allow models to transform
Dec 3, 2021
6c77ef7
remove console log
Dec 3, 2021
f948a9a
rename componentinspector in qml
Dec 4, 2021
e65a6b1
Update based on comments
Dec 4, 2021
a819658
Don't publish ECM changes when paused
Dec 6, 2021
af3afb6
Apply patch
Dec 6, 2021
414e082
Fix joint type dropdown
Dec 6, 2021
cc3ee2b
Joint type spacing
Dec 6, 2021
333331d
Fix codecheck
Dec 6, 2021
fb20f1f
editor changes
Dec 7, 2021
1b3798f
Recereate on sensors
Dec 7, 2021
b5f3778
Don't allow world as child link
Dec 8, 2021
531ce22
Merge branch 'ign-gazebo6' into model_editor
Dec 8, 2021
936d681
Merge branch 'ign-gazebo6' into model_editor
nkoenig Dec 8, 2021
af4b6c2
Merge branch 'ign-gazebo6' into model_editor
Dec 8, 2021
d1f9d91
Fix scene broadcaster test, and add another modelcommandapi test
Dec 8, 2021
62ae75c
Added model command api gpu lidar test
Dec 8, 2021
51536fb
use MAX_VALUE
Dec 8, 2021
c797584
Added units to model command
Dec 8, 2021
f8fe454
Fix tests
Dec 8, 2021
b60aac6
Added ProcessNewWorldControlState test
Dec 9, 2021
369c3c5
Update test/worlds/gpu_lidar.sdf
nkoenig Dec 9, 2021
f32131b
Removed comments and plugins
Dec 9, 2021
df9f5f8
Merge branch 'model_editor' of github.com:ignitionrobotics/ign-gazebo…
Dec 9, 2021
0734a60
Update comments
Dec 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# as protobuf could be find transitively by any dependency
set(protobuf_MODULE_COMPATIBLE TRUE)

ign_find_package(sdformat12 REQUIRED VERSION 12.2)
ign_find_package(sdformat12 REQUIRED VERSION 12.3)
set(SDF_VER ${sdformat12_VERSION_MAJOR})

#--------------------------------------
Expand Down Expand Up @@ -110,7 +110,7 @@ set(IGN_PHYSICS_VER ${ignition-physics5_VERSION_MAJOR})

#--------------------------------------
# Find ignition-sensors
ign_find_package(ignition-sensors6 REQUIRED
ign_find_package(ignition-sensors6 REQUIRED VERSION 6.0.1
# component order is important
COMPONENTS
# non-rendering
Expand Down
2 changes: 1 addition & 1 deletion examples/worlds/sensors.sdf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" ?>
<!--
Ignition Gazebo sensor demo
Ignition Gazebo sensor demo for sensors that do not require rendering.

Listen to sensor readings:

Expand Down
7 changes: 7 additions & 0 deletions include/ignition/gazebo/SdfEntityCreator.hh
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ namespace ignition
/// \return Joint entity.
public: Entity CreateEntities(const sdf::Joint *_joint);

/// \brief Create all entities that exist in the sdf::Joint object and
/// load their plugins.
/// \param[in] _joint SDF joint object.
/// \param[in] _resolved True if all frames are already resolved
/// \return Joint entity.
public: Entity CreateEntities(const sdf::Joint *_joint, bool _resolved);

/// \brief Create all entities that exist in the sdf::Visual object and
/// load their plugins.
/// \param[in] _visual SDF visual object.
Expand Down
48 changes: 48 additions & 0 deletions include/ignition/gazebo/components/Recreate.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 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.
*
*/
#ifndef IGNITION_GAZEBO_COMPONENTS_RECREATE_HH_
#define IGNITION_GAZEBO_COMPONENTS_RECREATE_HH_

#include <ignition/gazebo/components/Factory.hh>
#include <ignition/gazebo/components/Component.hh>
#include <ignition/gazebo/config.hh>

namespace ignition
{
namespace gazebo
{
// Inline bracket to help doxygen filtering.
inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
namespace components
{
/// \brief A component that identifies an entity needs to be recreated.
/// Currently, only Models will be processed for recreation by the
/// SimulationRunner in the ProcessRecreateEntitiesRemove and
/// ProcessRecreateEntitiesCreate functions.
///
/// The GUI ModelEditor contains example code on how to use this
/// component. For example, the ModelEditor allows a user to add a link to an
/// existing model. The existing model is tagged with this component so
/// that it can be recreated by the server.
using Recreate = Component<NoData, class RecreateTag>;
IGN_GAZEBO_REGISTER_COMPONENT("ign_gazebo_components.Recreate", Recreate)
}
}
}
}

#endif
1 change: 1 addition & 0 deletions include/ignition/gazebo/components/Serialization.hh
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace serializers
const DataType &_data)
{
MsgType msg;
// cppcheck-suppress syntaxError
if constexpr (traits::HasGazeboConvert<DataType, MsgType>::value)
{
msg = ignition::gazebo::convert<MsgType>(_data);
Expand Down
4 changes: 4 additions & 0 deletions include/ignition/gazebo/detail/View.hh
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ template<typename ...ComponentTypeTs>
bool View<ComponentTypeTs...>::NotifyComponentRemoval(const Entity _entity,
const ComponentTypeId _typeId)
{
// if entity is still marked as to add, remove from the view
if (this->RequiresComponent(_typeId))
this->toAddEntities.erase(_entity);
nkoenig marked this conversation as resolved.
Show resolved Hide resolved

// make sure that _typeId is a type required by the view and that _entity is
// already a part of the view
if (!this->RequiresComponent(_typeId) ||
Expand Down
35 changes: 35 additions & 0 deletions include/ignition/gazebo/gui/GuiEvents.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#define IGNITION_GAZEBO_GUI_GUIEVENTS_HH_

#include <QEvent>
#include <QMap>
#include <QString>

#include <set>
#include <string>
#include <utility>
Expand Down Expand Up @@ -176,6 +179,38 @@ namespace events
/// \brief True if a transform mode is active.
private: bool tranformModeActive;
};

/// \brief Event that notifies an entity is to be added to the model editor
class ModelEditorAddEntity : public QEvent
{
/// \brief Constructor
/// \param[in] _entity Entity added
/// \param[in] _type Entity type
/// \param[in] _parent Parent entity.
public: explicit ModelEditorAddEntity(QString _entity, QString _type,
ignition::gazebo::Entity _parent);

/// \brief Get the entity to add
public: QString Entity() const;

/// \brief Get the entity type
public: QString EntityType() const;


/// \brief Get the parent entity to add the entity to
public: ignition::gazebo::Entity ParentEntity() const;

/// \brief Get the data map.
/// \return the QMap of string, string holding custom data.
public: QMap<QString, QString> &Data();

static const QEvent::Type kType = QEvent::Type(QEvent::User + 7);

/// \internal
/// \brief Private data pointer
IGN_UTILS_IMPL_PTR(dataPtr)
};

} // namespace events
}
} // namespace gui
Expand Down
9 changes: 9 additions & 0 deletions include/ignition/gazebo/rendering/RenderUtil.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define IGNITION_GAZEBO_RENDERUTIL_HH_

#include <memory>
#include <set>
#include <string>
#include <vector>

Expand Down Expand Up @@ -76,6 +77,14 @@ inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
public: void UpdateFromECM(const UpdateInfo &_info,
const EntityComponentManager &_ecm);

/// \brief Helper function to create visuals for new entities created in
/// ECM. This function is intended to be used by other GUI plugins when
/// new entities are created on the GUI side.
/// \param[in] _ecm Const reference to the entity component manager
/// \param[in] _entities Entities to create visuals for.
public: void CreateVisualsForEntities(const EntityComponentManager &_ecm,
const std::set<Entity> &_entities);

/// \brief Set the rendering engine to use
/// \param[in] _engineName Name of the rendering engine.
public: void SetEngineName(const std::string &_engineName);
Expand Down
112 changes: 91 additions & 21 deletions src/EntityComponentManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "ignition/gazebo/components/Name.hh"
#include "ignition/gazebo/components/ParentEntity.hh"
#include "ignition/gazebo/components/ParentLinkName.hh"
#include "ignition/gazebo/components/Recreate.hh"
#include "ignition/gazebo/components/World.hh"

using namespace ignition;
using namespace gazebo;
Expand Down Expand Up @@ -420,7 +422,30 @@ Entity EntityComponentManager::CloneImpl(Entity _entity, Entity _parent,
}
else if (!_name.empty() && !_allowRename)
{
if (kNullEntity != this->EntityByComponents(components::Name(_name)))
// Get the entity's original parent. This is used to make sure we get
// the correct entity. For example, two different models may have a
// child with the name "link".
auto origParentComp =
this->Component<components::ParentEntity>(_entity);

// If there is an entity with the same name and user indicated renaming is
// not allowed then return null entity.
// If the entity or one of its ancestor has a Recreate component then carry
// on since the ECM is supposed to create a new entity with the same name.
Entity ent = this->EntityByComponents(components::Name(_name),
components::ParentEntity(origParentComp->Data()));

bool hasRecreateComp = false;
Entity recreateEnt = ent;
while (recreateEnt != kNullEntity && !hasRecreateComp)
{
hasRecreateComp = this->Component<components::Recreate>(recreateEnt) !=
nullptr;
auto parentComp = this->Component<components::ParentEntity>(recreateEnt);
recreateEnt = parentComp ? parentComp->Data() : kNullEntity;
}

if (kNullEntity != ent && !hasRecreateComp)
{
ignerr << "Requested to clone entity [" << _entity
<< "] with a name of [" << _name << "], but another entity already "
Expand Down Expand Up @@ -497,19 +522,35 @@ Entity EntityComponentManager::CloneImpl(Entity _entity, Entity _parent,
Entity originalParentLink = kNullEntity;
Entity originalChildLink = kNullEntity;

auto origParentComp =
this->Component<components::ParentEntity>(_entity);

const auto &parentName =
this->Component<components::ParentLinkName>(_entity);
if (parentName)
if (parentName && origParentComp)
{
originalParentLink = this->EntityByComponents<components::Name>(
components::Name(parentName->Data()));
// Handle the case where the parent link name is the world.
if (common::lowercase(parentName->Data()) == "world")
{
originalParentLink = this->Component<components::ParentEntity>(
origParentComp->Data())->Data();
}
else
{
originalParentLink =
this->EntityByComponents<components::Name, components::ParentEntity>(
components::Name(parentName->Data()),
components::ParentEntity(origParentComp->Data()));
}
}

const auto &childName = this->Component<components::ChildLinkName>(_entity);
if (childName)
if (childName && origParentComp)
{
originalChildLink = this->EntityByComponents<components::Name>(
components::Name(childName->Data()));
originalChildLink =
this->EntityByComponents<components::Name, components::ParentEntity>(
components::Name(childName->Data()),
components::ParentEntity(origParentComp->Data()));
}

if (!originalParentLink || !originalChildLink)
Expand All @@ -533,7 +574,14 @@ Entity EntityComponentManager::CloneImpl(Entity _entity, Entity _parent,
for (const auto &childEntity :
this->EntitiesByComponents(components::ParentEntity(_entity)))
{
auto clonedChild = this->CloneImpl(childEntity, clonedEntity, "", true);
std::string name;
if (!_allowRename)
{
auto nameComp = this->Component<components::Name>(childEntity);
name = nameComp->Data();
}
auto clonedChild = this->CloneImpl(childEntity, clonedEntity, name,
_allowRename);
if (kNullEntity == clonedChild)
{
ignerr << "Cloning child entity [" << childEntity << "] failed.\n";
Expand Down Expand Up @@ -1045,6 +1093,14 @@ bool EntityComponentManager::CreateComponentImplementation(

this->dataPtr->createdCompTypes.insert(_componentTypeId);

// If the component is a components::ParentEntity, then make sure to
// update the entities graph.
if (_componentTypeId == components::ParentEntity::typeId)
{
auto parentComp = this->Component<components::ParentEntity>(_entity);
this->SetParentEntity(_entity, parentComp->Data());
}

return updateData;
}

Expand Down Expand Up @@ -1944,24 +2000,38 @@ bool EntityComponentManagerPrivate::ClonedJointLinkName(Entity _joint,
return false;
}

auto iter = this->originalToClonedLink.find(_originalLink);
if (iter == this->originalToClonedLink.end())
Entity clonedLink = kNullEntity;


std::string name;
// Handle the case where the link could have been the world.
if (_ecm->Component<components::World>(_originalLink) != nullptr)
{
ignerr << "Error: attempted to clone links, but link ["
<< _originalLink << "] was never cloned.\n";
return false;
// Use the special identifier "world".
name = "world";
}
auto clonedLink = iter->second;

auto name = _ecm->Component<components::Name>(clonedLink);
if (!name)
else
{
ignerr << "Link [" << _originalLink << "] was cloned, but its clone has no "
<< "name.\n";
return false;
auto iter = this->originalToClonedLink.find(_originalLink);
if (iter == this->originalToClonedLink.end())
{
ignerr << "Error: attempted to clone links, but link ["
<< _originalLink << "] was never cloned.\n";
return false;
}
clonedLink = iter->second;

auto nameComp = _ecm->Component<components::Name>(clonedLink);
if (!nameComp)
{
ignerr << "Link [" << _originalLink
<< "] was cloned, but its clone has no name.\n";
return false;
}
name = nameComp->Data();
}

_ecm->SetComponentData<ComponentTypeT>(_joint, name->Data());
_ecm->SetComponentData<ComponentTypeT>(_joint, name);
return true;
}

Expand Down
Loading