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{
52
54 {
55 addPlugin(familiarObjectInstanceReaderPlugin);
56
57 p.exemplaryFamiliarObjectID.dataset = "myDataset";
58 p.exemplaryFamiliarObjectID.className = "sphere";
59 p.exemplaryFamiliarObjectID.instanceName = "0";
60
61 p.knownObjectID.dataset = "myDataset";
62 p.knownObjectID.className = "sphere";
63 p.knownObjectID.instanceName = "0";
64 }
65
68 {
71
72 defs->required(p.robotName, "p.robotName");
73
74 defs->optional(p.exemplaryFamiliarObjectID.dataset, "p.objectId.dataset");
75 defs->optional(p.exemplaryFamiliarObjectID.className, "p.objectId.className");
76 defs->optional(p.exemplaryFamiliarObjectID.instanceName, "p.objectId.instanceName");
77
78 defs->optional(p.knownObjectID.dataset, "p.knownObjectID.dataset");
79 defs->optional(p.knownObjectID.className, "p.knownObjectID.className");
80 defs->optional(p.knownObjectID.instanceName, "p.knownObjectID.instanceName");
81
82 defs->optional(p.knownObjectAsFamID.dataset, "p.knownObjectAsFamID.dataset");
83 defs->optional(p.knownObjectAsFamID.className, "p.knownObjectAsFamID.className");
84 defs->optional(p.knownObjectAsFamID.instanceName, "p.knownObjectAsFamID.instanceName");
85
86 defs->optional(p.objectShiftX, "p.objectShiftX", "");
87 defs->optional(p.objectShiftY, "p.objectShiftY", "");
88 defs->optional(p.nFamObjects, "p.nFamObjects", "Number of familiar objects to create");
89
90 defs->component(familiarObjectPoseStoragePrx, "ObjectMemory");
91
92 return defs;
93 }
94
95 std::string
97 {
98 return "FamiliarObjectDetectionExample";
99 }
100
101 void
105
106 void
108 {
109 //
110 // First, we create a familiar object and send it to the memory.
111 //
112
113 ARMARX_IMPORTANT << "Storing exemplary familiar object in memory";
115
116 //
117 // Then, we read the familiar object from the memory.
118 //
119 ARMARX_IMPORTANT << "Reading familiar object from memory";
121
122 ARMARX_IMPORTANT << "Storing known object as familiar object in memory";
124 }
125
126 void
128 {
129 detectTask =
132 1'000); // every 5 seconds
133
134 detectTask->start();
135 }
136
137 void
139 {
140 const auto client = getClient();
141
142 armarx::ObjectID knownObjectID;
143 fromAron(p.knownObjectID, knownObjectID);
144 const auto knownObjectPose = client.fetchObjectPose(knownObjectID);
145
146 ARMARX_CHECK(knownObjectPose.has_value())
147 << "Known object " << QUOTED(knownObjectID) << " not found in ObjectMemory.";
148
149 ObjectFinder finder;
150 auto manipulationObject = finder.loadManipulationObject(knownObjectPose.value());
151 ARMARX_CHECK_NOT_NULL(manipulationObject)
152 << "Could not load ManipulationObject for known object " << QUOTED(knownObjectID.str())
153 << ".";
154
155 manipulationObject->setGlobalPose(knownObjectPose->objectPoseGlobal);
156
157 ObjectID famObjectID;
158 fromAron(p.knownObjectAsFamID, famObjectID);
159
160 const auto familiarObject =
162 famObjectID);
163
164 ::armarx::objpose::ProvidedFamiliarObjectPoseSeq data;
165
166 for (unsigned int i = 0; i < p.nFamObjects; i++)
167 {
168 auto famObj = familiarObject;
169 famObj.objectID.instanceName = std::to_string(i);
170
171 // shift each object by 50mm in x direction
172 famObj.poseGlobal->pose.block(0, 3, 3, 1) +=
173 Eigen::Vector3f(static_cast<float>(i) * p.objectShiftX, static_cast<float>(i) * p.objectShiftY, 0.0f);
174
175 data.push_back(famObj.toAronDTO());
176 }
177
178 // data.push_back(familiarObject.toAronDTO());
179
180 ARMARX_INFO << "Sending " << data.size() << " familiar object(s) to the memory";
181 familiarObjectPoseStoragePrx->reportFamiliarObjectPoses(getName(), data);
182 }
183
184 void
186 {
187 armem::arondto::FamiliarObjectInstance familiarObject;
188
189 familiarObject.timestamp = armarx::Clock::Now();
190
191 familiarObject.poseSensFrame.pose =
192 Eigen::Isometry3f{Eigen::Translation3f{0, 0, 1000}}.matrix();
193 familiarObject.poseSensFrame.header.frame = "DepthCameraSim";
194 familiarObject.poseSensFrame.header.agent = p.robotName;
195 // familiarObject.poseSensFrame.header.frame = "AzureKinect_RGB";
196
197
198 familiarObject.objectID = p.exemplaryFamiliarObjectID;
199
200 familiarObject.confidence = 1.0;
201
202 // familiarObject.bounding_box =
203
204 // familiarObject.depth_image_patch = cv::Mat1f(cv::Size(20, 20));
205 // familiarObject.rgb_image_patch = cv::Mat3b(cv::Size(20, 20));
206
207 const unsigned int numPoints = 100;
208
209 // x in red
210 for (unsigned int i = 0; i < numPoints; i++)
211 {
212 pcl::PointXYZRGBA point;
213 point.x = static_cast<float>(i) - numPoints / 2;
214 point.y = 0;
215 point.z = 0;
216 point.r = 255;
217 point.g = 0;
218 point.b = 0;
219 familiarObject.points.points.push_back(point);
220 }
221
222 // y in green
223 for (unsigned int i = 0; i < numPoints; i++)
224 {
225 pcl::PointXYZRGBA point;
226 point.x = 0;
227 point.y = static_cast<float>(i) - numPoints / 2;
228 point.z = 0;
229 point.r = 0;
230 point.g = 255;
231 point.b = 0;
232 familiarObject.points.points.push_back(point);
233 }
234
235 // z in blue
236 for (unsigned int i = 0; i < numPoints; i++)
237 {
238 pcl::PointXYZRGBA point;
239 point.y = 0;
240 point.y = 0;
241 point.z = static_cast<float>(i) - numPoints / 2;
242 point.r = 0;
243 point.g = 0;
244 point.b = 255;
245 familiarObject.points.points.push_back(point);
246 }
247
248 familiarObject.points.header.frame_id = "DepthCameraSim";
249 familiarObject.points.is_dense = true;
250 familiarObject.points.width = familiarObject.points.points.size();
251 familiarObject.points.height = 1;
252
253 familiarObject.bounding_box.center.setZero();
254 familiarObject.bounding_box.extents.setConstant(numPoints);
255
256 ::armarx::objpose::ProvidedFamiliarObjectPoseSeq data;
257 data.push_back(familiarObject.toAronDTO());
258
259 ARMARX_INFO << "Sending " << data.size() << " familiar object to the memory";
260 familiarObjectPoseStoragePrx->reportFamiliarObjectPoses(getName(), data);
261 }
262
263 void
265 {
266 ARMARX_CHECK_NOT_NULL(familiarObjectInstanceReaderPlugin);
267
268 const armem::obj::familiar_object_instance::Reader& familiarObjectInstanceReader =
269 familiarObjectInstanceReaderPlugin->get();
270
271
272 //
273 // 1. Read from all providers
274 //
275 ARMARX_IMPORTANT << "Reading from all providers";
276 {
277
278 const auto allFamiliarObjectInstances =
279 familiarObjectInstanceReader.queryAllLatestFamiliarObjectInstances();
280
281 // print
282 for (const auto& [providerName, instances] : allFamiliarObjectInstances)
283 {
284 ARMARX_INFO << "Provider name: " << providerName;
285 for (const auto& instance : instances)
286 {
287 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
288 << instance.objectID.className << "/"
289 << instance.objectID.instanceName;
290 }
291 }
292 }
293
294 //
295 // 2. Read from a specific provider
296 //
297 ARMARX_IMPORTANT << "Reading from a specific provider";
298 {
299 const std::map<std::string, std::vector<armem::arondto::FamiliarObjectInstance>>
300 familiarObjectInstances =
301 familiarObjectInstanceReader.queryAllLatestFamiliarObjectInstances(getName());
302
303 ARMARX_INFO << "Provider name: " << getName();
304
305 ARMARX_CHECK_EQUAL(familiarObjectInstances.size(), 1);
306 ARMARX_CHECK_EQUAL(familiarObjectInstances.begin()->first, getName());
307
308 const auto& thisFamiliarObjectInstances = familiarObjectInstances.begin()->second;
309 // print
310 for (const auto& instance : thisFamiliarObjectInstances)
311 {
312 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
313 << instance.objectID.className << "/" << instance.objectID.instanceName;
314 }
315 }
316
317 //
318 // 3. Read all instances of a specific class
319 //
320 ARMARX_IMPORTANT << "Reading all instances of a specific class";
321 {
322 armarx::ObjectID objectId;
323 fromAron(p.exemplaryFamiliarObjectID, objectId);
324
325 const auto instances =
326 familiarObjectInstanceReader.queryLatestFamiliarObjectInstancesFromClass(
327 objectId.getClassID());
328
329 for (const auto& [instanceName, instancesForProvider] : instances)
330 {
331 for (const auto& instance : instancesForProvider)
332 {
333 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
334 << instance.objectID.className << "/"
335 << instance.objectID.instanceName;
336 }
337 }
338 }
339
340 //
341 // 4. Read a specific instance
342 //
343 ARMARX_IMPORTANT << "Reading a specific instance";
344 {
345 armarx::ObjectID objectId;
346 fromAron(p.exemplaryFamiliarObjectID, objectId);
347
348 const std::optional<std::map<std::string, armem::arondto::FamiliarObjectInstance>>
349 instances =
350 familiarObjectInstanceReader.queryLatestFamiliarObjectInstance(objectId);
351
352 ARMARX_CHECK(instances.has_value());
353
354 for (const auto& [instanceName, instance] : instances.value())
355 {
356 ARMARX_INFO << "- Instance: " << instance.objectID.dataset << "/"
357 << instance.objectID.className << "/" << instance.objectID.instanceName;
358 }
359 }
360 }
361
362 void
364 {
365 if (detectTask)
366 {
367 detectTask->stop();
368 detectTask = nullptr;
369 }
370 }
371
372 void
376
377
378} // namespace armarx::familiar_objects
#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.