FakeObjectDetector.h
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::components::FakeObjectDetector
17 * @author Timo Birr ( timo dot birr at kit dot edu )
18 * @date 2026
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <map>
26#include <mutex>
27#include <optional>
28#include <set>
29#include <string>
30#include <vector>
31
32#include <SimoxUtility/shapes/OrientedBox.h>
33#include <VirtualRobot/VirtualRobot.h>
34
38
42
44#include <ArmarXSimulation/interface/simulator/SimulatorInterface.h>
45
46namespace armarx
47{
48
49 /**
50 * @brief A fake object detector for simulation.
51 *
52 * Takes ground truth object poses from the simulator, but - unlike
53 * `SimulationObjectPoseProvider` - only reports an object once the robot could plausibly
54 * have perceived it:
55 *
56 * - `Always` : report everything (parity with `SimulationObjectPoseProvider`).
57 * - `FieldOfView` : report an object once its bounding box enters the camera frustum.
58 * - `LineOfSight` : additionally require a clear line of sight to the front facing side
59 * of the object's bounding box, tested against the other objects in the
60 * scene and the robot's own body.
61 *
62 * Detected objects are published on the standard object pose topic, so consumers keep
63 * reading the `Object/Instance` memory segment as usual.
64 *
65 * Objects that leave the view are simply no longer reported. They fade out through the
66 * object memory's decay mechanism, which must be enabled for that to happen:
67 * @code
68 * ArmarX.ObjectMemory.mem.inst.decay.enabled = 1
69 * @endcode
70 */
72 virtual public armarx::Component,
74 {
75 public:
76 /// @see armarx::ManagedIceObject::getDefaultName()
77 std::string getDefaultName() const override;
78
79 /// Get the component's default name.
80 static std::string GetDefaultName();
81
82 // ObjectPoseProvider interface
83 public:
84 objpose::provider::RequestObjectsOutput
85 requestObjects(const objpose::provider::RequestObjectsInput& input,
86 const Ice::Current& /* unused */) override;
87
88 objpose::ProviderInfo getProviderInfo(const Ice::Current& /* unused */) override;
89
90 protected:
91 /// @see PropertyUser::createPropertyDefinitions()
93
94 /// @see armarx::ManagedIceObject::onInitComponent()
95 void onInitComponent() override;
96
97 /// @see armarx::ManagedIceObject::onConnectComponent()
98 void onConnectComponent() override;
99
100 /// @see armarx::ManagedIceObject::onDisconnectComponent()
101 void onDisconnectComponent() override;
102
103 /// @see armarx::ManagedIceObject::onExitComponent()
104 void onExitComponent() override;
105
106 private:
107 /// An object of the simulated scene, prepared for the visibility checks.
108 struct SceneObject
109 {
110 armarx::ObjectID objectID;
111 Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
112 /// In the object's local frame; `std::nullopt` if it had to be guessed.
113 std::optional<simox::OrientedBoxf> localOOBB;
115 /// Part of the static scene: reported without a visibility check.
116 bool alwaysVisible = false;
117 };
118
119 void detectionTaskRun();
120
121 /// Run one detection cycle and publish the result.
122 void detectAndReport();
123
124 /// The robot to take the camera pose from, or `nullptr` if it is not in the scene.
125 const armarx::RobotVisuData* findRobot(const armarx::SceneVisuData& sceneData) const;
126
127 /// Convert the simulated objects into boxes, skipping ignored ones.
128 std::vector<SceneObject> collectSceneObjects(const armarx::SceneVisuData& sceneData);
129
130 /**
131 * The object's bounding box in its local frame.
132 *
133 * Looks the OOBB up via `ObjectFinder` and caches it per object class. Falls back to a
134 * cube of `properties.fallbackOobbSize` when the object has no bounding box on disk.
135 */
136 std::optional<simox::OrientedBoxf> getLocalOOBB(const armarx::ObjectID& objectID);
137
138 /// The camera frustum for the configured camera node, if that node exists.
139 std::optional<fake_object_detector::Frustum>
140 buildFrustum(const armarx::RobotVisuData& robot) const;
141
142 /// Bounding boxes of the robot's links, in the global frame.
143 std::vector<fake_object_detector::Box>
144 collectRobotBoxes(const armarx::RobotVisuData& robotData);
145
146 /// Load the robot model once, with collision models, so it can act as an occluder.
147 VirtualRobot::RobotPtr loadRobotModel(const armarx::RobotVisuData& robotData);
148
149 bool isVisible(const SceneObject& object,
150 const fake_object_detector::Frustum& frustum,
151 const std::vector<fake_object_detector::Box>& occluders) const;
152
153 objpose::ProvidedObjectPose toProvidedObjectPose(const SceneObject& object,
154 const DateTime& time) const;
155
156 void removeExpiredRequests(const DateTime& time);
157 bool isRequested(const armarx::ObjectID& objectID) const;
158
159 private:
160 static const std::string defaultName;
161
162 SimulatorInterfacePrx simulatorPrx;
163
165
166 armarx::ObjectFinder objectFinder;
167 /// Cached OOBBs, keyed by class ID (`dataset/className`).
168 std::map<std::string, std::optional<simox::OrientedBoxf>> oobbCache;
169
170 /// Lazily loaded robot model used for self-occlusion, keyed by robot name.
171 VirtualRobot::RobotPtr robotModel;
172 std::string robotModelName;
173 bool robotModelLoadFailed = false;
174
175 mutable std::mutex activeRequestsMutex;
176 /// Requested object IDs and when the request expires (invalid time = never).
177 std::map<std::string, armarx::DateTime> activeRequests;
178
179 /// Object IDs whose bounding box could not be found; used to warn only once.
180 std::set<std::string> warnedMissingOOBB;
181 bool warnedMissingCameraNode = false;
182
183 /// Parsed from `properties.alwaysVisibleDatasets`.
184 std::set<std::string> alwaysVisibleDatasets;
185
186 struct Properties
187 {
188 std::int64_t updateFrequency = 10;
189
190 std::string detectionMode = "FieldOfView";
193
194 std::string robotName;
195 std::string cameraFrame = "DepthCameraSim";
196
197 float horizontalFovDeg = 90.0F;
198 float verticalFovDeg = 60.0F;
199 float minDistance = 20.0F;
200 float maxDistance = 5000.0F;
201 std::string cameraForwardAxis = "+Z";
202 // ArmarX rendering ('...Sim') camera nodes follow the Coin3D convention: looking
203 // along +Z with +X pointing up (see VirtualRobot CoinVisualizationFactory).
204 std::string cameraUpAxis = "+X";
205 bool requireFullyInFov = false;
206
207 int frontFaceSampleGrid = 3;
208 float minVisibleFraction = 0.5F;
209 bool occlusionByObjects = true;
210 bool occlusionByRobot = true;
211 float rayEpsilon = 1.0F;
212
213 float fallbackOobbSize = 100.0F;
214 float confidence = 1.0F;
215 std::string ignoredObjects;
216 std::string alwaysVisibleDatasets;
217 bool requestedObjectsOnly = false;
218 };
219
220 Properties properties;
221
222 /// Parsed from `properties.ignoredObjects`.
223 std::set<std::string> ignoredObjects;
224
225 /// Parsed from `properties.cameraForwardAxis` / `cameraUpAxis`.
226 Eigen::Vector3f cameraForwardLocal = Eigen::Vector3f::UnitZ();
227 Eigen::Vector3f cameraUpLocal = -Eigen::Vector3f::UnitY();
228 };
229
230} // namespace armarx
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition Component.h:94
A fake object detector for simulation.
objpose::ProviderInfo getProviderInfo(const Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
static std::string GetDefaultName()
Get the component's default name.
objpose::provider::RequestObjectsOutput requestObjects(const objpose::provider::RequestObjectsInput &input, const Ice::Current &) override
std::string getDefaultName() const override
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition ObjectID.h:11
Provides an objpose::ObjectPoseTopicPrx objectPoseTopic as member variable.
IceUtil::Handle< RunningTask< T > > pointer_type
Shared pointer type for convenience.
Represents a point in time.
Definition DateTime.h:25
An object pose provided by an ObjectPoseProvider.
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
DetectionMode
How strictly an object must be perceivable before it is reported.
@ FieldOfView
Report an object once its bounding box enters the camera frustum.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
An oriented bounding box in the global frame.