ArVizStorage.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 RobotAPI::ArmarXObjects::ArViz
17 * @author Fabian Paus ( fabian dot paus at kit dot edu )
18 * @date 2019
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "ArVizStorage.h"
24
25#include <algorithm>
26#include <filesystem>
27#include <mutex>
28#include <optional>
29#include <string>
30
31#include <SimoxUtility/json/json.hpp>
32
41
42namespace armarx
43{
44 static std::filesystem::path
45 getAbsolutePath(const std::filesystem::path& path)
46 {
47 if (path.is_absolute())
48 {
49 return path;
50 }
51 else
52 {
53 std::string absolute;
54 if (ArmarXDataPath::getAbsolutePath(path.string(), absolute))
55 {
56 return absolute;
57 }
58 else
59 {
60 ARMARX_WARNING_S << "Could not resolve relative file as package data file: "
61 << path;
62 return path;
63 }
64 }
65 }
66
67 std::string
69 {
70 return "ArVizStorage";
71 }
72
75 {
78
79 defs->optional(
80 properties_.topicName, "TopicName", "Layer updates are sent over this topic.");
81
82 defs->optional(properties_.maxHistorySize,
83 "MaxHistorySize",
84 "How many layer updates are saved in the history until they are compressed")
85 .setMin(0);
86
87 defs->optional(properties_.historyPath,
88 "HistoryPath",
89 "Destination path where the history is serialized to");
90
91
92 defs->optional(properties_.componentWarnFrequency,
93 "ComponentWarnFrequency",
94 "Define a frequency in Hz above which the compnent raises a warning. As you "
95 "should not send data at a too high rate.");
96
97 return defs;
98 }
99
100 void
102 {
103 properties_.historyPath = getAbsolutePath(properties_.historyPath);
104 if (!std::filesystem::exists(properties_.historyPath))
105 {
106 ARMARX_INFO << "Creating history path: " << properties_.historyPath;
107 std::error_code error;
108 std::filesystem::create_directory(properties_.historyPath, error);
109 if (error)
110 {
111 ARMARX_WARNING << "Could not create directory for history: \n" << error.message();
112 }
113 }
114
115 usingTopic(properties_.topicName);
116 }
117
118 void
120 {
121 revision = 0;
122 currentState.clear();
123 history.clear();
124 recordingInitialState.clear();
125
126 recordingBuffer.clear();
127 recordingMetaData.id = "";
128 }
129
130 void
132 {
133 if (recordingTask)
134 {
135 recordingTask->stop();
136 recordingTask = nullptr;
137 }
138 }
139
140 void
144
145 void
146 ArVizStorage::updateLayers(viz::data::LayerUpdateSeq const& updates, const Ice::Current&)
147 {
148 std::unique_lock<std::mutex> lock(historyMutex);
149
150 revision += 1;
151
152 IceUtil::Time now = IceUtil::Time::now();
153 long nowInMicroSeconds = now.toMicroSeconds();
154
155 if (not updates.empty())
156 {
157 const std::string& componentName = updates.front().component;
158
159 auto& history = updateHistoryForComponents[componentName];
160 history.push_back(armarx::Clock::Now());
161
162 const auto maxHistoryDur = armarx::Duration::SecondsDouble(1);
163
164 const DateTime referenceNow = Clock::Now();
165 const auto isOutdated = [&referenceNow,
166 &maxHistoryDur](const DateTime& timestamp) -> bool
167 { return (referenceNow - timestamp) > maxHistoryDur; };
168
169 // trim history
170 history.erase(std::remove_if(history.begin(), history.end(), isOutdated),
171 history.end());
172
173 ARMARX_VERBOSE << deactivateSpam(1, componentName) << componentName << ": "
174 << history.size() / maxHistoryDur.toSecondsDouble() << " Hz";
175
176 if (history.size() > properties_.componentWarnFrequency)
177 {
178 ARMARX_WARNING << deactivateSpam(10) << "Component `" << componentName << "`"
179 << "sends data at a too high rate ("
180 << history.size() / maxHistoryDur.toSecondsDouble() << ")"
181 << deactivateSpam(10, componentName);
182 }
183 }
184
185
186 for (auto& update : updates)
187 {
188 if (update.component.empty())
189 {
191 << "Discarding ArViz update with empty component name. Check whether "
192 << "you correctly create your ArViz client (`armarx::viz::Client`) "
193 << "in your code.";
194 continue;
195 }
196
197 auto& historyEntry = history.emplace_back();
198 historyEntry.revision = revision;
199 historyEntry.timestampInMicroseconds = nowInMicroSeconds;
200 historyEntry.update = update;
201
202 // Insert or create the layer
203 bool found = false;
204 for (auto& layer : currentState)
205 {
206 if (layer.update.component == update.component && layer.update.name == update.name)
207 {
208 layer = historyEntry;
209 found = true;
210 break;
211 }
212 }
213 if (!found)
214 {
215 currentState.push_back(historyEntry);
216 }
217 }
218
219 long currentHistorySize = history.size();
220 if (currentHistorySize >= properties_.maxHistorySize)
221 {
222 {
223 std::unique_lock<std::mutex> lock(recordingMutex);
224 if (recordingMetaData.id.size() > 0)
225 {
226 auto& newBatch = recordingBuffer.emplace_back();
227 newBatch.initialState = recordingInitialState;
228 newBatch.updates = std::move(history);
229 recordingInitialState = currentState;
230
231 recordingCondition.notify_one();
232 }
233 }
234 history.clear();
235 }
236 }
237
238 viz::data::CommitResult
239 ArVizStorage::commitAndReceiveInteractions(viz::data::CommitInput const& input,
240 const Ice::Current&)
241 {
242 viz::data::CommitResult result;
243
244 {
245 std::unique_lock<std::mutex> lock(historyMutex);
246
247 revision += 1;
248 result.revision = revision;
249
250 IceUtil::Time now = IceUtil::Time::now();
251 long nowInMicroSeconds = now.toMicroSeconds();
252
253 // Insert updates into the history and update the current state
254 for (viz::data::LayerUpdate const& update : input.updates)
255 {
256 viz::data::TimestampedLayerUpdate& historyEntry = history.emplace_back();
257 historyEntry.revision = revision;
258 historyEntry.timestampInMicroseconds = nowInMicroSeconds;
259 historyEntry.update = update;
260
261 // Insert or create the layer
262 bool found = false;
263 for (viz::data::TimestampedLayerUpdate& layer : currentState)
264 {
265 if (layer.update.component == update.component &&
266 layer.update.name == update.name)
267 {
268 layer = historyEntry;
269 found = true;
270 break;
271 }
272 }
273 if (!found)
274 {
275 currentState.push_back(historyEntry);
276 }
277 }
278
279 // Trim the history if max size has been exceeded
280 long currentHistorySize = history.size();
281 if (currentHistorySize >= properties_.maxHistorySize)
282 {
283 {
284 std::unique_lock<std::mutex> lock(recordingMutex);
285 if (recordingMetaData.id.size() > 0)
286 {
287 auto& newBatch = recordingBuffer.emplace_back();
288 newBatch.initialState = recordingInitialState;
289 newBatch.updates = std::move(history);
290 recordingInitialState = currentState;
291
292 recordingCondition.notify_one();
293 }
294 }
295 history.clear();
296 }
297
298 // Find relevant interactions
299 if (input.interactionComponent.size() > 0)
300 {
301 auto interactionsEnd = interactionBuffer.end();
302 auto foundInteractionsBegin =
303 std::partition(interactionBuffer.begin(),
304 interactionsEnd,
305 [&input](viz::data::InteractionFeedback const& interaction)
306 {
307 if (interaction.component == input.interactionComponent)
308 {
309 for (std::string const& layer : input.interactionLayers)
310 {
311 if (interaction.layer == layer)
312 {
313 return false;
314 }
315 }
316 }
317 return true;
318 });
319
320 result.interactions.assign(foundInteractionsBegin, interactionsEnd);
321 interactionBuffer.erase(foundInteractionsBegin, interactionsEnd);
322 }
323 }
324
325 return result;
326 }
327
328 viz::data::LayerUpdates
329 ArVizStorage::pullUpdatesSince(Ice::Long revision, const Ice::Current&)
330 {
331 viz::data::LayerUpdates result;
332
333 std::unique_lock<std::mutex> lock(historyMutex);
334
335 result.updates.reserve(currentState.size());
336 for (auto& layer : currentState)
337 {
338 if (layer.revision > revision)
339 {
340 result.updates.push_back(layer.update);
341 }
342 }
343 result.revision = this->revision;
344
345 return result;
346 }
347
348 static const int ALL_TRANSFORM_FLAGS =
349 viz::data::InteractionFeedbackType::TRANSFORM_BEGIN_FLAG |
350 viz::data::InteractionFeedbackType::TRANSFORM_DURING_FLAG |
351 viz::data::InteractionFeedbackType::TRANSFORM_END_FLAG;
352
353 viz::data::LayerUpdates
355 Ice::Long revision,
356 viz::data::InteractionFeedbackSeq const& interactions,
357 const Ice::Current& c)
358 {
359 viz::data::LayerUpdates result;
360
361 std::unique_lock<std::mutex> lock(historyMutex);
362
363 for (viz::data::InteractionFeedback const& interaction : interactions)
364 {
365 for (viz::data::InteractionFeedback& entry : interactionBuffer)
366 {
367 if (entry.component == interaction.component && entry.layer == interaction.layer &&
368 entry.element == interaction.element)
369 {
370 int previousTransformFlags = entry.type & ALL_TRANSFORM_FLAGS;
371 int interactionTransformFlags = interaction.type & ALL_TRANSFORM_FLAGS;
372
373 entry = interaction;
374 // Keep the previous transform flags.
375 // Blindly overwriting the entry might skip over the begin or during events.
376 if (previousTransformFlags != 0 && interactionTransformFlags != 0)
377 {
378 entry.type |= previousTransformFlags;
379 }
380 goto for_end;
381 }
382 }
383
384 // Interaction did not exist, add it to the buffer
385 interactionBuffer.push_back(interaction);
386
387 for_end:;
388 }
389
390 result.updates.reserve(currentState.size());
391 for (viz::data::TimestampedLayerUpdate& layer : currentState)
392 {
393 if (layer.revision > revision)
394 {
395 result.updates.push_back(layer.update);
396 }
397 }
398 result.revision = this->revision;
399
400 return result;
401 }
402
403 void
404 ArVizStorage::record()
405 {
406 while (!recordingTask->isStopped())
407 {
408 std::unique_lock<std::mutex> lock(recordingMutex);
409 while (!recordingTask->isStopped() && recordingBuffer.empty())
410 {
411 recordingCondition.wait_for(lock, std::chrono::milliseconds(10));
412 }
413 for (auto& batch : recordingBuffer)
414 {
415 recordBatch(batch);
416 }
417 recordingBuffer.clear();
418 }
419 }
420} // namespace armarx
421
423{
424
425 void
426 to_json(nlohmann::json& j, RecordingBatchHeader const& batch)
427 {
428 j["index"] = batch.index;
429 j["firstRevision"] = batch.firstRevision;
430 j["lastRevision"] = batch.lastRevision;
431 j["firstTimestampInMicroSeconds"] = batch.firstTimestampInMicroSeconds;
432 j["lastTimestampInMicroSeconds"] = batch.lastTimestampInMicroSeconds;
433 }
434
435 void
436 from_json(nlohmann::json const& j, RecordingBatchHeader& batch)
437 {
438 batch.index = j["index"];
439 batch.firstRevision = j["firstRevision"];
440 batch.lastRevision = j["lastRevision"];
441 batch.firstTimestampInMicroSeconds = j["firstTimestampInMicroSeconds"];
442 batch.lastTimestampInMicroSeconds = j["lastTimestampInMicroSeconds"];
443 }
444
445 void
446 to_json(nlohmann::json& j, Recording const& recording)
447 {
448 j["id"] = recording.id;
449 j["firstRevision"] = recording.firstRevision;
450 j["lastRevision"] = recording.lastRevision;
451 j["firstTimestampInMicroSeconds"] = recording.firstTimestampInMicroSeconds;
452 j["lastTimestampInMicroSeconds"] = recording.lastTimestampInMicroSeconds;
453 j["batchHeaders"] = recording.batchHeaders;
454 }
455
456 void
457 from_json(nlohmann::json const& j, Recording& recording)
458 {
459 recording.id = j["id"];
460 recording.firstRevision = j["firstRevision"];
461 recording.lastRevision = j["lastRevision"];
462 recording.firstTimestampInMicroSeconds = j["firstTimestampInMicroSeconds"];
463 recording.lastTimestampInMicroSeconds = j["lastTimestampInMicroSeconds"];
464 j["batchHeaders"].get_to(recording.batchHeaders);
465 }
466
467} // namespace armarx::viz::data
468
469static bool
470writeCompleteFile(std::string const& filename, const void* data, std::size_t size)
471{
472 FILE* file = fopen(filename.c_str(), "wb");
473 if (!file)
474 {
475 return false;
476 }
477 std::size_t written = std::fwrite(data, 1, size, file);
478 if (written != size)
479 {
480 return false;
481 }
482 std::fclose(file);
483 return true;
484}
485
486static std::string
487readCompleteFile(std::filesystem::path const& path)
488{
489 FILE* f = fopen(path.string().c_str(), "rb");
490 fseek(f, 0, SEEK_END);
491 long fsize = ftell(f);
492 fseek(f, 0, SEEK_SET); /* same as rewind(f); */
493
494 std::string result(fsize, '\0');
495 std::size_t read = fread(result.data(), 1, fsize, f);
496 result.resize(read);
497 fclose(f);
498
499 return result;
500}
501
502static std::optional<armarx::viz::data::Recording>
503readRecordingInfo(std::filesystem::path const& recordingDirectory)
504{
505 std::optional<::armarx::viz::data::Recording> result;
506
507 std::filesystem::path recordingFilePath = recordingDirectory / "recording.json";
508 if (!std::filesystem::exists(recordingFilePath))
509 {
510 ARMARX_INFO << "No recording.json found in directory: " << recordingDirectory;
511 return result;
512 }
513
514 try
515 {
516 std::string recordingString = readCompleteFile(recordingFilePath);
517 nlohmann::json recordingJson = nlohmann::json::parse(recordingString);
518
519 ::armarx::viz::data::Recording recording;
520 recordingJson.get_to(recording);
521
522 result = std::move(recording);
523 return result;
524 }
525 catch (std::exception const& ex)
526 {
527 ARMARX_WARNING << "Could not parse JSON file: " << recordingFilePath
528 << "\nReason: " << ex.what();
529 return result;
530 }
531}
532
533static std::string
534batchFileName(armarx::viz::data::RecordingBatchHeader const& batchHeader)
535{
536 return std::to_string(batchHeader.firstRevision) + ".bin";
537}
538
539void
540armarx::ArVizStorage::recordBatch(armarx::viz::data::RecordingBatch& batch)
541{
542 if (batch.updates.empty())
543 {
544 return;
545 }
546
547 auto& first = batch.updates.front();
548 auto& last = batch.updates.back();
549
550 batch.header.index = -1; // TODO: Should we save the index?
551 batch.header.firstRevision = first.revision;
552 batch.header.lastRevision = last.revision;
553 batch.header.firstTimestampInMicroSeconds = first.timestampInMicroseconds;
554 batch.header.lastTimestampInMicroSeconds = last.timestampInMicroseconds;
555 if (firstBatch)
556 {
557 batch.initialState = currentState;
558 firstBatch = false;
559 }
560
561
562 std::string filename = batchFileName(batch.header);
563 std::filesystem::path filePath = recordingPath / filename;
564
565 ObjectToIceBlobSerializer ser{batch};
566 // Save the batch to a new file
567 if (!writeCompleteFile(filePath.string(), ser.begin(), ser.size()))
568 {
569 ARMARX_WARNING << "Could not write history file: " << filePath;
570 return;
571 }
572
573 // Update the meta data
574 if (recordingMetaData.firstRevision < 0)
575 {
576 recordingMetaData.firstRevision = first.revision;
577 }
578 recordingMetaData.lastRevision = last.revision;
579
580 if (recordingMetaData.firstTimestampInMicroSeconds < 0)
581 {
582 recordingMetaData.firstTimestampInMicroSeconds = first.timestampInMicroseconds;
583 }
584 recordingMetaData.lastTimestampInMicroSeconds = last.timestampInMicroseconds;
585
586 armarx::viz::data::RecordingBatchHeader& newBatch =
587 recordingMetaData.batchHeaders.emplace_back();
588 newBatch.index = recordingMetaData.batchHeaders.size() - 1;
589 newBatch.firstRevision = first.revision;
590 newBatch.lastRevision = last.revision;
591 newBatch.firstTimestampInMicroSeconds = first.timestampInMicroseconds;
592 newBatch.lastTimestampInMicroSeconds = last.timestampInMicroseconds;
593
594 // Save the meta data to a (potentially existing) json file
595 nlohmann::json j = recordingMetaData;
596 std::string jString = j.dump(2);
597 std::filesystem::path recordingFile = recordingPath / "recording.json";
598 if (!writeCompleteFile(recordingFile.string(), jString.data(), jString.size()))
599 {
600 ARMARX_WARNING << "Could not write recording file: " << recordingFile;
601 return;
602 }
603
604 ARMARX_INFO << "Recorded ArViz batch to: " << filePath;
605}
606
607std::string
608armarx::ArVizStorage::startRecording(std::string const& newRecordingPrefix, const Ice::Current&)
609{
610 {
611 std::unique_lock<std::mutex> lock(recordingMutex);
612 if (recordingMetaData.id.size() > 0)
613 {
615 << "Could not start recording with prefix " << newRecordingPrefix
616 << "\nbecause there is already a recording running for the recording ID: "
617 << recordingMetaData.id;
618 return recordingMetaData.id;
619 }
620
621 IceUtil::Time now = IceUtil::Time::now();
622 std::ostringstream id;
623 id << newRecordingPrefix << '_' << now.toString("%Y-%m-%d_%H-%M-%S");
624 std::string newRecordingID = id.str();
625
626 recordingPath = properties_.historyPath / newRecordingID;
627 if (!std::filesystem::exists(recordingPath))
628 {
629 ARMARX_INFO << "Creating directory for recording with ID '" << newRecordingID
630 << "'\nPath: " << recordingPath;
631 std::filesystem::create_directory(recordingPath);
632 }
633
634 recordingBuffer.clear();
635
636 recordingMetaData.id = newRecordingID;
637 {
638 std::unique_lock<std::mutex> lock(historyMutex);
639 if (history.size() > 0)
640 {
641 auto& mostRecent = history.back();
642 recordingMetaData.firstRevision = mostRecent.revision;
643 recordingMetaData.firstTimestampInMicroSeconds = mostRecent.timestampInMicroseconds;
644 }
645 }
646 recordingMetaData.lastRevision = 0;
647 recordingMetaData.lastTimestampInMicroSeconds = 0;
648 recordingMetaData.batchHeaders.clear();
649 }
650
651 firstBatch = true;
652 recordingTask = new RunningTask<ArVizStorage>(this, &ArVizStorage::record);
653 recordingTask->start();
654
655 return "";
656}
657
658std::string
659armarx::ArVizStorage::startRecordingToDirectory(std::string const& recordingPath,
660 const Ice::Current&)
661{
662 {
663 std::unique_lock<std::mutex> lock(recordingMutex);
664 if (recordingMetaData.id.size() > 0)
665 {
667 << "Could not start recording with prefix " << recordingPath
668 << "\nbecause there is already a recording running for the recording ID: "
669 << recordingMetaData.id;
670 return recordingMetaData.id;
671 }
672
673 const std::string& newRecordingID = recordingPath;
674
675 this->recordingPath = recordingPath;
676 if (!std::filesystem::exists(recordingPath))
677 {
678 ARMARX_INFO << "Creating directory for recording with ID and path: "
679 << QUOTED(newRecordingID);
680 std::filesystem::create_directory(recordingPath);
681 }
682
683 recordingBuffer.clear();
684
685 recordingMetaData.id = newRecordingID;
686 {
687 std::unique_lock<std::mutex> lock(historyMutex);
688 if (history.size() > 0)
689 {
690 auto& mostRecent = history.back();
691 recordingMetaData.firstRevision = mostRecent.revision;
692 recordingMetaData.firstTimestampInMicroSeconds = mostRecent.timestampInMicroseconds;
693 }
694 }
695 recordingMetaData.lastRevision = 0;
696 recordingMetaData.lastTimestampInMicroSeconds = 0;
697 recordingMetaData.batchHeaders.clear();
698 }
699
700 firstBatch = true;
701 recordingTask = new RunningTask<ArVizStorage>(this, &ArVizStorage::record);
702 recordingTask->start();
703
704 return "";
705}
706
707void
709{
710 if (!recordingTask)
711 {
712 return;
713 }
714
715 recordingTask->stop();
716 recordingTask = nullptr;
717
718 std::unique_lock<std::mutex> lock(recordingMutex);
719
720 viz::data::RecordingBatch lastBatch;
721 lastBatch.initialState = recordingInitialState;
722 lastBatch.updates = std::move(history);
723 recordBatch(lastBatch);
724
725 recordingMetaData.id = "";
726 recordingMetaData.firstRevision = -1;
727 recordingMetaData.firstTimestampInMicroSeconds = -1;
728}
729
730armarx::viz::data::RecordingsInfo
732{
733 viz::data::RecordingsInfo recordingsInfo;
734 viz::data::RecordingSeq result;
735
736 for (std::filesystem::directory_entry const& entry :
737 std::filesystem::directory_iterator(properties_.historyPath))
738 {
739 ARMARX_DEBUG << "Checking: " << entry.path();
740
741 if (!entry.is_directory())
742 {
743 continue;
744 }
745
746 std::optional<viz::data::Recording> recording = readRecordingInfo(entry.path());
747 if (recording)
748 {
749 result.push_back(std::move(*recording));
750 }
751 }
752
753 recordingsInfo.recordings = result;
754 recordingsInfo.recordingsPath = properties_.historyPath;
755
756 return recordingsInfo;
757}
758
759armarx::viz::data::RecordingBatch
760armarx::ArVizStorage::getRecordingBatch(std::string const& recordingID,
761 Ice::Long batchIndex,
762 const Ice::Current&)
763{
764 viz::data::RecordingBatch result;
765 result.header.index = -1;
766
767 std::filesystem::path recordingPath = properties_.historyPath / recordingID;
768 std::optional<viz::data::Recording> recording = readRecordingInfo(recordingPath);
769 if (!recording)
770 {
771 ARMARX_WARNING << "Could not read recording information for '" << recordingID << "'"
772 << "\nPath: " << recordingPath;
773 return result;
774 }
775
776 if (batchIndex < 0 || batchIndex >= (long)recording->batchHeaders.size())
777 {
778 ARMARX_WARNING << "Batch index is not valid. Index = " << batchIndex
779 << "Batch count: " << recording->batchHeaders.size();
780 return result;
781 }
782
783 viz::data::RecordingBatchHeader const& batchHeader = recording->batchHeaders[batchIndex];
784 std::filesystem::path batchFile = recordingPath / batchFileName(batchHeader);
785 if (!std::filesystem::exists(batchFile))
786 {
787 ARMARX_WARNING << "Could not find batch file for recording '" << recordingID
788 << "' with index " << batchIndex << "\nPath: " << batchFile;
789 return result;
790 }
791
792 iceBlobToObject(result, readCompleteFile(batchFile));
793
794 result.header.index = batchIndex;
795
796 return result;
797}
std::string timestamp()
uint8_t data[1]
#define QUOTED(x)
constexpr T c
viz::data::CommitResult commitAndReceiveInteractions(viz::data::CommitInput const &input, const Ice::Current &) override
void onInitComponent() override
armarx::ManagedIceObject::onInitComponent()
std::string startRecording(std::string const &prefix, const Ice::Current &) override
void updateLayers(viz::data::LayerUpdateSeq const &updates, const Ice::Current &) override
void onDisconnectComponent() override
armarx::ManagedIceObject::onDisconnectComponent()
viz::data::LayerUpdates pullUpdatesSinceAndSendInteractions(Ice::Long revision, viz::data::InteractionFeedbackSeq const &interactions, const Ice::Current &) override
viz::data::LayerUpdates pullUpdatesSince(Ice::Long revision, const Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
PropertyUser::createPropertyDefinitions()
std::string startRecordingToDirectory(std::string const &recordingPath, const Ice::Current &) override
viz::data::RecordingsInfo getAllRecordings(const Ice::Current &) override
void onConnectComponent() override
armarx::ManagedIceObject::onConnectComponent()
viz::data::RecordingBatch getRecordingBatch(const std::string &, Ice::Long, const Ice::Current &) override
void stopRecording(const Ice::Current &) override
void onExitComponent() override
armarx::ManagedIceObject::onExitComponent()
std::string getDefaultName() const override
armarx::ManagedIceObject::getDefaultName()
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
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
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
Definition Duration.cpp:78
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
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Represents a point in time.
Definition DateTime.h:25
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
void to_json(nlohmann::json &j, RecordingBatchHeader const &batch)
void from_json(nlohmann::json const &j, RecordingBatchHeader &batch)
This file offers overloads of toIce() and fromIce() functions for STL container types.
void read(auto &eigen, auto *table)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
void iceBlobToObject(T &result, const std::string_view &sv)