FamiliarObjectDetectionExample.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 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @date 2024
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
23
24#include <map>
25#include <optional>
26#include <string>
27#include <vector>
28
29#include <Eigen/Geometry>
30
31#include <pcl/point_types.h>
32#include <VirtualRobot/ManipulationObject.h>
33
41
47#include <RobotAPI/interface/objectpose/FamiliarObjectPoseStorageInterface.h>
48#include <RobotAPI/libraries/armem_objects/aron/FamiliarObjectInstance.aron.generated.h>
49
51
53{
54
56 {
57 addPlugin(familiarObjectInstanceReaderPlugin);
58
59 p.exemplaryFamiliarObjectID.dataset = "myDataset";
60 p.exemplaryFamiliarObjectID.className = "sphere";
61 p.exemplaryFamiliarObjectID.instanceName = "0";
62
63 p.knownObjectID.dataset = "myDataset";
64 p.knownObjectID.className = "sphere";
65 p.knownObjectID.instanceName = "0";
66 }
67
70 {
73
74 defs->required(p.robotName, "p.robotName");
75
76 defs->optional(p.exemplaryFamiliarObjectID.dataset, "p.objectId.dataset");
77 defs->optional(p.exemplaryFamiliarObjectID.className, "p.objectId.className");
78 defs->optional(p.exemplaryFamiliarObjectID.instanceName, "p.objectId.instanceName");
79
80 defs->optional(p.knownObjectID.dataset, "p.knownObjectID.dataset");
81 defs->optional(p.knownObjectID.className, "p.knownObjectID.className");
82 defs->optional(p.knownObjectID.instanceName, "p.knownObjectID.instanceName");
83
84 defs->optional(p.knownObjectAsFamID.dataset, "p.knownObjectAsFamID.dataset");
85 defs->optional(p.knownObjectAsFamID.className, "p.knownObjectAsFamID.className");
86 defs->optional(p.knownObjectAsFamID.instanceName, "p.knownObjectAsFamID.instanceName");
87
88 defs->optional(p.objectShiftX, "p.objectShiftX", "");
89 defs->optional(p.objectShiftY, "p.objectShiftY", "");
90 defs->optional(p.nFamObjects, "p.nFamObjects", "Number of familiar objects to create");
91
92 defs->component(familiarObjectPoseStoragePrx, "ObjectMemory");
93
94 return defs;
95 }
96
97 std::string
99 {
100 return "FamiliarObjectDetectionExample";
101 }
102
103 void
107
108 void
110 {
111 //
112 // First, we create a familiar object and send it to the memory.
113 //
114
115 ARMARX_IMPORTANT << "Storing exemplary familiar object in memory";
117
118 //
119 // Then, we read the familiar object from the memory.
120 //
121 ARMARX_IMPORTANT << "Reading familiar object from memory";
123
124 ARMARX_IMPORTANT << "Storing known object as familiar object in memory";
126 }
127
128 void
130 {
131 detectTask =
134 1'000); // every 5 seconds
135
136 detectTask->start();
137 }
138
139 void
141 {
142 const auto client = getClient();
143
144 armarx::ObjectID knownObjectID;
145 fromAron(p.knownObjectID, knownObjectID);
146 const auto knownObjectPose = client.fetchObjectPose(knownObjectID);
147
148 ARMARX_CHECK(knownObjectPose.has_value())
149 << "Known object " << QUOTED(knownObjectID) << " not found in ObjectMemory.";
150
151 ObjectFinder finder;
152 auto manipulationObject = finder.loadManipulationObject(knownObjectPose.value());
153 ARMARX_CHECK_NOT_NULL(manipulationObject)
154 << "Could not load ManipulationObject for known object " << QUOTED(knownObjectID.str())
155 << ".";
156
157 manipulationObject->setGlobalPose(knownObjectPose->objectPoseGlobal);
158
159 ObjectID famObjectID;
160 fromAron(p.knownObjectAsFamID, famObjectID);
161
162 const auto familiarObject =
164 famObjectID);
165
166 ::armarx::objpose::ProvidedFamiliarObjectPoseSeq data;
167
168 for (unsigned int i = 0; i < p.nFamObjects; i++)
169 {
170 auto famObj = familiarObject;
171 famObj.objectID.instanceName = std::to_string(i);
172
173 // shift each object by 50mm in x direction
174 famObj.poseGlobal->pose.block(0, 3, 3, 1) +=
175 Eigen::Vector3f(static_cast<float>(i) * p.objectShiftX, static_cast<float>(i) * p.objectShiftY, 0.0f);
176
177 data.push_back(famObj.toAronDTO());
178 }
179
180 // data.push_back(familiarObject.toAronDTO());
181
182 ARMARX_INFO << "Sending " << data.size() << " familiar object(s) to the memory";
183 familiarObjectPoseStoragePrx->reportFamiliarObjectPoses(getName(), data);
184 }
185
186 void
188 {
189 armem::arondto::FamiliarObjectInstance familiarObject;
190
191 familiarObject.timestamp = armarx::Clock::Now();
192
193 familiarObject.poseSensFrame.pose =
194 Eigen::Isometry3f{Eigen::Translation3f{0, 0, 1000}}.matrix();
195 familiarObject.poseSensFrame.header.frame = "DepthCameraSim";
196 familiarObject.poseSensFrame.header.agent = p.robotName;
197 // familiarObject.poseSensFrame.header.frame = "AzureKinect_RGB";
198
199
200 familiarObject.objectID = p.exemplaryFamiliarObjectID;
201
202 familiarObject.confidence = 1.0;
203
204 // familiarObject.bounding_box =
205
206 // familiarObject.depth_image_patch = cv::Mat1f(cv::Size(20, 20));
207 // familiarObject.rgb_image_patch = cv::Mat3b(cv::Size(20, 20));
208
209 const unsigned int numPoints = 100;
210
211 // x in red
212 for (unsigned int i = 0; i < numPoints; i++)
213 {
214 pcl::PointXYZRGBA point;
215 point.x = static_cast<float>(i) - numPoints / 2;
216 point.y = 0;
217 point.z = 0;
218 point.r = 255;
219 point.g = 0;
220 point.b = 0;
221 familiarObject.points.points.push_back(point);
222 }
223
224 // y in green
225 for (unsigned int i = 0; i < numPoints; i++)
226 {
227 pcl::PointXYZRGBA point;
228 point.x = 0;
229 point.y = static_cast<float>(i) - numPoints / 2;
230 point.z = 0;
231 point.r = 0;
232 point.g = 255;
233 point.b = 0;
234 familiarObject.points.points.push_back(point);
235 }
236
237 // z in blue
238 for (unsigned int i = 0; i < numPoints; i++)
239 {
240 pcl::PointXYZRGBA point;
241 point.y = 0;
242 point.y = 0;
243 point.z = static_cast<float>(i) - numPoints / 2;
244 point.r = 0;
245 point.g = 0;
246 point.b = 255;
247 familiarObject.points.points.push_back(point);
248 }
249
250 familiarObject.points.header.frame_id = "DepthCameraSim";
251 familiarObject.points.is_dense = true;
252 familiarObject.points.width = familiarObject.points.points.size();
253 familiarObject.points.height = 1;
254
255 familiarObject.bounding_box.center.setZero();
256 familiarObject.bounding_box.extents.setConstant(numPoints);
257
258 ::armarx::objpose::ProvidedFamiliarObjectPoseSeq data;
259 data.push_back(familiarObject.toAronDTO());
260
261 ARMARX_INFO << "Sending " << data.size() << " familiar object to the memory";
262 familiarObjectPoseStoragePrx->reportFamiliarObjectPoses(getName(), data);
263 }
264
265 void
267 {
268 ARMARX_CHECK_NOT_NULL(familiarObjectInstanceReaderPlugin);
269
270 const armem::obj::familiar_object_instance::Reader& familiarObjectInstanceReader =
271 familiarObjectInstanceReaderPlugin->get();
272
273
274 //
275 // 1. Read from all providers
276 //
277 ARMARX_IMPORTANT << "Reading from all providers";
278 {
279
280 const auto allFamiliarObjectInstances =
281 familiarObjectInstanceReader.queryAllLatestFamiliarObjectInstances();
282
283 // print
284 for (const auto& [providerName, instances] : allFamiliarObjectInstances)
285 {
286 ARMARX_INFO << "Provider name: " << providerName;
287 for (const auto& instance : instances)
288 {
289 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
290 << instance.objectID.className << "/"
291 << instance.objectID.instanceName;
292 }
293 }
294 }
295
296 //
297 // 2. Read from a specific provider
298 //
299 ARMARX_IMPORTANT << "Reading from a specific provider";
300 {
301 const std::map<std::string, std::vector<armem::arondto::FamiliarObjectInstance>>
302 familiarObjectInstances =
303 familiarObjectInstanceReader.queryAllLatestFamiliarObjectInstances(getName());
304
305 ARMARX_INFO << "Provider name: " << getName();
306
307 ARMARX_CHECK_EQUAL(familiarObjectInstances.size(), 1);
308 ARMARX_CHECK_EQUAL(familiarObjectInstances.begin()->first, getName());
309
310 const auto& thisFamiliarObjectInstances = familiarObjectInstances.begin()->second;
311 // print
312 for (const auto& instance : thisFamiliarObjectInstances)
313 {
314 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
315 << instance.objectID.className << "/" << instance.objectID.instanceName;
316 }
317 }
318
319 //
320 // 3. Read all instances of a specific class
321 //
322 ARMARX_IMPORTANT << "Reading all instances of a specific class";
323 {
324 armarx::ObjectID objectId;
325 fromAron(p.exemplaryFamiliarObjectID, objectId);
326
327 const auto instances =
328 familiarObjectInstanceReader.queryLatestFamiliarObjectInstancesFromClass(
329 objectId.getClassID());
330
331 for (const auto& [instanceName, instancesForProvider] : instances)
332 {
333 for (const auto& instance : instancesForProvider)
334 {
335 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
336 << instance.objectID.className << "/"
337 << instance.objectID.instanceName;
338 }
339 }
340 }
341
342 //
343 // 4. Read a specific instance
344 //
345 ARMARX_IMPORTANT << "Reading a specific instance";
346 {
347 armarx::ObjectID objectId;
348 fromAron(p.exemplaryFamiliarObjectID, objectId);
349
350 const std::optional<std::map<std::string, armem::arondto::FamiliarObjectInstance>>
351 instances =
352 familiarObjectInstanceReader.queryLatestFamiliarObjectInstance(objectId);
353
354 ARMARX_CHECK(instances.has_value());
355
356 for (const auto& [instanceName, instance] : instances.value())
357 {
358 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
359 << instance.objectID.className << "/" << instance.objectID.instanceName;
360 }
361 }
362 }
363
364 void
366 {
367 if (detectTask)
368 {
369 detectTask->stop();
370 detectTask = nullptr;
371 }
372 }
373
374 void
378
380 "FamiliarObjectDetectionExample");
381} // namespace armarx::familiar_objects
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
#define QUOTED(x)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
Default component property definition container.
Definition Component.h:70
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
std::string getName() const
Retrieve name of object.
Used to find objects in the ArmarX objects repository [1] (formerly [2]).
static VirtualRobot::ManipulationObjectPtr loadManipulationObject(const std::optional< ObjectInfo > &ts, VirtualRobot::ObjectIO::ObjectDescription loadMode=VirtualRobot::ObjectIO::ObjectDescription::eFull)
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
Definition ObjectID.h:11
ObjectID getClassID() const
Return just the class ID without an intance name.
Definition ObjectID.cpp:71
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
Definition ObjectID.cpp:60
objpose::ObjectPoseClient getClient() const
The periodic task executes one thread method repeatedly using the time period specified in the constr...
std::map< std::string, std::vector< arondto::FamiliarObjectInstance > > queryLatestFamiliarObjectInstancesFromClass(const ObjectID &classId, const std::optional< std::string > &providerName=std::nullopt) const
std::optional< std::map< std::string, arondto::FamiliarObjectInstance > > queryLatestFamiliarObjectInstance(const ObjectID &instanceId, const std::optional< std::string > &providerName=std::nullopt) const
std::map< std::string, std::vector< arondto::FamiliarObjectInstance > > queryAllLatestFamiliarObjectInstances(const std::optional< std::string > &providerName=std::nullopt) const
void onInitComponent() override
Pure virtual hook for the subclass.
void onConnectComponent() override
Pure virtual hook for the subclass.
#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_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
armarx::armem::arondto::FamiliarObjectInstance createFamiliarObjectInstanceFromManipulationObject(const VirtualRobot::ManipulationObject &manipulationObject, const armarx::ObjectID &objectID)
createFamiliarObjectInstanceFromManipulationObject Create a FamiliarObjectInstance from a known Manip...
Definition utils.cpp:115
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.