ClutteredSceneGenerator.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package ArmarXSimulation::ArmarXObjects::ClutteredSceneGenerator
17  * @author Patrick Hegemann ( patrick dot hegemann at kit dot edu )
18  * @date 2021
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
28 
32 
33 #include <VirtualRobot/CollisionDetection/CollisionChecker.h>
34 #include <VirtualRobot/ManipulationObject.h>
35 #include <VirtualRobot/Obstacle.h>
36 #include <VirtualRobot/SceneObjectSet.h>
37 #include <VirtualRobot/XML/RobotIO.h>
38 #include <VirtualRobot/XML/ObjectIO.h>
39 
40 #include <SimoxUtility/math/pose/pose.h>
41 
42 #include <boost/random/uniform_int.hpp>
43 #include <boost/random/uniform_real.hpp>
44 
45 #include <memory>
46 #include <string>
47 
49 {
50  ClutteredSceneGenerator::ClutteredSceneGenerator(const armarx::SimulatorInterfacePrx& simulator,
51  const ClutteredSceneGenerator::Config &config) :
52  config_(config),
53  simulator_(simulator)
54  {
55  createCollisionWalls();
56  }
57 
59  {
60  deleteLocalObjectCopies();
61 
62  simulator_->stop();
63 
64  rnd_.seed(seed);
65 
66  ARMARX_CHECK(!config_.objectSets.empty()) << "No object set configured.";
67 
68  for (uint i = 0; i < config_.amountObjects; ++i)
69  {
70  // Rotate through object sets
71  const size_t objectSetIndex = i % config_.objectSets.size();
72  const ObjectSet& objectSet = config_.objectSets[objectSetIndex];
73  ARMARX_CHECK(!objectSet.objects.empty()) << "Object set is empty.";
74 
75  // Select random object from this set
76  const boost::uniform_int<uint> uniform(0, objectSet.objects.size() - 1);
77  const size_t objectIndex = uniform(rnd_);
78  const ObjectSource& objectSource = objectSet.objects[objectIndex];
79 
80  // Spawn this object in the simulator
81  std::string objectName = "obj_" + std::to_string(i);;
82  if (objectSource.objectID)
83  {
84  armarx::ObjectID newID(objectSource.objectID.value());
85  newID.setInstanceName(objectName);
86  objectName = newID.str();
87  }
88  std::unique_ptr<SimulatedObject> object = makeObject(objectName, objectSource);
89  object->setLocalPose(randomObjectPose(i));
90  object->addToSimulator(simulator_);
91  object->updatePoseToSimulator(simulator_);
92  localObjectCopies_.push_back(std::move(object));
93  }
94 
95  // Let objects fall onto the table
96  dropObjects();
97 
98  // Try to reset some objects until all of them are on the table
99  if (config_.autoResetInvalidObjects)
100  {
101  resetInvalidObjects();
102  }
103 
104  simulator_->start();
105  }
106 
107  void ClutteredSceneGenerator::createCollisionWalls()
108  {
109  // Initialize invisible walls for object collision checking
110  const float wallHeight = 1000;
111  frontWall_ = VirtualRobot::Obstacle::createBox(config_.boxW, 1, wallHeight);
112  backWall_ = VirtualRobot::Obstacle::createBox(config_.boxW, 1, wallHeight);
113  leftWall_ = VirtualRobot::Obstacle::createBox(1, config_.boxH, wallHeight);
114  rightWall_ = VirtualRobot::Obstacle::createBox(1, config_.boxH, wallHeight);
115 
116  const float wallZ = config_.boxZ + config_.boxD + wallHeight / 2;
117  frontWall_->setGlobalPose(simox::math::pose(Eigen::Vector3f{config_.boxX, config_.boxY - config_.boxH / 2.0f, wallZ}));
118  backWall_->setGlobalPose(simox::math::pose(Eigen::Vector3f{config_.boxX, config_.boxY + config_.boxH / 2.0f, wallZ}));
119  leftWall_->setGlobalPose(simox::math::pose(Eigen::Vector3f{config_.boxX - config_.boxW / 2.0f, config_.boxY, wallZ}));
120  rightWall_->setGlobalPose(simox::math::pose(Eigen::Vector3f{config_.boxX + config_.boxW / 2.0f, config_.boxY, wallZ}));
121 
122  walls_.reset(new VirtualRobot::SceneObjectSet("walls"));
123  walls_->addSceneObject(frontWall_);
124  walls_->addSceneObject(backWall_);
125  walls_->addSceneObject(leftWall_);
126  walls_->addSceneObject(rightWall_);
127  }
128 
129  armarx::PosePtr ClutteredSceneGenerator::randomObjectPose(uint heightIndex)
130  {
131  // Object position and angle random distributions
132  boost::uniform_real<float> objectPositionDistX(config_.minObjectX, config_.maxObjectX);
133  boost::uniform_real<float> objectPositionDistY(config_.minObjectY, config_.maxObjectY);
134  boost::uniform_real<float> objectAngleDist(0, 2 * M_PI);
135 
136  // Sample random position and rotation around z-axis
137  float x = objectPositionDistX(rnd_);
138  float y = objectPositionDistY(rnd_);
139  float z = config_.minObjectZ + static_cast<float>(heightIndex) * config_.objectSpacingZ;
140  float angle = objectAngleDist(rnd_);
141 
142  Eigen::AngleAxisf rotation(angle, Eigen::Vector3f::UnitZ());
143  armarx::PosePtr pose(new Pose(simox::math::pose(Eigen::Vector3f{x, y, z}, rotation)));
144  return pose;
145  }
146 
147  void ClutteredSceneGenerator::deleteLocalObjectCopies()
148  {
149  localObjectCopies_.clear();
150  }
151 
152  std::unique_ptr<SimulatedObject>
153  ClutteredSceneGenerator::makeObject(const std::string& name, const ObjectSource& objectSource)
154  {
155  switch (objectSource.type) {
156  case AsObject:
157  return std::make_unique<SimulatedObjectAsObject>(name, objectSource);
158  case AsRobot:
159  return std::make_unique<SimulatedObjectAsRobot>(name, objectSource);
160  case Automatic:
161  // TODO(patrick.hegemann): Implement (look up top-level tag in simox xml)
162  ARMARX_INFO << __FUNCTION__ << " Unknown SimulationObjectType: TO DO: Implement";
163  return nullptr;
164  default:
165  ARMARX_ERROR << __FUNCTION__ << " - unknown object type for " << name;
166  return nullptr;
167  }
168  }
169 
170  void ClutteredSceneGenerator::updateLocalObjectCopies()
171  {
172  for (const auto& object : localObjectCopies_)
173  {
174  object->updatePoseFromSimulator(simulator_);
175  }
176  }
177 
178  void ClutteredSceneGenerator::dropObjects()
179  {
180  simulator_->stop();
181  for (uint k = 0; k < config_.fallingSteps; ++k)
182  {
183  simulator_->step();
184  }
185  simulator_->start();
186  }
187 
188  void ClutteredSceneGenerator::resetInvalidObjects()
189  {
190  VirtualRobot::CollisionCheckerPtr col = VirtualRobot::CollisionChecker::getGlobalCollisionChecker();
191  bool anyRespawn = false;
192 
193  // Try to reset the objects a number of times, or until all objects are inside the box
194  for (uint i = 0; i < config_.maxResetTries; ++i)
195  {
196  updateLocalObjectCopies();
197 
198  // TODO(patrick.hegemann): clean up magic number
199  int heightIndex = 6;
200  anyRespawn = false;
201 
202  // Check and reset every object
203  // for (const VirtualRobot::RobotPtr& robot : localObjectCopies_)
204  for (const auto& object : localObjectCopies_)
205  {
206  // Check if object collides with the imaginary walls around the box
207  bool collision = object->checkCollision(col, walls_);
208 
209  float z = object->getLocalPose()->position->z;
210  bool isObjectOutsideOfTable = z < config_.minObjectZOtherwiseReset;
211 
212  // Respawn object if necessary
213  if (collision || isObjectOutsideOfTable)
214  {
215  anyRespawn = true;
216  object->setLocalPose(randomObjectPose(heightIndex));
217  object->updatePoseToSimulator(simulator_);
218  heightIndex++;
219  }
220  }
221 
222  // Let objects fall again if anything has changed
223  if (!anyRespawn)
224  {
225  break;
226  }
227  dropObjects();
228  }
229  }
230 
232  {
233  return config_;
234  }
235 
237  {
238  ClutteredSceneGenerator::config_ = conf;
239  }
240 
241  const SimulatorInterfacePrx &ClutteredSceneGenerator::getSimulator() const
242  {
243  return simulator_;
244  }
245 
246  void ClutteredSceneGenerator::setSimulator(const SimulatorInterfacePrx &sim)
247  {
248  ClutteredSceneGenerator::simulator_ = sim;
249  }
250 } // namespace armarx::simulation::scene_generation
armarx::ObjectID
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition: ObjectID.h:11
armarx::simulation::scene_generation::ObjectSource
Definition: SimulatedObject.h:44
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::minObjectZOtherwiseReset
float minObjectZOtherwiseReset
Definition: ClutteredSceneGenerator.h:89
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::simulation::scene_generation::ClutteredSceneGenerator::setConfig
void setConfig(const Config &conf)
Definition: ClutteredSceneGenerator.cpp:236
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::maxResetTries
uint maxResetTries
Maximum number of retries when resetting objects.
Definition: ClutteredSceneGenerator.h:66
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config
Definition: ClutteredSceneGenerator.h:52
armarx::simulation::scene_generation::ObjectSet::objects
std::vector< ObjectSource > objects
Definition: SimulatedObject.h:54
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxX
float boxX
Definition: ClutteredSceneGenerator.h:69
armarx::simulation::scene_generation
Definition: ClutteredSceneGenerator.cpp:48
armarx::simulation::scene_generation::ClutteredSceneGenerator::getSimulator
const SimulatorInterfacePrx & getSimulator() const
Definition: ClutteredSceneGenerator.cpp:241
armarx::simulation::scene_generation::AsObject
@ AsObject
Definition: SimulatedObject.h:39
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::maxObjectY
float maxObjectY
Definition: ClutteredSceneGenerator.h:85
SimulatedObjectAsRobot.h
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::minObjectX
float minObjectX
Definition: ClutteredSceneGenerator.h:82
armarx::simulation::scene_generation::ClutteredSceneGenerator::generateScene
void generateScene(int seed)
Definition: ClutteredSceneGenerator.cpp:58
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::simulation::scene_generation::ObjectSource::objectID
std::optional< armarx::ObjectID > objectID
Definition: SimulatedObject.h:49
armarx::simulation::scene_generation::ObjectSet
Definition: SimulatedObject.h:52
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::minObjectZ
float minObjectZ
Definition: ClutteredSceneGenerator.h:86
IceInternal::Handle< Pose >
M_PI
#define M_PI
Definition: MathTools.h:17
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxD
float boxD
Definition: ClutteredSceneGenerator.h:74
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::minObjectY
float minObjectY
Definition: ClutteredSceneGenerator.h:83
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxH
float boxH
Definition: ClutteredSceneGenerator.h:73
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::objectSpacingZ
float objectSpacingZ
Definition: ClutteredSceneGenerator.h:79
ObjectID.h
armarx::simulation::scene_generation::AsRobot
@ AsRobot
Definition: SimulatedObject.h:40
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxZ
float boxZ
Definition: ClutteredSceneGenerator.h:71
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
SimulatedObject.h
SimulatedObjectAsObject.h
armarx::simulation::scene_generation::ClutteredSceneGenerator::getConfig
const Config & getConfig() const
Definition: ClutteredSceneGenerator.cpp:231
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::amountObjects
uint amountObjects
Number of objects to generate in a scene.
Definition: ClutteredSceneGenerator.h:58
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::simulation::scene_generation::ClutteredSceneGenerator::ClutteredSceneGenerator
ClutteredSceneGenerator(const armarx::SimulatorInterfacePrx &simulator, const Config &config)
Definition: ClutteredSceneGenerator.cpp:50
ExpressionException.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::objectSets
std::vector< ObjectSet > objectSets
Definition: ClutteredSceneGenerator.h:55
angle
double angle(const Point &a, const Point &b, const Point &c)
Definition: point.hpp:100
ClutteredSceneGenerator.h
armarx::simulation::scene_generation::ClutteredSceneGenerator::setSimulator
void setSimulator(const SimulatorInterfacePrx &simulator)
Definition: ClutteredSceneGenerator.cpp:246
Logging.h
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxY
float boxY
Definition: ClutteredSceneGenerator.h:70
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::maxObjectX
float maxObjectX
Definition: ClutteredSceneGenerator.h:84
armarx::simulation::scene_generation::Automatic
@ Automatic
Definition: SimulatedObject.h:41
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::autoResetInvalidObjects
bool autoResetInvalidObjects
Whether to automatically reset invalid objects after scene generation.
Definition: ClutteredSceneGenerator.h:64
armarx::ObjectID::str
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
Definition: ObjectID.cpp:55
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::boxW
float boxW
Definition: ClutteredSceneGenerator.h:72
armarx::simulation::scene_generation::ClutteredSceneGenerator::Config::fallingSteps
uint fallingSteps
Number of simulation steps executed for letting objects fall onto the table.
Definition: ClutteredSceneGenerator.h:61
armarx::ObjectID::setInstanceName
void setInstanceName(const std::string &instanceName)
Definition: ObjectID.h:36