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
25#include <algorithm>
26
30
33
34namespace visionx
35{
36
37 std::string
39 {
40 return "ArMemToImageProvider";
41 }
42
45 {
48
49 defs->topic(debugObserver);
50
51 defs->optional(
52 p.providerSegmentName, "img.ProviderSegmentName", "Name of the provider segment(s).");
53 defs->optional(p.resultImagesName,
54 "img.ResultImagesName",
55 "Name of the resulting (provided) images.\n"
56 "If '(auto)', the provider segment name is used.");
57
58 defs->defineOptionalPropertyVector(
59 "img.FallbackDimensions",
60 p.fallbackDims,
61 "Image dimensions to use when they cannot be fetched from memory.",
62 'x');
63
64 p.images.define(*defs);
65
66 return defs;
67 }
68
69 void
71 {
72 // Parse properties.
73 getProperty(p.fallbackDims, "img.FallbackDimensions");
74 if (p.resultImagesName == "(auto)")
75 {
76 p.resultImagesName = p.providerSegmentName;
77 }
78 p.images.read(*this, p.providerSegmentName);
79
80 // Setup images.
81 armemToImage.addImagesRGB(p.images.rgbEntityID, p.images.rgbIndices);
82 armemToImage.addImagesDepth(p.images.depthEntityID, p.images.depthIndices);
83 ARMARX_INFO << "Result image structure: \n" << armemToImage.summarizeStructure();
84
85 // Connect to memory updates.
86 auto callback = [this](const armarx::armem::MemoryID& entityID,
87 const std::vector<armarx::armem::MemoryID>& updatedSnapshotIDs)
88 { this->fetchUpdates(entityID, updatedSnapshotIDs); };
89 memoryNameSystem().subscribe(p.images.rgbEntityID, callback);
90 memoryNameSystem().subscribe(p.images.depthEntityID, callback);
91 }
92
93 void
95 {
96 armemToImage.setDebugObserver(debugObserver, getName());
97 {
98 try
99 {
100 armemToImage.memoryReader =
101 memoryNameSystem().useReader(armemToImage.getMemoryID());
102 }
104 {
105 ARMARX_ERROR << e.what();
106 }
107 }
108
109 ARMARX_VERBOSE << "Trying initial fetch ...";
110 Eigen::Vector2i dimensions = p.fallbackDims;
111
112 armemToImage.fetchLatest();
113 if (armemToImage.updated)
114 {
115 dimensions = armemToImage.getImageDimensions();
116 ARMARX_VERBOSE << "Image formats: \n" << armemToImage.printFormats();
117 }
118 // ToDo: We (or the result image provider) could also wait until images are available.
119 enableResultImages(
120 armemToImage.images.size(), {dimensions(0), dimensions(1)}, eRgb, p.resultImagesName);
121 }
122
123 void
125 {
126 if (resultImageProvider)
127 {
128 getArmarXManager()->removeObjectBlocking(resultImageProvider->getName());
129 resultImageProvider = nullptr;
130 }
131 }
132
133 void
137
139 {
140 // Allow calling setName() from outside.
142 virtual ~LocalResultImageProvider() override;
143 };
144
148
149 void
150 ArMemToImageProvider::enableResultImages(size_t numberImages,
151 ImageDimension imageDimension,
152 ImageType imageType,
153 const std::string& name)
154 {
155 if (!resultImageProvider)
156 {
157 ARMARX_VERBOSE << "Enabling ImageProvider with " << numberImages
158 << " result images of size " << imageDimension.width << "x"
159 << imageDimension.height << ".";
160
162 Component::create<LocalResultImageProvider>();
163 provider->setName(name);
164 provider->setNumberResultImages(static_cast<int>(numberImages));
165 provider->setResultImageFormat(imageDimension, imageType);
166
167 try
168 {
169 getArmarXManager()->addObject(provider);
170 }
171 catch (const Ice::AlreadyRegisteredException& e)
172 {
173 ARMARX_ERROR << "The name '" << name
174 << "' is already used. Please choose another one.\n"
175 << "Reason: " << e.what();
176 getArmarXManager()->removeObjectBlocking(name);
177 }
178 provider->getObjectScheduler()->waitForObjectState(
179 armarx::ManagedIceObjectState::eManagedIceObjectStarted);
180
181 // Only now store it in member variable.
182 this->resultImageProvider = provider;
183 }
184 }
185
186 void
187 ArMemToImageProvider::fetchUpdates(
188 const armarx::armem::MemoryID& entityID,
189 const std::vector<armarx::armem::MemoryID>& updatedSnapshotIDs)
190 {
191 std::scoped_lock lock(armemToImageMutex);
192 armemToImage.fetchUpdates(entityID, updatedSnapshotIDs);
193
194 if (resultImageProvider && armemToImage.updated)
195 {
196 std::vector<CByteImage> ivtImages;
197 std::vector<CByteImage*> ivtImagesBuffer;
198 ivtImages.reserve(armemToImage.images.size());
199 ivtImagesBuffer.reserve(armemToImage.images.size());
200 for (auto& image : armemToImage.images)
201 {
202 CByteImage& ivt = ivtImages.emplace_back(image->toCByteImage());
203 ivtImagesBuffer.emplace_back(&ivt);
204 }
205 TIMING_START(Provide);
206 resultImageProvider->provideResultImages(
207 ivtImagesBuffer.data(), armemToImage.timestamp.toMicroSecondsSinceEpoch());
209 armemToImage.updated = false;
210
211 if (debugObserver)
212 {
213 debugObserver->setDebugChannel(
214 getName(),
215 {
216 {"Provide [us]", new armarx::Variant(Provide.toMicroSecondsDouble())},
217 });
218 }
219 }
220 }
221
222} // namespace visionx
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
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.