ArMemToImageProvider.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 VisionX::ArmarXObjects::ArMemToImage
17 * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18 * @date 2021
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
26
27#include <algorithm>
28
32
35
36namespace visionx
37{
38
39 std::string
41 {
42 return "ArMemToImageProvider";
43 }
44
45 std::string
50
53 {
56
57 defs->topic(debugObserver);
58
59 defs->optional(
60 p.providerSegmentName, "img.ProviderSegmentName", "Name of the provider segment(s).");
61 defs->optional(p.resultImagesName,
62 "img.ResultImagesName",
63 "Name of the resulting (provided) images.\n"
64 "If '(auto)', the provider segment name is used.");
65
66 defs->defineOptionalPropertyVector(
67 "img.FallbackDimensions",
68 p.fallbackDims,
69 "Image dimensions to use when they cannot be fetched from memory.",
70 'x');
71
72 p.images.define(*defs);
73
74 return defs;
75 }
76
77 void
79 {
80 // Parse properties.
81 getProperty(p.fallbackDims, "img.FallbackDimensions");
82 if (p.resultImagesName == "(auto)")
83 {
84 p.resultImagesName = p.providerSegmentName;
85 }
86 p.images.read(*this, p.providerSegmentName);
87
88 // Setup images.
89 armemToImage.addImagesRGB(p.images.rgbEntityID, p.images.rgbIndices);
90 armemToImage.addImagesDepth(p.images.depthEntityID, p.images.depthIndices);
91 ARMARX_INFO << "Result image structure: \n" << armemToImage.summarizeStructure();
92
93 // Connect to memory updates.
94 auto callback = [this](const armarx::armem::MemoryID& entityID,
95 const std::vector<armarx::armem::MemoryID>& updatedSnapshotIDs)
96 { this->fetchUpdates(entityID, updatedSnapshotIDs); };
97 memoryNameSystem().subscribe(p.images.rgbEntityID, callback);
98 memoryNameSystem().subscribe(p.images.depthEntityID, callback);
99 }
100
101 void
103 {
104 armemToImage.setDebugObserver(debugObserver, getName());
105 {
106 try
107 {
108 armemToImage.memoryReader =
109 memoryNameSystem().useReader(armemToImage.getMemoryID());
110 }
112 {
113 ARMARX_ERROR << e.what();
114 }
115 }
116
117 ARMARX_VERBOSE << "Trying initial fetch ...";
118 Eigen::Vector2i dimensions = p.fallbackDims;
119
120 armemToImage.fetchLatest();
121 if (armemToImage.updated)
122 {
123 dimensions = armemToImage.getImageDimensions();
124 ARMARX_VERBOSE << "Image formats: \n" << armemToImage.printFormats();
125 }
126 // ToDo: We (or the result image provider) could also wait until images are available.
127 enableResultImages(
128 armemToImage.images.size(), {dimensions(0), dimensions(1)}, eRgb, p.resultImagesName);
129 }
130
131 void
133 {
134 if (resultImageProvider)
135 {
136 getArmarXManager()->removeObjectBlocking(resultImageProvider->getName());
137 resultImageProvider = nullptr;
138 }
139 }
140
141 void
145
147 {
148 // Allow calling setName() from outside.
150 virtual ~LocalResultImageProvider() override;
151 };
152
156
157 void
158 ArMemToImageProvider::enableResultImages(size_t numberImages,
159 ImageDimension imageDimension,
160 ImageType imageType,
161 const std::string& name)
162 {
163 if (!resultImageProvider)
164 {
165 ARMARX_VERBOSE << "Enabling ImageProvider with " << numberImages
166 << " result images of size " << imageDimension.width << "x"
167 << imageDimension.height << ".";
168
170 Component::create<LocalResultImageProvider>();
171 provider->setName(name);
172 provider->setNumberResultImages(static_cast<int>(numberImages));
173 provider->setResultImageFormat(imageDimension, imageType);
174
175 try
176 {
177 getArmarXManager()->addObject(provider);
178 }
179 catch (const Ice::AlreadyRegisteredException& e)
180 {
181 ARMARX_ERROR << "The name '" << name
182 << "' is already used. Please choose another one.\n"
183 << "Reason: " << e.what();
184 getArmarXManager()->removeObjectBlocking(name);
185 }
186 provider->getObjectScheduler()->waitForObjectState(
187 armarx::ManagedIceObjectState::eManagedIceObjectStarted);
188
189 // Only now store it in member variable.
190 this->resultImageProvider = provider;
191 }
192 }
193
194 void
195 ArMemToImageProvider::fetchUpdates(
196 const armarx::armem::MemoryID& entityID,
197 const std::vector<armarx::armem::MemoryID>& updatedSnapshotIDs)
198 {
199 std::scoped_lock lock(armemToImageMutex);
200 armemToImage.fetchUpdates(entityID, updatedSnapshotIDs);
201
202 if (resultImageProvider && armemToImage.updated)
203 {
204 std::vector<CByteImage> ivtImages;
205 std::vector<CByteImage*> ivtImagesBuffer;
206 ivtImages.reserve(armemToImage.images.size());
207 ivtImagesBuffer.reserve(armemToImage.images.size());
208 for (auto& image : armemToImage.images)
209 {
210 CByteImage& ivt = ivtImages.emplace_back(image->toCByteImage());
211 ivtImagesBuffer.emplace_back(&ivt);
212 }
213 TIMING_START(Provide);
214 resultImageProvider->provideResultImages(
215 ivtImagesBuffer.data(), armemToImage.timestamp.toMicroSecondsSinceEpoch());
217 armemToImage.updated = false;
218
219 if (debugObserver)
220 {
221 debugObserver->setDebugChannel(
222 getName(),
223 {
224 {"Provide [us]", new armarx::Variant(Provide.toMicroSecondsDouble())},
225 });
226 }
227 }
228 }
229
230
232} // namespace visionx
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
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
Property< PropertyType > getProperty(const std::string &name)
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Reader useReader(const MemoryID &memoryID)
Use a memory server and get a reader for it.
SubscriptionHandle subscribe(const MemoryID &subscriptionID, Callback Callback)
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
Brief description of class ArMemToImageProvider.
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void onConnectComponent() override
Pure virtual hook for the subclass.
void onExitComponent() override
Hook for subclass.
std::string getDefaultName() const override
Retrieve default name of component.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define TIMING_START(name)
Helper macro to do timing tests.
Definition TimeUtil.h:289
#define TIMING_END_STREAM(name, os)
Prints duration.
Definition TimeUtil.h:310
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
ArmarX headers.