WorkingMemoryObjectPoseProvider.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 MemoryX::ArmarXObjects::WorkingMemoryObjectPoseProvider
17 * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18 * @date 2020
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <SimoxUtility/algorithm/string.h>
26#include <SimoxUtility/json.h>
27#include <VirtualRobot/CollisionDetection/CollisionModel.h>
28#include <VirtualRobot/ManipulationObject.h>
29
35
40
43
44void
45memoryx::to_json(nlohmann::json& j, const Config& config)
46{
47 j["objectNames"] = config.objectNames;
48}
49
50void
51memoryx::from_json(const nlohmann::json& j, Config& config)
52{
53 j.at("objectNames").get_to(config.objectNames);
54}
55
56namespace memoryx
57{
58
61 {
64
65 defs->component(workingMemory);
66 defs->component(robotStateComponent);
67 defs->component(priorKnowledge);
68
69 defs->optional(updateFrequency, "UpdateFrequency", "Target number of updates per second.");
70 defs->optional(configFile, "ConfigFile", "Path to the config file.");
71 defs->optional(loadObjectDatasetsStr,
72 "LoadDatasets",
73 "Only load the files for the following datasets, separated by ;. Load all "
74 "if input is empty.");
75
76 return defs;
77 }
78
79 std::string
81 {
82 return "WorkingMemoryObjectPoseProvider";
83 }
84
85 std::string
87 {
88 return "WorkingMemoryObjectPoseProvider";
89 }
90
91 void
93 {
94 configFile = armarx::ArmarXDataPath::resolvePath(configFile);
95 ARMARX_INFO << "Loading config file '" << configFile << "' ...";
96 if (std::filesystem::is_regular_file(configFile))
97 {
98 const nlohmann::json j = nlohmann::read_json(configFile);
99 j.get_to(config);
100 }
101 else
102 {
103 ARMARX_INFO << "No config file at '" << configFile << "'";
104 }
105 }
106
107 void
109 {
110 ARMARX_CHECK_NOT_NULL(workingMemory);
111 ARMARX_CHECK_NOT_NULL(robotStateComponent);
112 ARMARX_CHECK_NOT_NULL(priorKnowledge);
113
114 ARMARX_IMPORTANT << "Loading workingmemory and priorknowledge entites and files. This may "
115 "take a while....";
116 attachments.initFromProxies(workingMemory, robotStateComponent);
117
118 std::vector<std::string> loadDatasets = simox::alg::split(loadObjectDatasetsStr, ";");
119
120 objectClassSegment.initFromProxy(priorKnowledge, loadDatasets);
121 ARMARX_IMPORTANT << "... done loading!";
122
123 // A periodic task logs an important info when the cycle time is not met.
124 // To avoid this, we use a running task.
126 [this]()
127 {
128 armarx::CycleUtil cycle(int(1000 / updateFrequency));
129
130 while (task && !task->isStopped())
131 {
132 provideObjectInstancesPoses();
133 cycle.waitForCycleDuration();
134 }
135 });
136
137 task->start();
138 }
139
140 void
142 {
143 if (task)
144 {
145 task->stop();
146 }
147 }
148
149 void
153
154 void
155 WorkingMemoryObjectPoseProvider::provideObjectInstancesPoses()
156 {
157 std::scoped_lock lock(mutex);
158 std::vector<ObjectInstancePtr> instances = attachments.queryObjects();
159 provideObjectInstancesPoses(instances);
160 }
161
162 void
163 WorkingMemoryObjectPoseProvider::provideObjectInstancesPoses(
164 const std::vector<ObjectInstancePtr>& objectInstances)
165 {
166 armarx::objpose::data::ProvidedObjectPoseSeq objectPoses;
167
168 for (const auto& instance : objectInstances)
169 {
170 objectPoses.push_back(toProvidedObjectPose(instance).toIce());
171 }
172
173 objectPoseTopic->reportObjectPoses(getName(), objectPoses);
174 }
175
176 armarx::objpose::ProvidedObjectPose
177 WorkingMemoryObjectPoseProvider::toProvidedObjectPose(const ObjectInstancePtr& instance)
178 {
179 armarx::objpose::ProvidedObjectPose pose;
180
181 pose.objectType = armarx::objpose::KnownObject;
182 std::string className = instance->getMostProbableClass();
183 if (auto it = config.objectNames.find(className); it != config.objectNames.end())
184 {
185 ARMARX_VERBOSE << deactivateSpam(60) << "Replacing class '" << className << "' by '"
186 << it->second << "'";
187 className = it->second;
188 }
189 pose.objectID = armarx::ObjectID(className);
190 pose.objectID.setInstanceName(instance->getId());
191
192 pose.objectPose = instance->getPose()->toEigen();
193 pose.objectPoseFrame = instance->getPose()->getFrame();
194 if (pose.objectPoseFrame.empty())
195 {
197 }
198
199 pose.confidence = instance->getExistenceCertainty();
200 if (instance->hasLocalizationTimestamp())
201 {
202 fromIce(instance->getLocalizationTimestamp(), pose.timestamp);
203 }
204 else
205 {
207 }
208
209 std::optional<ObjectClassWrapper> objectClass = objectClassSegment.getClass(className);
210 //ARMARX_IMPORTANT << "Looking for class: " << className;
211 if (objectClass)
212 {
213 VirtualRobot::CollisionModelPtr collisionModel =
214 objectClass->manipulationObject->getCollisionModel();
215 VirtualRobot::BoundingBox bb = collisionModel->getBoundingBox(false);
216 Eigen::Vector3f bbMin = bb.getMin();
217 Eigen::Vector3f bbMax = bb.getMax();
218 Eigen::Vector3f extents = bbMax - bbMin;
219 //ARMARX_IMPORTANT << "Bounding box: " << extents.transpose();
220
221 pose.localOOBB = simox::OrientedBoxf(
222 (0.5 * (bbMin + bbMax)).eval(), Eigen::Quaternionf::Identity(), extents);
223 }
224
225 pose.providerName = getName();
226
227 return pose;
228 }
229
230 armarx::objpose::ProviderInfo
232 {
233 armarx::objpose::ProviderInfo info;
234
235 return info;
236 }
237
238 void
240 const AttachObjectToRobotNodeInput& attachment,
241 const Ice::Current&)
242 {
243 std::scoped_lock lock(mutex);
244 attachments.attachObjectToRobotNode(attachment);
245 }
246
247 void
249 const DetachObjectFromRobotNodeInput& detachment,
250 const Ice::Current&)
251 {
252 std::scoped_lock lock(mutex);
253 attachments.detachObjectFromRobotNode(detachment);
254 }
255
256} // namespace memoryx
257
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
static std::string resolvePath(const std::string &path, bool verbose=true)
Resolves environment variables and home paths and tries to make path absolute.
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
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
IceUtil::Time waitForCycleDuration()
This function will wait (virtual or system time) until the cycle time is reached.
Definition CycleUtil.cpp:53
static DateTime Now()
Definition DateTime.cpp:51
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition Logging.cpp:99
std::string getName() const
Retrieve name of object.
void setInstanceName(const std::string &instanceName)
Definition ObjectID.h:42
objpose::ObjectPoseStorageInterfacePrx objectPoseTopic
float confidence
Confidence in [0, 1] (1 = full, 0 = none).
armarx::ObjectID objectID
The object ID, i.e. dataset, class name and instance name.
std::string providerName
Name of the providing component.
DateTime timestamp
Source timestamp.
ObjectType objectType
Known or unknown object.
std::optional< simox::OrientedBoxf > localOOBB
Object bounding box in object's local coordinate frame.
std::vector< ObjectInstancePtr > queryObjects()
Get all entities from objectInstanceSegment and cast them to ObjectInstance.
Brief description of class WorkingMemoryObjectPoseProvider.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void attachObjectToRobotNode(const AttachObjectToRobotNodeInput &attachment, const Ice::Current &) override
void detachObjectFromRobotNode(const DetachObjectFromRobotNodeInput &detachment, const Ice::Current &) override
armarx::objpose::ProviderInfo getProviderInfo(const Ice::Current &=Ice::emptyCurrent) override
#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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
void fromIce(Eigen::Vector2f &e, const Ice::FloatSeq &ice)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
SimpleRunningTask(Ts...) -> SimpleRunningTask< std::function< void(void)> >
VirtualRobot headers.
void from_json(const nlohmann::json &j, Config &config)
IceInternal::Handle< ObjectInstance > ObjectInstancePtr
void to_json(nlohmann::json &j, const Config &config)
std::map< std::string, std::string > objectNames