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
25#include <memory>
26#include <string>
27
28#include <boost/random/uniform_int.hpp>
29#include <boost/random/uniform_real.hpp>
30
31#include <SimoxUtility/math/pose/pose.h>
32#include <VirtualRobot/CollisionDetection/CollisionChecker.h>
33#include <VirtualRobot/ManipulationObject.h>
34#include <VirtualRobot/Obstacle.h>
35#include <VirtualRobot/SceneObjectSet.h>
36#include <VirtualRobot/XML/ObjectIO.h>
37#include <VirtualRobot/XML/RobotIO.h>
38
41
43
47
49{
51 const armarx::SimulatorInterfacePrx& simulator,
52 const ClutteredSceneGenerator::Config& config) :
53 config_(config), simulator_(simulator)
54 {
55 createCollisionWalls();
56 }
57
58 void
60 {
61 deleteLocalObjectCopies();
62
63 simulator_->stop();
64
65 rnd_.seed(seed);
66
67 ARMARX_CHECK(!config_.objectSets.empty()) << "No object set configured.";
68
69 for (uint i = 0; i < config_.amountObjects; ++i)
70 {
71 // Rotate through object sets
72 const size_t objectSetIndex = i % config_.objectSets.size();
73 const ObjectSet& objectSet = config_.objectSets[objectSetIndex];
74 ARMARX_CHECK(!objectSet.objects.empty()) << "Object set is empty.";
75
76 // Select random object from this set
77 const boost::uniform_int<uint> uniform(0, objectSet.objects.size() - 1);
78 const size_t objectIndex = uniform(rnd_);
79 const ObjectSource& objectSource = objectSet.objects[objectIndex];
80
81 // Spawn this object in the simulator
82 std::string objectName = "obj_" + std::to_string(i);
83 ;
84 if (objectSource.objectID)
85 {
86 armarx::ObjectID newID(objectSource.objectID.value());
87 newID.setInstanceName(objectName);
88 objectName = newID.str();
89 }
90 std::unique_ptr<SimulatedObject> object = makeObject(objectName, objectSource);
91 object->setLocalPose(randomObjectPose(i));
92 object->addToSimulator(simulator_);
93 object->updatePoseToSimulator(simulator_);
94 localObjectCopies_.push_back(std::move(object));
95 }
96
97 // Let objects fall onto the table
98 dropObjects();
99
100 // Try to reset some objects until all of them are on the table
101 if (config_.autoResetInvalidObjects)
102 {
103 resetInvalidObjects();
104 }
105
106 simulator_->start();
107 }
108
109 void
110 ClutteredSceneGenerator::createCollisionWalls()
111 {
112 // Initialize invisible walls for object collision checking
113 const float wallHeight = 1000;
114 frontWall_ = VirtualRobot::Obstacle::createBox(config_.boxW, 1, wallHeight);
115 backWall_ = VirtualRobot::Obstacle::createBox(config_.boxW, 1, wallHeight);
116 leftWall_ = VirtualRobot::Obstacle::createBox(1, config_.boxH, wallHeight);
117 rightWall_ = VirtualRobot::Obstacle::createBox(1, config_.boxH, wallHeight);
118
119 const float wallZ = config_.boxZ + config_.boxD + wallHeight / 2;
120 frontWall_->setGlobalPose(simox::math::pose(
121 Eigen::Vector3f{config_.boxX, config_.boxY - config_.boxH / 2.0f, wallZ}));
122 backWall_->setGlobalPose(simox::math::pose(
123 Eigen::Vector3f{config_.boxX, config_.boxY + config_.boxH / 2.0f, wallZ}));
124 leftWall_->setGlobalPose(simox::math::pose(
125 Eigen::Vector3f{config_.boxX - config_.boxW / 2.0f, config_.boxY, wallZ}));
126 rightWall_->setGlobalPose(simox::math::pose(
127 Eigen::Vector3f{config_.boxX + config_.boxW / 2.0f, config_.boxY, wallZ}));
128
129 walls_.reset(new VirtualRobot::SceneObjectSet("walls"));
130 walls_->addSceneObject(frontWall_);
131 walls_->addSceneObject(backWall_);
132 walls_->addSceneObject(leftWall_);
133 walls_->addSceneObject(rightWall_);
134 }
135
137 ClutteredSceneGenerator::randomObjectPose(uint heightIndex)
138 {
139 // Object position and angle random distributions
140 boost::uniform_real<float> objectPositionDistX(config_.minObjectX, config_.maxObjectX);
141 boost::uniform_real<float> objectPositionDistY(config_.minObjectY, config_.maxObjectY);
142 boost::uniform_real<float> objectAngleDist(0, 2 * M_PI);
143
144 // Sample random position and rotation around z-axis
145 float x = objectPositionDistX(rnd_);
146 float y = objectPositionDistY(rnd_);
147 float z = config_.minObjectZ + static_cast<float>(heightIndex) * config_.objectSpacingZ;
148 float angle = objectAngleDist(rnd_);
149
150 Eigen::AngleAxisf rotation(angle, Eigen::Vector3f::UnitZ());
151 armarx::PosePtr pose(new Pose(simox::math::pose(Eigen::Vector3f{x, y, z}, rotation)));
152 return pose;
153 }
154
155 void
156 ClutteredSceneGenerator::deleteLocalObjectCopies()
157 {
158 localObjectCopies_.clear();
159 }
160
161 std::unique_ptr<SimulatedObject>
162 ClutteredSceneGenerator::makeObject(const std::string& name, const ObjectSource& objectSource)
163 {
164 switch (objectSource.type)
165 {
166 case AsObject:
167 return std::make_unique<SimulatedObjectAsObject>(name, objectSource);
168 case AsRobot:
169 return std::make_unique<SimulatedObjectAsRobot>(name, objectSource);
170 case Automatic:
171 // TODO(patrick.hegemann): Implement (look up top-level tag in simox xml)
172 ARMARX_INFO << __FUNCTION__ << " Unknown SimulationObjectType: TO DO: Implement";
173 return nullptr;
174 default:
175 ARMARX_ERROR << __FUNCTION__ << " - unknown object type for " << name;
176 return nullptr;
177 }
178 }
179
180 void
181 ClutteredSceneGenerator::updateLocalObjectCopies()
182 {
183 for (const auto& object : localObjectCopies_)
184 {
185 object->updatePoseFromSimulator(simulator_);
186 }
187 }
188
189 void
190 ClutteredSceneGenerator::dropObjects()
191 {
192 simulator_->stop();
193 for (uint k = 0; k < config_.fallingSteps; ++k)
194 {
195 simulator_->step();
196 }
197 simulator_->start();
198 }
199
200 void
201 ClutteredSceneGenerator::resetInvalidObjects()
202 {
203 VirtualRobot::CollisionCheckerPtr col =
204 VirtualRobot::CollisionChecker::getGlobalCollisionChecker();
205 bool anyRespawn = false;
206
207 // Try to reset the objects a number of times, or until all objects are inside the box
208 for (uint i = 0; i < config_.maxResetTries; ++i)
209 {
210 updateLocalObjectCopies();
211
212 // TODO(patrick.hegemann): clean up magic number
213 int heightIndex = 6;
214 anyRespawn = false;
215
216 // Check and reset every object
217 // for (const VirtualRobot::RobotPtr& robot : localObjectCopies_)
218 for (const auto& object : localObjectCopies_)
219 {
220 // Check if object collides with the imaginary walls around the box
221 bool collision = object->checkCollision(col, walls_);
222
223 float z = object->getLocalPose()->position->z;
224 bool isObjectOutsideOfTable = z < config_.minObjectZOtherwiseReset;
225
226 // Respawn object if necessary
227 if (collision || isObjectOutsideOfTable)
228 {
229 anyRespawn = true;
230 object->setLocalPose(randomObjectPose(heightIndex));
231 object->updatePoseToSimulator(simulator_);
232 heightIndex++;
233 }
234 }
235
236 // Let objects fall again if anything has changed
237 if (!anyRespawn)
238 {
239 break;
240 }
241 dropObjects();
242 }
243 }
244
247 {
248 return config_;
249 }
250
251 void
253 {
254 ClutteredSceneGenerator::config_ = conf;
255 }
256
257 const SimulatorInterfacePrx&
259 {
260 return simulator_;
261 }
262
263 void
264 ClutteredSceneGenerator::setSimulator(const SimulatorInterfacePrx& sim)
265 {
266 ClutteredSceneGenerator::simulator_ = sim;
267 }
268} // namespace armarx::simulation::scene_generation
#define M_PI
Definition MathTools.h:17
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition ObjectID.h:11
void setInstanceName(const std::string &instanceName)
Definition ObjectID.h:42
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
Definition ObjectID.cpp:60
ClutteredSceneGenerator(const armarx::SimulatorInterfacePrx &simulator, const Config &config)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
Eigen::Isometry3f Pose
Definition basic_types.h:31
IceInternal::Handle< Pose > PosePtr
Definition Pose.h:306
double angle(const Point &a, const Point &b, const Point &c)
Definition point.hpp:109