SceneProvider.cpp
Go to the documentation of this file.
1#include "SceneProvider.h"
2
3#include <optional>
4#include <utility>
5#include <vector>
6
7#include <VirtualRobot/SceneObjectSet.h> // IWYU pragma: keep
8#include <VirtualRobot/XML/BaseIO.h>
9#include <VirtualRobot/XML/ObjectIO.h>
10#include <VirtualRobot/XML/RobotIO.h>
11
21
27
39
41{
42
44 srv(srv), config(config)
45 {
46 }
47
48 const core::Scene&
50 {
51 return scn;
52 }
53
54 bool
56 {
57 scn.timestamp = timestamp;
58
59 // Only load structure. This includes the primitive models (no mesh files though).
60 scn.robot = srv.virtualRobotReader->getRobotWaiting(
61 config.robotName, timestamp, VirtualRobot::RobotIO::RobotDescription::eStructure);
62 scn.robot->setPrimitiveApproximationModel(config.primitiveApproximationModels);
63
64 ARMARX_CHECK_NOT_NULL(scn.robot);
65
66 scn.staticScene.emplace(getStaticScene(timestamp));
67 scn.dynamicScene.emplace(getDynamicScene(timestamp));
68 scn.graph = getSceneGraph(timestamp);
69
70 return true; // TODO(fabian.reister): return false if sync fails
71 }
72
73 bool
74 SceneProvider::synchronize(const DateTime& timestamp, const bool fullUpdate)
75 {
76 scn.timestamp = timestamp;
77
78 ARMARX_CHECK_NOT_NULL(srv.virtualRobotReader);
79 ARMARX_CHECK(srv.virtualRobotReader->synchronizeRobotPose(*scn.robot, timestamp));
80
81 if (fullUpdate)
82 {
83 scn.staticScene.emplace(getStaticScene(timestamp));
84 }
85
86
87 scn.dynamicScene.emplace(getDynamicScene(timestamp));
88
89 const auto updateAttachedObjects = [this](const std::vector<objpose::ObjectPose*>& objPoses)
90 {
91 for (auto* objPose : objPoses)
92 {
93 objPose->updateAttached(scn.robot);
94 }
95 };
96
97 updateAttachedObjects(scn.dynamicScene->attachedObjects);
98
99 // scn.graph = getSceneGraph(timestamp);
100
101 const auto platformState =
102 srv.virtualRobotReader->queryPlatformState(scn.robot->getName(), timestamp);
103 ARMARX_CHECK(platformState.has_value())
104 << "Could not get a platform state for ts: " << VAROUT(timestamp);
105
106 scn.platformVelocity = core::Twist{.linear = platformState->twist.linear,
107 .angular = platformState->twist.angular};
108
109 return true; // TODO(fabian.reister): return false if sync fails
110 }
111
113 SceneProvider::getStaticScene(const DateTime& timestamp) const
114 {
116
117 ARMARX_VERBOSE << "Getting static scene info";
118
120
121 objpose::ObjectPoseMap objectMap;
122 for (const objpose::ObjectPose& object : objectPoses)
123 {
124 objectMap.emplace(object.objectID, object);
125 }
126
127 std::vector<ObjectInfo> objectInfo = srv.objectPoseClient.objectFinder.findAllObjects();
128
129 // remove those objects that belong to an object dataset. the manipulation object / distance computation is broken
130 auto objectPosesStatic = armarx::objpose::util::filterObjects(
131 objectPoses, {"KIT", "HOPE", "MDB", "YCB", "Kitchen", "Maintenance"});
132
133 ARMARX_VERBOSE << "Static objects:";
134 for (const auto& objectPose : objectPosesStatic)
135 {
136 ARMARX_VERBOSE << "- " << objectPose.objectID;
137 }
138
139 // we maintain a local cache of the objects to avoid having to reload them every iteration
141 objects, objectPosesStatic, VirtualRobot::ObjectIO::eCollisionModel);
142
144 ARMARX_VERBOSE << objects->getSize() << " objects in the scene";
145
146 ARMARX_VERBOSE << "Retrieving costmap in memory";
147
149
150 const algorithms::Costmap costmap = [&]()
151 {
152 Metronome metronome(Frequency::Hertz(10));
153 // waiting for static costmap to become available
154 while (true)
155 {
156 const memory::client::costmap::Reader::Query query{
157 .providerName = config.staticCostmapProviderName,
158 .name = config.staticCostmapName,
159 .timestamp = armarx::Clock::Now()};
160
161
162 if (const memory::client::costmap::Reader::Result costmap =
163 srv.costmapReader->query(query))
164 {
165 ARMARX_CHECK(costmap.costmap.has_value());
166 ARMARX_VERBOSE << "Static costmap available.";
167 return costmap.costmap.value();
168 }
169
170 ARMARX_INFO << deactivateSpam(5) << "Static costmap `" << query.name
171 << "` from provider " << query.providerName << " not available yet.";
172
173 metronome.waitForNextTick();
174 }
175 }();
176
177 const auto costmap3d = [&]() -> std::optional<algorithms::orientation_aware::Costmap3D>
178 {
179 const memory::client::costmap3d::Reader::Query query{.providerName =
180 config.costmap3dProviderName,
181 .name = config.costmap3dName,
182 .timestamp = armarx::Clock::Now()};
183
184
185 if (const memory::client::costmap3d::Reader::Result costmap =
186 srv.costmap3dReader->query(query))
187 {
188 ARMARX_CHECK(costmap.costmap.has_value());
189 ARMARX_VERBOSE << "Static costmap3d available.";
190 return costmap.costmap;
191 }
192
193 ARMARX_INFO << deactivateSpam(5) << "Static costmap3d `" << query.name
194 << "` from provider " << query.providerName << " not available yet.";
195 return std::nullopt;
196 }();
197
198 const auto locations = srv.graphReader->locations();
199
200 ARMARX_INFO << deactivateSpam(5) << "Retrieved static costmap";
201
202 return {.objects = objects,
203 .objectMap = std::move(objectMap),
204 .objectInfo = std::move(objectInfo),
205 .distanceToObstaclesCostmap = costmap,
206 .orientationAwareCostmap = costmap3d,
207 .locations = std::move(locations)};
208 }
209
210 core::DynamicScene
211 SceneProvider::getDynamicScene(const DateTime& timestamp)
212 {
213 const memory::client::human::Reader::Query queryHumans{
214 .providerName = config.humanProviderName,
215 .timestamp = timestamp,
216 .maxAge = Duration::MilliSeconds(500)};
217
218 const memory::client::laser_scanner_features::Reader::Query queryFeatures{
219 .providerName = config.laserScannerFeaturesProviderName,
220 .name = "global",
221 .timestamp = timestamp};
222
223 // add all object that are attached to the root node of the robot
224 std::vector<objpose::ObjectPose*> attachedObjects;
225 const std::string& rootNode = scn.robot->getRootNode()->getName();
226 for (auto& [_, obj] : scn.staticScene->objectMap)
227 {
228 if (obj.attachment.has_value())
229 {
230 if (obj.attachment->frameName == rootNode)
231 {
232 attachedObjects.emplace_back(&obj);
233 }
234 }
235 }
236
237 return {.humans = srv.humanReader->queryHumans(queryHumans).humans,
238 .laserScannerFeatures =
239 srv.laserScannerFeaturesReader->queryData(queryFeatures).features,
240 .attachedObjects = std::move(attachedObjects)};
241 }
242
243 core::SceneGraph
244 SceneProvider::getSceneGraph(const DateTime& /*timestamp*/) const
245 {
246 ARMARX_CHECK_NOT_NULL(srv.graphReader);
247 return {.subgraphs = srv.graphReader->graphs()};
248 }
249
250} // namespace armarx::navigation::server::scene_provider
std::string timestamp()
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
Definition Duration.cpp:48
static Frequency Hertz(std::int64_t hertz)
Definition Frequency.cpp:20
std::vector< ObjectInfo > findAllObjects(bool checkPaths=true) const
Represents a point in time.
Definition DateTime.h:25
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition Metronome.h:57
Result query(const Query &query) const
Definition Reader.cpp:87
bool initialize(const DateTime &timestamp) override
bool synchronize(const DateTime &timestamp, bool fullUpdate) override
SceneProvider(const InjectedServices &srv, const Config &config)
ObjectPoseSeq fetchObjectPoses() const
Fetch all known object poses.
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
VirtualRobot::SceneObjectSetPtr asSceneObjects(const objpose::ObjectPoseSeq &objectPoses, const VirtualRobot::ObjectIO::ObjectDescription loadMode)
Definition util.cpp:147
objpose::ObjectPoseSeq filterObjects(objpose::ObjectPoseSeq objects, const std::vector< std::string > &datasetDisableList)
Definition util.cpp:49
std::map< ObjectID, ObjectPose > ObjectPoseMap
std::vector< ObjectPose > ObjectPoseSeq
An object pose as stored by the ObjectPoseStorage.
Definition ObjectPose.h:34
#define ARMARX_TRACE
Definition trace.h:77