35 #include "../util/ControlThreadOutputBuffer.h"
47 t = IceUtil::Time::seconds(0);
68 return t.toMilliSecondsDouble();
94 const std::string& marker,
99 std::lock_guard<std::mutex> guard{rtLoggingMutex};
100 if (!rtLoggingEntries.count(token->getId()))
102 throw InvalidArgumentException{
"addMarkerToRtLog called for a nonexistent log"};
104 rtLoggingEntries.at(token->getId())->marker = marker;
107 SimpleRemoteReferenceCounterBasePtr
109 const Ice::StringSeq& loggingNames,
114 StringStringDictionary alias;
115 for (
const auto& name : loggingNames)
117 alias.emplace(name,
"");
127 std::lock_guard<std::mutex> guard{rtLoggingMutex};
131 if (!rtLoggingEntries.count(token->getId()))
133 throw InvalidArgumentException{
"stopRtLogging called for a nonexistent log"};
136 << rtLoggingEntries.at(token->getId())->filename;
137 rtLoggingEntries.at(token->getId())->stopLogging =
true;
150 Ice::StringSeq result;
151 for (
const auto&
data : sensorDeviceValueMetaData)
153 for (
auto& fieldData :
data.fields)
155 result.push_back(fieldData.name);
158 for (
const auto& datas : controlDeviceValueMetaData)
160 for (
const auto&
data : datas)
162 for (
auto& fieldData :
data.fields)
164 result.push_back(fieldData.name);
171 SimpleRemoteReferenceCounterBasePtr
173 const StringStringDictionary& aliasNames,
179 std::lock_guard<std::mutex> guard{rtLoggingMutex};
180 if (rtLoggingEntries.count(pb.getPath()))
182 throw InvalidArgumentException{
"There already is a logger for the path '" +
185 rtLoggingEntries[pb.getPath()].reset(
new CSVLoggingEntry());
186 auto ptr = rtLoggingEntries[pb.getPath()];
187 CSVLoggingEntry& e = *ptr;
188 e.filename = pb.getPath();
189 pb.createParentDirectories();
190 e.stream.open(e.filename);
193 rtLoggingEntries.erase(pb.getPath());
194 throw LogicError{
"RtLogging could not open filestream for '" + pb.getPath() +
"'"};
197 <<
". Names (pattern, replacement name): " << aliasNames;
199 std::stringstream header;
200 header <<
"marker;iteration;timestamp;TimeSinceLastIteration";
201 auto logDev = [&](
const std::string& dev)
204 for (
const auto& [key,
value] : aliasNames)
206 if (MatchName(key, dev))
208 header <<
";" << (
value.empty() ? dev :
value);
218 e.loggedSensorDeviceValues.reserve(sensorDeviceValueMetaData.size());
219 for (
const auto& valData : sensorDeviceValueMetaData)
221 e.loggedSensorDeviceValues.emplace_back();
222 auto& svfieldsFlags = e.loggedSensorDeviceValues.back();
223 svfieldsFlags.reserve(valData.fields.size());
224 for (
const auto& field : valData.fields)
226 svfieldsFlags.emplace_back(logDev(field.name));
233 e.loggedControlDeviceValues.reserve(controlDeviceValueMetaData.size());
234 for (
const auto& datas : controlDeviceValueMetaData)
236 e.loggedControlDeviceValues.emplace_back();
237 auto& deviceCtrlFlags = e.loggedControlDeviceValues.back();
238 deviceCtrlFlags.reserve(datas.size());
239 for (
const auto& valData : datas)
241 deviceCtrlFlags.emplace_back();
242 auto& ctrlFieldFlags = deviceCtrlFlags.back();
243 ctrlFieldFlags.reserve(valData.fields.size());
245 for (
const auto& field : valData.fields)
247 ctrlFieldFlags.emplace_back(logDev(field.name));
255 e.stream << header.str()
261 ARMARX_DEBUG_S <<
"RobotUnit: stop RtLogging for file " << ptr->filename;
262 ptr->stopLogging =
true;
265 IceUtil::Time::milliSeconds(100));
266 auto counter = block->getReferenceCounter();
267 block->activateCounting();
268 ARMARX_DEBUG_S <<
"RobotUnit: start RtLogging for file " << ptr->filename;
277 std::lock_guard<std::mutex> guard{rtLoggingMutex};
280 std::ofstream outCSV{pb.getPath() +
".csv"};
283 throw LogicError{
"writeRecentIterationsToFile could not open filestream for '" +
284 pb.getPath() +
".csv'"};
286 std::ofstream outMsg{pb.getPath() +
".messages"};
289 throw LogicError{
"writeRecentIterationsToFile could not open filestream for '" +
290 pb.getPath() +
".messages'"};
292 ARMARX_INFO <<
"writing the last " << backlog.size() <<
" iterations to " << pb.getPath()
293 <<
".{csv, messages}";
296 outCSV <<
"iteration;timestamp";
297 for (
const auto& vs : sensorDeviceValueMetaData)
299 for (
const auto& f : vs.fields)
301 outCSV <<
";" << f.name;
304 for (
const auto& vvs : controlDeviceValueMetaData)
306 for (
const auto& vs : vvs)
308 for (
const auto& f : vs.fields)
310 outCSV <<
";" << f.name;
317 for (const ::armarx::detail::ControlThreadOutputBufferEntry& iteration : backlog)
321 outCSV << iteration.iteration <<
";" << iteration.sensorValuesTimestamp;
337 for (
const auto& vals : iteration.control)
341 for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields();
345 val->getDataFieldAs(idxField,
s);
355 bool atLeastOneMessage =
false;
356 for (const ::armarx::detail::RtMessageLogEntryBase* msg :
357 iteration.messages.getEntries())
363 outMsg <<
"[" << msg->getTime().toDateTime() <<
"] iteration "
364 << iteration.iteration <<
":\n"
365 << msg->format() << std::endl;
366 atLeastOneMessage =
true;
368 if (atLeastOneMessage)
370 outMsg <<
"\nmessages lost: " << iteration.messages.messagesLost
371 <<
" (required additional "
372 << iteration.messages.requiredAdditionalBufferSpace <<
" bytes, "
373 << iteration.messages.requiredAdditionalEntries <<
" message entries)\n"
380 RobotUnitDataStreaming::DataStreamingDescription
382 const RobotUnitDataStreaming::Config& config,
389 throw InvalidArgumentException{
"Receiver proxy is NULL!"};
391 std::lock_guard<std::mutex> guard{rtLoggingMutex};
392 if (rtDataStreamingEntry.count(receiver))
394 throw InvalidArgumentException{
"There already is a logger for the given receiver"};
397 RobotUnitDataStreaming::DataStreamingDescription result;
398 DataStreamingEntry& streamingEntry = rtDataStreamingEntry[receiver];
399 getProperty(streamingEntry.rtStreamMaxClientErrors,
400 "RTLogging_StreamingDataMaxClientConnectionFailures");
403 ARMARX_INFO <<
"start data streaming to " << receiver->ice_getIdentity().name
404 <<
". Values: " << config.loggingNames;
405 auto devMatchesAnyKey = [&](
const std::string& dev)
407 for (
const auto& key : config.loggingNames)
409 if (MatchName(key, dev))
417 const auto handleVal = [&](
const ValueMetaData& valData,
418 DataStreamingEntry& streamingEntry,
419 RobotUnitDataStreaming::DataStreamingDescription& descr)
420 -> std::vector<DataStreamingEntry::OutVal>
423 std::vector<DataStreamingEntry::OutVal> result;
424 result.resize(valData.fields.size());
425 for (std::size_t i = 0; i < valData.fields.size(); ++i)
427 if (!devMatchesAnyKey(valData.fields.at(i).name))
431 auto& descrEntr = descr.entries[valData.fields.at(i).name];
434 #define make_case(Type, TName) \
435 (typeid(Type) == *valData.fields.at(i).type) \
437 descrEntr.index = streamingEntry.num##TName##s; \
438 descrEntr.type = RobotUnitDataStreaming::NodeType##TName; \
439 result.at(i).idx = streamingEntry.num##TName##s; \
440 result.at(i).value = DataStreamingEntry::ValueT::TName; \
441 ++streamingEntry.num##TName##s; \
454 <<
"This code sould be unreachable! "
456 << valData.fields.at(i).name <<
" is not handled correctly!";
467 streamingEntry.sensDevs.reserve(sensorDeviceValueMetaData.size());
468 for (
const auto& valData : sensorDeviceValueMetaData)
470 streamingEntry.sensDevs.emplace_back(handleVal(valData, streamingEntry, result));
476 streamingEntry.ctrlDevs.reserve(controlDeviceValueMetaData.size());
477 for (
const auto& devData : controlDeviceValueMetaData)
479 streamingEntry.ctrlDevs.emplace_back();
480 auto& ctrlDevEntrs = streamingEntry.ctrlDevs.back();
481 ctrlDevEntrs.reserve(devData.size());
482 for (
const auto& valData : devData)
484 ctrlDevEntrs.emplace_back(handleVal(valData, streamingEntry, result));
498 std::lock_guard<std::mutex> guard{rtLoggingMutex};
500 if (rtDataStreamingEntry.count(receiver) == 0u)
502 ARMARX_INFO <<
"stopDataStreaming called for a nonexistent log";
506 ARMARX_INFO_S <<
"RobotUnit: request to stop DataStreaming for " << receiver->ice_id();
507 rtDataStreamingEntry.at(receiver).stopStreaming =
true;
511 Logging::_preFinishRunning()
515 defaultLogHandle =
nullptr;
516 if (rtLoggingTask.joinable())
519 stopRtLoggingTask =
true;
520 rtLoggingTask.join();
526 Logging::_preFinishControlThreadInitialization()
531 ControlThreadOutputBuffer::RtLoggingInstance =
532 &(_module<ControlThreadDataBuffer>().getControlThreadOutputBuffer());
534 ARMARX_INFO <<
"starting rt logging with timestep " << rtLoggingTimestepMs;
535 stopRtLoggingTask =
false;
537 rtLoggingTask = std::thread{
540 using clock_t = std::chrono::steady_clock;
541 const auto now = [] {
return clock_t::now(); };
543 while (!stopRtLoggingTask)
545 const auto start = now();
547 const std::uint64_t ms =
548 std::chrono::duration_cast<std::chrono::milliseconds>(now() - start)
550 if (ms > rtLoggingTimestepMs)
553 <<
" ms > " << rtLoggingTimestepMs
554 <<
" ms (message printed every 10 seconds)";
556 metronome.waitForNextTick();
566 std::lock_guard<std::mutex> guard{rtLoggingMutex};
571 const auto start_time_remove_backlog_entries =
armarx::rtNow();
573 if (rtLoggingBacklogEnabled)
575 while (!backlog.empty() &&
576 (backlog.front().writeTimestamp + rtLoggingBacklogRetentionTime < now or
577 backlog.size() > rtLoggingBacklogMaxSize))
585 details::DoLoggingDurations dlogdurs;
587 if (!rtLoggingEntries.empty() || !rtDataStreamingEntry.empty())
591 <<
"Number of streams " << rtDataStreamingEntry.size();
594 if (numberOfEntriesToLog < 1)
596 _module<ControlThreadDataBuffer>()
597 .getControlThreadOutputBuffer()
598 .forEachNewLoggingEntry(
599 [
this, &dlogdurs, &now](
const auto&
data,
auto i,
auto num)
602 doLogging(dlogdurs, now,
data, i, num);
607 _module<ControlThreadDataBuffer>()
608 .getControlThreadOutputBuffer()
609 .forLatestLoggingEntry(
610 [
this, &dlogdurs, &now](
const auto&
data,
auto i,
auto num)
613 doLogging(dlogdurs, now,
data, i, num);
615 numberOfEntriesToLog);
619 <<
" iterations are stored";
623 for (
auto& pair : rtLoggingEntries)
633 std::vector<std::string> toRemove;
634 toRemove.reserve(rtLoggingEntries.size());
635 for (
auto& [key,
value] : rtLoggingEntries)
637 if (
value->stopLogging)
641 toRemove.emplace_back(key);
644 for (
const auto& rem : toRemove)
646 rtLoggingEntries.erase(rem);
653 std::vector<RobotUnitDataStreaming::ReceiverPrx> toRemove;
654 toRemove.reserve(rtDataStreamingEntry.size());
655 for (
auto& [prx,
data] : rtDataStreamingEntry)
658 << prx->ice_toString();
659 if (
data.stopStreaming)
661 toRemove.emplace_back(prx);
665 data.send(prx, rtDataStreamingMsgID);
668 ++rtDataStreamingMsgID;
669 for (
const auto& prx : toRemove)
671 rtDataStreamingEntry.erase(prx);
676 const auto time_total = (end_time - now).toMilliSecondsDouble();
678 <<
"rtlogging time required: " << time_total <<
"ms\n"
679 <<
" time_remove_backlog_entries "
680 << (start_time_log_all - start_time_remove_backlog_entries).toMilliSecondsDouble() <<
"ms\n"
682 << (start_time_flush_all_files - start_time_log_all).toMilliSecondsDouble() <<
"ms\n"
683 <<
" header " << dlogdurs.header.ms() <<
"ms\t(" << dlogdurs.header.n
685 <<
" csv " << dlogdurs.header_csv.ms() <<
"ms\t("
686 << dlogdurs.header_csv.n <<
" calls)\n"
687 <<
" stream " << dlogdurs.header_stream.ms() <<
"ms\t("
688 << dlogdurs.header_stream.n <<
" calls)\n"
689 <<
" sens " << dlogdurs.sens.ms() <<
"ms\t(" << dlogdurs.sens.n
691 <<
" csv " << dlogdurs.sens_csv.ms() <<
"ms\t(" << dlogdurs.sens_csv.n
693 <<
" stream " << dlogdurs.sens_stream.ms() <<
"ms\t("
694 << dlogdurs.sens_stream.n <<
" calls)\n"
695 <<
" per elem " << dlogdurs.sens_stream_elem.ms() <<
"ms\t("
696 << dlogdurs.sens_stream_elem.n <<
" calls)\n"
697 <<
" ctrl " << dlogdurs.ctrl.ms() <<
"ms\t(" << dlogdurs.ctrl.n
699 <<
" csv " << dlogdurs.ctrl_csv.ms() <<
"ms\t(" << dlogdurs.ctrl_csv.n
701 <<
" stream " << dlogdurs.ctrl_stream.ms() <<
"ms\t("
702 << dlogdurs.ctrl_stream.n <<
" calls)\n"
703 <<
" per elem " << dlogdurs.ctrl_stream_elem.ms() <<
"ms\t("
704 << dlogdurs.ctrl_stream_elem.n <<
" calls)\n"
705 <<
" backlog " << dlogdurs.backlog.ms() <<
"ms\t(" << dlogdurs.backlog.n
707 <<
" msg " << dlogdurs.msg.ms() <<
"ms\t(" << dlogdurs.msg.n
709 <<
" time_flush_all_files "
710 << (start_time_remove_entries - start_time_flush_all_files).toMilliSecondsDouble() <<
"ms\n"
711 <<
" time_remove_entries "
712 << (start_time_data_streaming - start_time_remove_entries).toMilliSecondsDouble() <<
"ms\n"
713 <<
" time_data_streaming "
714 << (end_time - start_time_data_streaming).toMilliSecondsDouble() <<
"ms\n";
719 Logging::doLogging(details::DoLoggingDurations& durations,
730 durations.header.start();
733 if (!rtLoggingEntries.empty())
735 durations.header_csv.start();
736 for (
auto& [_, e] : rtLoggingEntries)
739 << e->marker <<
";" <<
data.iteration <<
";"
740 <<
data.sensorValuesTimestamp.toMicroSeconds() <<
";"
741 <<
data.timeSinceLastIteration.toMicroSeconds();
744 durations.header_csv.stop();
747 if (!rtDataStreamingEntry.empty())
749 durations.header_stream.start();
750 for (
auto& [_, e] : rtDataStreamingEntry)
752 e.processHeader(
data);
754 durations.header_stream.stop();
756 durations.header.stop();
763 durations.sens.start();
765 for (std::size_t idxDev = 0; idxDev <
data.sensors.size(); ++idxDev)
767 const SensorValueBase* val =
data.sensors.at(idxDev);
769 for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields();
772 if (!rtLoggingEntries.empty())
774 durations.sens_csv.start();
775 const auto str = val->getDataFieldAs<std::string>(idxField);
776 for (
auto& [_, entry] : rtLoggingEntries)
778 if (entry->loggedSensorDeviceValues.at(idxDev).at(idxField))
780 entry->stream <<
";" <<
str;
783 durations.sens_csv.stop();
785 if (!rtDataStreamingEntry.empty())
787 durations.sens_stream.start();
788 for (
auto& [_, rtStreamingEntry] : rtDataStreamingEntry)
790 durations.sens_stream_elem.start();
791 rtStreamingEntry.processSens(*val, idxDev, idxField);
792 durations.sens_stream_elem.stop();
794 durations.sens_stream.stop();
798 durations.sens.stop();
803 durations.ctrl.start();
806 for (std::size_t idxDev = 0; idxDev <
data.control.size(); ++idxDev)
808 const auto& vals =
data.control.at(idxDev);
810 for (std::size_t idxVal = 0; idxVal < vals.size(); ++idxVal)
812 const ControlTargetBase* val = vals.at(idxVal);
814 for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields();
817 if (!rtLoggingEntries.empty())
819 durations.ctrl_csv.start();
821 val->getDataFieldAs(idxField,
str);
822 for (
auto& [_, entry] : rtLoggingEntries)
824 if (entry->loggedControlDeviceValues.at(idxDev).at(idxVal).at(
827 entry->stream <<
";" <<
str;
830 durations.ctrl_csv.stop();
832 if (!rtDataStreamingEntry.empty())
834 durations.ctrl_stream.start();
835 for (
auto& [_, rtStreamingEntry] : rtDataStreamingEntry)
837 durations.ctrl_stream_elem.start();
838 rtStreamingEntry.processCtrl(*val, idxDev, idxVal, idxField);
839 durations.ctrl_stream_elem.stop();
841 durations.ctrl_stream.stop();
847 durations.ctrl.stop();
855 if (rtLoggingBacklogEnabled)
857 durations.backlog.start();
859 if (
data.writeTimestamp + rtLoggingBacklogRetentionTime >= now)
861 backlog.emplace_back(
data,
true);
863 durations.backlog.stop();
868 durations.msg.start();
870 for (const ::armarx::detail::RtMessageLogEntryBase* ptr :
871 data.messages.getEntries())
877 ptr->print(controlThreadId);
879 durations.msg.stop();
885 Logging::MatchName(
const std::string& pattern,
const std::string& name)
892 static const std::regex pattern_regex{R
"(^\^?[- ._*a-zA-Z0-9]+\$?$)"};
893 if (!std::regex_match(pattern, pattern_regex))
895 throw InvalidArgumentException{
"Pattern '" + pattern +
"' is invalid"};
897 static const std::regex reg_dot{
"[.]"};
898 static const std::regex reg_star{
"[*]"};
899 const std::string rpl1 = std::regex_replace(pattern, reg_dot,
"\\.");
900 const std::string rpl2 = std::regex_replace(rpl1, reg_star,
".*");
901 const std::regex key_regex{rpl2};
902 return std::regex_search(name, key_regex);
906 Logging::_postOnInitRobotUnit()
910 rtLoggingTimestepMs = getProperty<std::size_t>(
"RTLogging_PeriodMs");
911 ARMARX_CHECK_LESS(0, rtLoggingTimestepMs) <<
"The property RTLoggingPeriodMs must not be 0";
913 messageBufferSize = getProperty<std::size_t>(
"RTLogging_MessageBufferSize");
914 messageBufferMaxSize = getProperty<std::size_t>(
"RTLogging_MaxMessageBufferSize");
917 messageBufferNumberEntries = getProperty<std::size_t>(
"RTLogging_MessageNumber");
918 messageBufferMaxNumberEntries = getProperty<std::size_t>(
"RTLogging_MaxMessageNumber");
921 rtLoggingBacklogRetentionTime =
922 IceUtil::Time::milliSeconds(getProperty<std::size_t>(
"RTLogging_KeepIterationsForMs"));
923 rtLoggingBacklogMaxSize = getProperty<std::size_t>(
"RTLogging_MaxBacklogSize");
924 rtLoggingBacklogEnabled = getProperty<bool>(
"RTLogging_EnableBacklog");
925 getProperty(numberOfEntriesToLog,
"RTLogging_LogLastNMessagesOnly");
927 ARMARX_IMPORTANT <<
"Initializing RTLogging with the following parameters: "
928 <<
VAROUT(rtLoggingTimestepMs) <<
VAROUT(messageBufferSize)
929 <<
VAROUT(messageBufferMaxSize) <<
VAROUT(messageBufferNumberEntries)
930 <<
VAROUT(messageBufferMaxNumberEntries)
931 <<
VAROUT(rtLoggingBacklogRetentionTime) <<
VAROUT(rtLoggingBacklogMaxSize)
932 <<
VAROUT(rtLoggingBacklogEnabled) <<
VAROUT(numberOfEntriesToLog);
936 Logging::_postFinishDeviceInitialization()
943 std::size_t ctrlThreadPeriodUs =
945 std::size_t logThreadPeriodUs = rtLoggingTimestepMs * 1000;
946 std::size_t nBuffers = (logThreadPeriodUs / ctrlThreadPeriodUs + 1) * 100;
948 const auto bufferSize =
949 _module<ControlThreadDataBuffer>().getControlThreadOutputBuffer().initialize(
951 _module<Devices>().getControlDevices(),
952 _module<Devices>().getSensorDevices(),
954 messageBufferNumberEntries,
955 messageBufferMaxSize,
956 messageBufferMaxNumberEntries);
957 ARMARX_INFO <<
"RTLogging activated. Using " << nBuffers <<
" buffers "
958 <<
"(buffersize = " << bufferSize <<
" bytes)";
963 const auto makeValueMetaData = [&](
auto* val,
const std::string& namePre)
966 const auto names = val->getDataFieldNames();
969 for (std::size_t fieldIdx = 0; fieldIdx <
names.size(); ++fieldIdx)
971 std::string
const& fieldName =
names[fieldIdx];
972 data.fields.at(fieldIdx).name = namePre +
'.' + fieldName;
973 data.fields.at(fieldIdx).type = &(val->getDataFieldType(fieldIdx));
979 controlDeviceValueMetaData.reserve(_module<Devices>().getControlDevices().size());
980 for (
const auto& cd : _module<Devices>().getControlDevices().values())
983 controlDeviceValueMetaData.emplace_back();
984 auto& dataForDev = controlDeviceValueMetaData.back();
985 dataForDev.reserve(cd->getJointControllers().size());
986 for (
auto jointC : cd->getJointControllers())
988 dataForDev.emplace_back(makeValueMetaData(jointC->getControlTarget(),
989 "ctrl." + cd->getDeviceName() +
"." +
990 jointC->getControlMode()));
994 sensorDeviceValueMetaData.reserve(_module<Devices>().getSensorDevices().size());
995 for (
const auto& sd : _module<Devices>().getSensorDevices().values())
998 sensorDeviceValueMetaData.emplace_back(
999 makeValueMetaData(sd->getSensorValue(),
"sens." + sd->getDeviceName()));
1006 const auto loggingpath = getProperty<std::string>(
"RTLogging_DefaultLog").getValue();
1007 if (!loggingpath.empty())
1015 Logging::DataStreamingEntry::clearResult()
1018 for (
auto& e : result)
1020 entryBuffer.emplace_back(std::move(e));
1025 RobotUnitDataStreaming::TimeStep
1026 Logging::DataStreamingEntry::allocateResultElement()
const
1029 RobotUnitDataStreaming::TimeStep
data;
1030 data.bools.resize(numBools);
1031 data.bytes.resize(numBytes);
1032 data.shorts.resize(numShorts);
1033 data.ints.resize(numInts);
1034 data.longs.resize(numLongs);
1035 data.floats.resize(numFloats);
1036 data.doubles.resize(numDoubles);
1040 RobotUnitDataStreaming::TimeStep
1041 Logging::DataStreamingEntry::getResultElement()
1044 if (entryBuffer.empty())
1046 return allocateResultElement();
1048 auto e = std::move(entryBuffer.back());
1049 entryBuffer.pop_back();
1062 auto&
data = result.emplace_back(getResultElement());
1064 data.iterationId = e.iteration;
1065 data.timestampUSec =
1067 data.timesSinceLastIterationUSec = e.timeSinceLastIteration.toMicroSeconds();
1078 using enum_t = Logging::DataStreamingEntry::ValueT;
1086 val.getDataFieldAs(fidx, b);
1090 val.getDataFieldAs(fidx,
data.bytes.at(out.
idx));
1093 val.getDataFieldAs(fidx,
data.shorts.at(out.
idx));
1096 val.getDataFieldAs(fidx,
data.ints.at(out.
idx));
1099 val.getDataFieldAs(fidx,
data.longs.at(out.
idx));
1102 val.getDataFieldAs(fidx,
data.floats.at(out.
idx));
1105 val.getDataFieldAs(fidx,
data.doubles.at(out.
idx));
1107 case enum_t::Skipped:
1137 auto&
data = result.back();
1138 const OutVal& o = ctrlDevs.at(didx).at(vidx).at(fidx);
1143 Logging::DataStreamingEntry::processSens(
const SensorValueBase& val,
1152 auto&
data = result.back();
1153 const OutVal& o = sensDevs.at(didx).at(fidx);
1158 Logging::DataStreamingEntry::send(
const RobotUnitDataStreaming::ReceiverPrx& r,
1159 std::uint64_t msgId)
1164 updateCalls.emplace_back(r->begin_update(result,
static_cast<Ice::Long>(msgId)));
1169 <<
"\n update " << (start_clear - start_send).toMilliSecondsDouble()
1171 <<
"\n clear " << (end - start_clear).toMilliSecondsDouble() <<
"ms";
1175 for (; i < updateCalls.size(); ++i)
1179 if (!updateCalls.at(i)->isCompleted())
1183 r->end_update(updateCalls.at(i));
1184 connectionFailures = 0;
1189 ++connectionFailures;
1190 if (connectionFailures > rtStreamMaxClientErrors)
1192 stopStreaming =
true;
1194 << connectionFailures <<
" iterations! Removing receiver";
1195 updateCalls.clear();
1200 if (!updateCalls.empty())
1202 updateCalls.erase(updateCalls.begin(), updateCalls.begin() + i);