-
Notifications
You must be signed in to change notification settings - Fork 304
Modelpropshop gazebo plugin port #1331
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
Changes from 3 commits
387aaa7
b7a0ac7
8b12d5c
43dc07d
d16f688
4c64557
ebcf122
00dbb5c
bbbf263
3f1e5a4
cd6f7c6
a712a0e
b0dc697
c0c14b0
2ed80f3
2eefd53
8899e20
bb3d391
e0965ca
40796db
c17a158
59a8870
a9dee08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<sdf version="1.6"> | ||
<world name="default"> | ||
<plugin | ||
filename="ignition-gazebo-physics-system" | ||
name="ignition::gazebo::systems::Physics"> | ||
</plugin> | ||
<plugin | ||
filename="ignition-gazebo-sensors-system" | ||
name="ignition::gazebo::systems::Sensors"> | ||
<render_engine>ogre2</render_engine> | ||
<background_color>1, 1, 1</background_color> | ||
</plugin> | ||
<plugin | ||
filename="ignition-gazebo-user-commands-system" | ||
name="ignition::gazebo::systems::UserCommands"> | ||
</plugin> | ||
<plugin | ||
filename="ignition-gazebo-scene-broadcaster-system" | ||
name="ignition::gazebo::systems::SceneBroadcaster"> | ||
</plugin> | ||
<include> | ||
<uri>https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/barcs_qav500_sensor_config_1</uri> | ||
<plugin | ||
filename="ignition-gazebo-model-photo-shoot-system" | ||
name="ignition::gazebo::systems::ModelPhotoShoot"> | ||
<translation_data_file>poses.txt</translation_data_file> | ||
<random_joints_pose>false</random_joints_pose> | ||
</plugin> | ||
</include> | ||
<model name="photo_shoot"> | ||
<pose>2.2 0 0 0 0 -3.14</pose> | ||
<link name="link"> | ||
<pose>0 0 0 0 0 0</pose> | ||
<sensor name="camera" type="camera"> | ||
<camera> | ||
<horizontal_fov>1.047</horizontal_fov> | ||
<image> | ||
<width>960</width> | ||
<height>540</height> | ||
</image> | ||
<clip> | ||
<near>0.1</near> | ||
<far>100</far> | ||
</clip> | ||
</camera> | ||
<always_on>1</always_on> | ||
<update_rate>30</update_rate> | ||
<visualize>true</visualize> | ||
<topic>camera</topic> | ||
</sensor> | ||
</link> | ||
<static>true</static> | ||
</model> | ||
</world> | ||
</sdf> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
gz_add_system(model-photo-shoot | ||
SOURCES | ||
ModelPhotoShoot.cc | ||
PUBLIC_LINK_LIBS | ||
ignition-common${IGN_COMMON_VER}::ignition-common${IGN_COMMON_VER} | ||
ignition-rendering${IGN_RENDERING_VER}::ignition-rendering${IGN_RENDERING_VER} | ||
ignition-transport${IGN_TRANSPORT_VER}::ignition-transport${IGN_TRANSPORT_VER} | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
/* | ||
* Copyright (C) 2019 Open Source Robotics Foundation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: 2022 |
||
* | ||
* 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 "ModelPhotoShoot.hh" | ||
|
||
#include <random> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "ignition/gazebo/components/Joint.hh" | ||
#include "ignition/gazebo/components/JointAxis.hh" | ||
#include "ignition/gazebo/components/JointPosition.hh" | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include "ignition/gazebo/components/JointPositionLimitsCmd.hh" | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include "ignition/gazebo/components/JointPositionReset.hh" | ||
#include <ignition/common/Image.hh> | ||
#include <ignition/gazebo/World.hh> | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include <ignition/gazebo/components/Name.hh> | ||
#include <ignition/gazebo/components/Pose.hh> | ||
#include <ignition/gazebo/rendering/Events.hh> | ||
#include <ignition/msgs.hh> | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include <ignition/plugin/Register.hh> | ||
#include <ignition/rendering/Scene.hh> | ||
#include <ignition/gazebo/Util.hh> | ||
#include <ignition/rendering/Visual.hh> | ||
#include <ignition/rendering/WireBox.hh> | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
using namespace ignition; | ||
using namespace gazebo; | ||
using namespace systems; | ||
|
||
/// \brief Private ModelPhotoShoot data class. | ||
class ignition::gazebo::systems::ModelPhotoShootPrivate | ||
{ | ||
/// \brief Callback for pos rendering operations. | ||
public: void PerformPostRenderingOperations(); | ||
|
||
/// \brief Save a pitcture with the camera from the given pose. | ||
public: void SavePicture (const ignition::rendering::CameraPtr _camera, | ||
const ignition::math::Pose3d _pose, | ||
const std::string _fileName) const; | ||
|
||
/// \brief Name of the loaded model. | ||
public: std::string modelName; | ||
|
||
/// \brief model | ||
public: std::shared_ptr<ignition::gazebo::Model> model; | ||
|
||
/// \brief model world pose | ||
public: ignition::math::Pose3d modelPose3D; | ||
|
||
/// \brief Connection to pre-render event callback. | ||
public: ignition::common::ConnectionPtr connection{nullptr}; | ||
|
||
/// \brief Boolean to control we only take the pictures once. | ||
public: bool takePicture{true}; | ||
|
||
/// \brief Boolean to control if joints should adopt random poses. | ||
public: bool randomPoses{false}; | ||
|
||
/// \brief File to save translation and scaling info. | ||
public: std::ofstream savingFile; | ||
}; | ||
|
||
////////////////////////////////////////////////// | ||
ModelPhotoShoot::ModelPhotoShoot() | ||
: System(), dataPtr(std::make_unique<ModelPhotoShootPrivate>()) | ||
{ | ||
} | ||
|
||
////////////////////////////////////////////////// | ||
void ModelPhotoShoot::Configure(const ignition::gazebo::Entity &_entity, | ||
const std::shared_ptr<const sdf::Element> &_sdf, | ||
ignition::gazebo::EntityComponentManager &_ecm, | ||
ignition::gazebo::EventManager &_eventMgr) | ||
{ | ||
std::string save_data_location = | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_sdf->Get<std::string>("translation_data_file"); | ||
if (save_data_location.empty()) | ||
{ | ||
igndbg << "No data location specified, skipping translaiton data" | ||
"saving.\n"; | ||
} | ||
else | ||
{ | ||
igndbg << "Saving translation data to: " | ||
<< save_data_location << std::endl; | ||
this->dataPtr->savingFile.open(save_data_location); | ||
} | ||
|
||
if (_sdf->HasElement("random_joints_pose")) | ||
{ | ||
this->dataPtr->randomPoses = _sdf->Get<bool>("random_joints_pose"); | ||
} | ||
|
||
this->dataPtr->connection = | ||
_eventMgr.Connect<ignition::gazebo::events::PostRender>(std::bind( | ||
&ModelPhotoShootPrivate::PerformPostRenderingOperations, | ||
this->dataPtr.get())); | ||
|
||
this->dataPtr->model = std::make_shared<ignition::gazebo::Model>(_entity); | ||
this->dataPtr->modelName = this->dataPtr->model->Name(_ecm); | ||
// Get the pose of the model | ||
this->dataPtr->modelPose3D = | ||
ignition::gazebo::worldPose(this->dataPtr->model->Entity(), _ecm); | ||
} | ||
|
||
////////////////////////////////////////////////// | ||
void ModelPhotoShoot::PreUpdate( | ||
const ignition::gazebo::UpdateInfo &, | ||
ignition::gazebo::EntityComponentManager &_ecm) | ||
{ | ||
if (this->dataPtr->randomPoses) | ||
{ | ||
std::vector<gazebo::Entity> joints = this->dataPtr->model->Joints(_ecm); | ||
unsigned seed = | ||
std::chrono::system_clock::now().time_since_epoch().count(); | ||
std::default_random_engine generator(seed); | ||
for (auto joint = joints.begin(); joint != joints.end(); ++joint) | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
auto jointNameComp = _ecm.Component<components::Name>(*joint); | ||
if (jointNameComp && jointNameComp->Data() != "World") | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
// Using the JointAxis component to extract the joint pose limits | ||
auto jointAxisComp = _ecm.Component<components::JointAxis>(*joint); | ||
if (jointAxisComp) | ||
{ | ||
float mean = | ||
(jointAxisComp->Data().Lower() + | ||
jointAxisComp->Data().Upper()) / 2; | ||
float stdv = (jointAxisComp->Data().Upper() - mean) / 3; | ||
std::normal_distribution<float> distribution(mean, stdv); | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
float jointPose = distribution(generator); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a |
||
_ecm.SetComponentData<components::JointPositionReset>(*joint, | ||
azeey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{jointPose}); | ||
if (this->dataPtr->savingFile.is_open()) | ||
{ | ||
this->dataPtr->savingFile << jointNameComp->Data() << ": " | ||
<< jointPose << std::endl; | ||
} | ||
} | ||
else | ||
{ | ||
igndbg << "No jointAxisComp found, ignoring joint: " << | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be at least a warning, if not an error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't sure if there was any valid case in which a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, that reminds me about fixed joints. We should probably check the joint type and ignore it if it's fixed. It would also be good to emit an error if the joint type is not Revolute or Prismatic. |
||
jointNameComp->Data() << std::endl; | ||
} | ||
} | ||
} | ||
// Only set random joint poses once | ||
this->dataPtr->randomPoses = false; | ||
} | ||
} | ||
|
||
////////////////////////////////////////////////// | ||
void ModelPhotoShootPrivate::PerformPostRenderingOperations() | ||
{ | ||
ignition::rendering::ScenePtr scene = | ||
ignition::rendering::sceneFromFirstRenderEngine(); | ||
ignition::rendering::VisualPtr modelVisual = | ||
scene->VisualByName(this->modelName); | ||
|
||
ignition::rendering::VisualPtr root = scene->RootVisual(); | ||
|
||
if (modelVisual && this->takePicture) | ||
{ | ||
scene->SetAmbientLight(0.3, 0.3, 0.3); | ||
|
||
// create directional light | ||
ignition::rendering::DirectionalLightPtr light0 = | ||
scene->CreateDirectionalLight(); | ||
light0->SetDirection(-0.5, 0.5, -1); | ||
light0->SetDiffuseColor(0.8, 0.8, 0.8); | ||
light0->SetSpecularColor(0.5, 0.5, 0.5); | ||
root->AddChild(light0); | ||
|
||
// create point light | ||
ignition::rendering::PointLightPtr light2 = scene->CreatePointLight(); | ||
light2->SetDiffuseColor(0.5, 0.5, 0.5); | ||
light2->SetSpecularColor(0.5, 0.5, 0.5); | ||
light2->SetLocalPosition(3, 5, 5); | ||
root->AddChild(light2); | ||
|
||
for (unsigned int i = 0; i < scene->NodeCount(); ++i) | ||
{ | ||
auto camera = std::dynamic_pointer_cast<ignition::rendering::Camera>( | ||
scene->NodeByIndex(i)); | ||
if (nullptr != camera && camera->Name() == "photo_shoot::link::camera") | ||
{ | ||
// Compute the translation we have to apply to the cameras to | ||
// center the model in the image. | ||
ignition::math::AxisAlignedBox bbox = modelVisual->LocalBoundingBox(); | ||
double scaling = 1.0 / bbox.Size().Max(); | ||
ignition::math::Vector3d bboxCenter = bbox.Center(); | ||
ignition::math::Vector3d translation = | ||
bboxCenter + this->modelPose3D.Pos(); | ||
if (this->savingFile.is_open()) { | ||
this->savingFile << "Translation: " << translation << std::endl; | ||
this->savingFile << "Scaling: " << scaling << std::endl; | ||
} | ||
|
||
ignition::math::Pose3d pose; | ||
// Perspective view | ||
pose.Pos().Set(1.6 / scaling + translation.X(), | ||
-1.6 / scaling + translation.Y(), | ||
1.2 / scaling + translation.Z()+0.078); | ||
pose.Rot().Euler(0, IGN_DTOR(30), IGN_DTOR(-225)); | ||
SavePicture(camera, pose, "1.png"); | ||
|
||
// Top view | ||
pose.Pos().Set(0 + translation.X(), | ||
0 + translation.Y(), | ||
2.2 / scaling + translation.Z()+0.078); | ||
pose.Rot().Euler(0, IGN_DTOR(90), 0); | ||
SavePicture(camera, pose, "2.png"); | ||
|
||
// Front view | ||
pose.Pos().Set(2.2 / scaling + translation.X(), | ||
0 + translation.Y(), | ||
0 + translation.Z()+0.078); | ||
pose.Rot().Euler(0, 0, IGN_DTOR(-180)); | ||
SavePicture(camera, pose, "3.png"); | ||
|
||
// Side view | ||
pose.Pos().Set(0 + translation.X(), | ||
2.2 / scaling + translation.Y(), | ||
0 + translation.Z()+0.078); | ||
pose.Rot().Euler(0, 0, IGN_DTOR(-90)); | ||
SavePicture(camera, pose, "4.png"); | ||
|
||
// Back view | ||
pose.Pos().Set(-2.2 / scaling + translation.X(), | ||
0 + translation.Y(), | ||
0 + translation.Z()+0.078); | ||
pose.Rot().Euler(0, 0, 0); | ||
SavePicture(camera, pose, "5.png"); | ||
|
||
this->takePicture = false; | ||
} | ||
} | ||
} | ||
} | ||
|
||
////////////////////////////////////////////////// | ||
void ModelPhotoShootPrivate::SavePicture( | ||
const ignition::rendering::CameraPtr _camera, | ||
const ignition::math::Pose3d _pose, | ||
marcoag marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const std::string _fileName) const | ||
marcoag marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
unsigned int width = _camera->ImageWidth(); | ||
unsigned int height = _camera->ImageHeight(); | ||
ignition::common::Image image; | ||
|
||
_camera->SetWorldPose(_pose); | ||
auto cameraImage = _camera->CreateImage(); | ||
_camera->Capture(cameraImage); | ||
auto formatStr = | ||
ignition::rendering::PixelUtil::Name(_camera->ImageFormat()); | ||
auto format = ignition::common::Image::ConvertPixelFormat(formatStr); | ||
image.SetFromData(cameraImage.Data<unsigned char>(), width, height, format); | ||
std::string fullName = _fileName; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason for the copy of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, previously I was adding the extension at this point but since it's not done anymore we don't need this. |
||
image.SavePNG(fullName); | ||
|
||
igndbg << "Saved image to [" << fullName << "]" << std::endl; | ||
} | ||
|
||
IGNITION_ADD_PLUGIN(ModelPhotoShoot, ignition::gazebo::System, | ||
ModelPhotoShoot::ISystemConfigure, | ||
ModelPhotoShoot::ISystemPreUpdate) | ||
|
||
IGNITION_ADD_PLUGIN_ALIAS(ModelPhotoShoot, | ||
"ignition::gazebo::systems::ModelPhotoShoot") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the command to run
ign-gazebo
as in the other example sdf files? Perhaps include the number of iterations.