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 
23 #include "ArMemToImageProvider.h"
24 
25 #include <algorithm>
26 
30 
33 
34 namespace 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
135  {
136  }
137 
139  {
140  // Allow calling setName() from outside.
142  virtual ~LocalResultImageProvider() override;
143  };
144 
146  {
147  }
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
visionx::armem_images::ArMemToImage::timestamp
armarx::armem::Time timestamp
Definition: ArMemToImage.h:53
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
visionx::LocalResultImageProvider
Definition: ArMemToImageProvider.cpp:138
TIMING_START
#define TIMING_START(name)
Definition: TimeUtil.h:289
visionx::ArMemToImageProvider::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ArMemToImageProvider.cpp:134
visionx::armem_images::ArMemToImage::memoryReader
armarx::armem::client::Reader memoryReader
Definition: ArMemToImage.h:50
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
client.h
visionx::LocalResultImageProvider::~LocalResultImageProvider
virtual ~LocalResultImageProvider() override
Definition: ArMemToImageProvider.cpp:145
visionx::ArMemToImageProvider::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ArMemToImageProvider.cpp:94
armarx::armem::client::plugins::PluginUser::memoryNameSystem
MemoryNameSystem & memoryNameSystem()
Definition: PluginUser.cpp:20
armarx::ManagedIceObject::getArmarXManager
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Definition: ManagedIceObject.cpp:360
visionx::armem_images::ArMemToImage::getMemoryID
armarx::armem::MemoryID getMemoryID() const override
Definition: ArMemToImage.cpp:55
visionx::armem_images::detail::ImageAdapter::setDebugObserver
void setDebugObserver(armarx::DebugObserverInterfacePrx proxy)
Definition: ImageAdapter.cpp:16
visionx::armem_images::ArMemToImage::updated
bool updated
Definition: ArMemToImage.h:54
TIMING_END_STREAM
#define TIMING_END_STREAM(name, os)
Definition: TimeUtil.h:310
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
visionx::armem_images::ArMemToImage::addImagesRGB
void addImagesRGB(const armarx::armem::MemoryID &entityID, const std::vector< size_t > &imageIndices) override
Definition: ArMemToImage.cpp:41
error.h
armarx::armem::client::MemoryNameSystem::useReader
Reader useReader(const MemoryID &memoryID)
Use a memory server and get a reader for it.
Definition: MemoryNameSystem.cpp:198
visionx::armem_images::ArMemToImage::summarizeStructure
std::string summarizeStructure() const override
Definition: ArMemToImage.cpp:109
visionx::armem_images::ArMemToImage::printFormats
std::string printFormats() const
Definition: ArMemToImage.cpp:155
ArmarXObjectScheduler.h
armarx::armem::client::util::MemoryListener::subscribe
SubscriptionHandle subscribe(const MemoryID &subscriptionID, Callback Callback)
Definition: MemoryListener.cpp:116
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::core::time::DateTime::toMicroSecondsSinceEpoch
std::int64_t toMicroSecondsSinceEpoch() const
Definition: DateTime.cpp:87
visionx::ArMemToImageProvider::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: ArMemToImageProvider.cpp:124
visionx::armem_images::ArMemToImage::fetchLatest
armarx::armem::client::QueryResult fetchLatest()
Definition: ArMemToImage.cpp:120
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
visionx::LocalResultImageProvider::ArMemToImageProvider
friend ArMemToImageProvider
Definition: ArMemToImageProvider.cpp:141
visionx::ArMemToImageProvider::getDefaultName
std::string getDefaultName() const override
Retrieve default name of component.
Definition: ArMemToImageProvider.cpp:38
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:69
TimeUtil.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::PropertyUser::getProperty
Property< PropertyType > getProperty(const std::string &name)
Property creation and retrieval.
Definition: PropertyUser.h:180
visionx::armem_images::ArMemToImage::addImagesDepth
void addImagesDepth(const armarx::armem::MemoryID &entityID, const std::vector< size_t > &imageIndices) override
Definition: ArMemToImage.cpp:48
IceUtil::Handle< class PropertyDefinitionContainer >
visionx::armem_images::ArMemToImage::getImageDimensions
Eigen::Vector2i getImageDimensions() const
Definition: ArMemToImage.cpp:67
ArMemToImageProvider.h
armarx::armem::error::CouldNotResolveMemoryServer
Indicates that a query to the Memory Name System failed.
Definition: mns.h:24
visionx::ResultImageProvider
The ResultImageProvider is used by the ImageProcessor to stream result images to any other processor ...
Definition: ImageProcessor.h:541
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:108
visionx::armem_images::ArMemToImage::fetchUpdates
void fetchUpdates(const armarx::armem::MemoryID &entityID, const std::vector< armarx::armem::MemoryID > &updatedSnapshotIDs)
Definition: ArMemToImage.cpp:80
visionx::ArMemToImageProvider::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: ArMemToImageProvider.cpp:44
Variant.h
visionx::armem_images::ArMemToImage::images
std::vector< std::unique_ptr< ImageBase > > images
Definition: ArMemToImage.h:52
visionx::ArMemToImageProvider::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: ArMemToImageProvider.cpp:70