2#include "Components/WindowComponent.h"
3#include "Systems/DataSetSystem.h"
4#include "SwathPathResamplingPositions.h"
9#define VERBOSE_WRAP(a) do ; while(0)
11bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::clear(
float spacing,
float maxPathUpsample)
13 this->spacing = spacing;
14 this->maxPathUpsample = std::max(1.f, maxPathUpsample);
18 auto N = entries.count();
20 if (N != 0) { VERBOSE_WRAP(std::cerr <<
"Removed all entities [clear]\n"); }
25bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::retireEvictedSlices(int64_t validTimeStart)
28 while (!entries.empty() && (entries.front().bufferTime < validTimeStart)) {
29 VERBOSE_WRAP(std::cerr <<
"Popped " << entries.frontIndex() <<
":" << entries.front().bufferIndex <<
"[retireEvict]\n");
36bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::seedIfQueueEmpty(
const Config& config,
const DataSetBuffers& buffer)
38 if (!entries.empty())
return false;
43 bool isResampling = spacing != 0.f;
44 float fractional = isResampling ? 1.f : 0.f;
45 auto ix = (buffer.sliceBegin + buffer.sliceCount - (isResampling ? 2 : 1)) % config.capacity;
47 entries.pushBack(Entry{ buffer.timestamps[ix], ix, fractional });
48 VERBOSE_WRAP(std::cerr <<
"pushBack: " << entries.backIndex() <<
": ix=" << ix <<
", t=" << fractional <<
"[seed]\n");
55bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::trimEntries()
58 while (maxSlices < entries.count()) {
59 VERBOSE_WRAP(std::cerr <<
"Popped " << entries.frontIndex() <<
":" << entries.front().bufferIndex <<
" [trimEntries]\n");
67bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::includeMostRecentSlices(
const Config& config,
const DataSetBuffers& buffer)
69 assert(!entries.empty());
71 auto sliceHead1 = (buffer.sliceBegin + buffer.sliceCount - 1u) % config.capacity;
74 if (spacing == 0.0f) {
76 while (entries.back().bufferIndex != sliceHead1)
78 auto ix = (entries.back().bufferIndex + 1) % config.capacity;
79 entries.pushBack(Entry{ buffer.timestamps[ix], ix, 0.0f });
80 VERBOSE_WRAP(std::cerr <<
"pushBack: " << entries.backIndex() <<
": ix=" << ix <<
", t=0.0 [includeMostRecentSlices]\n");
87 assert(entries.back().bufferIndex != sliceHead1);
90 auto ep = entryPosition(config, buffer, entries.backIndex());
91 auto currPos = ep.first;
92 auto distanceToCover = std::max(ep.second/maxPathUpsample, spacing);
93 for (uint32_t k = 0; k < maxSliceSkip; k++) {
94 auto currIx = (entries.back().bufferIndex + k) % config.capacity;
95 if (currIx == sliceHead1) {
98 auto nextIx = (entries.back().bufferIndex + k + 1) % config.capacity;
100 auto distanceToNextSlice = glm::distance(currPos, buffer.metaPings[nextIx].vesselPositionGlobal);
101 if (distanceToCover < distanceToNextSlice) {
104 if (entries.back().bufferIndex == currIx) {
105 auto distBetweenSlices = distanceToNextSlice / (1 - entries.back().fractional);
106 fractional = entries.back().fractional + distanceToCover / distBetweenSlices;
109 fractional = distanceToCover / distanceToNextSlice;
111 assert(fractional - 1e-5f < 1.f);
112 entries.pushBack(Entry{ buffer.timestamps[currIx], currIx, fractional });
113 VERBOSE_WRAP(std::cerr <<
"pushBack: " << entries.backIndex() <<
": ix=" << currIx <<
", t=" << fractional <<
"[includeMostRecentSlices]\n");
117 distanceToCover -= distanceToNextSlice;
121 auto forceIx = (entries.back().bufferIndex + maxSliceSkip - 1) % config.capacity;
122 entries.pushBack(Entry{ buffer.timestamps[forceIx], forceIx, 0.0 });
123 VERBOSE_WRAP(std::cerr <<
"pushBack: " << entries.backIndex() <<
": ix=" << forceIx <<
", t=0.f" <<
"[includeMostRecentSlices, forced]\n");
135std::pair<glm::vec3, float> Cogs::Core::EchoSounder::SwathPathResamplingPositions::entryPosition(
const Config& config,
const DataSetBuffers& buffer, uint32_t entryIx)
137 auto bufferIx = entries[entryIx].bufferIndex;
138 const auto & pc = buffer.metaPings[bufferIx].vesselPositionGlobal;
139 const auto & pn = buffer.metaPings[(bufferIx + 1) % config.capacity].vesselPositionGlobal;
140 return std::make_pair(glm::mix(pc, pn, entries[entryIx].fractional), glm::distance(pc, pn));
145bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::includeLessRecentSlices(
const Config& config,
const DataSetBuffers& buffer, int64_t validTimeStart)
147 assert(!entries.empty());
150 if (spacing == 0.0f) {
152 while ((entries.count() < maxSlices) && (entries.front().bufferIndex != buffer.sliceBegin))
154 auto ix = (entries.front().bufferIndex - 1u + config.capacity) % config.capacity;
155 if (buffer.timestamps[ix] < validTimeStart)
break;
156 entries.pushFront(Entry{ buffer.timestamps[ix], ix, 0.0f });
157 VERBOSE_WRAP(std::cerr <<
"pushFront: " << entries.frontIndex() <<
": ix=" << ix <<
", t=0.0 [includeLessRecentSlices]\n");
164 while (entries.count() < maxSlices) {
165 auto ep = entryPosition(config, buffer, entries.frontIndex());
166 auto currPos = ep.first;
167 auto distanceToCover = std::max(ep.second / maxPathUpsample, spacing);
168 auto currIx = entries.front().bufferIndex;
169 for (uint32_t k = 0; k < maxSliceSkip; k++) {
170 auto nextIx = (entries.front().bufferIndex - k + config.capacity) % config.capacity;
172 if (((currIx == buffer.sliceBegin) && (currIx != nextIx)) || (buffer.timestamps[nextIx] < validTimeStart) ) {
176 auto distanceToNextSlice = glm::distance(currPos, buffer.metaPings[nextIx].vesselPositionGlobal);
177 if (distanceToCover < distanceToNextSlice) {
180 if (nextIx == entries.front().bufferIndex) {
181 auto distBetweenSlices = distanceToNextSlice / (entries.front().fractional);
182 fractional = entries.front().fractional - distanceToCover / distBetweenSlices;
185 fractional = 1.f - distanceToCover / distanceToNextSlice;
187 assert(fractional - 1e-5 <= 1.f);
188 entries.pushFront(Entry{ buffer.timestamps[nextIx], nextIx, glm::max(0.f, fractional) });
189 VERBOSE_WRAP(std::cerr <<
"pushFront: " << entries.frontIndex() <<
": ix=" << entries.front().bufferIndex <<
", t=" << entries.front().fractional <<
"[includeLessRecentSlices]\n");
196 distanceToCover -= distanceToNextSlice;
197 currPos = buffer.metaPings[currIx].vesselPositionGlobal;
202 auto forceIx = (entries.front().bufferIndex - maxSliceSkip + config.capacity + 1u) % config.capacity;
203 entries.pushFront(Entry{ buffer.timestamps[forceIx], forceIx, 0.0 });
204 VERBOSE_WRAP(std::cerr <<
"pushFront: " << entries.backIndex() <<
": ix=" << forceIx <<
", t=0.f" <<
"[includeLessRecentSlices, forced]\n");
208 for (uint32_t k = entries.front().bufferIndex; k != forceIx; k = (k - 1u) % config.capacity) {
209 assert(k != buffer.sliceBegin);
217 VERBOSE_WRAP(std::cerr <<
"Done includeLessRecentSlices\n");
221void Cogs::Core::EchoSounder::SwathPathResamplingPositions::printBuffer(
const Config& config,
const DataSetBuffers& buffer)
223 std::stringstream bufferIndexes;
224 std::stringstream bufferTimes;
225 bufferIndexes << buffer.sliceBegin;
226 bufferTimes << buffer.timestamps[buffer.sliceBegin];
228 auto sliceTimeFirst = buffer.timestamps[buffer.sliceBegin];
229 for (uint32_t i = 1; i < buffer.sliceCount; ++i) {
230 auto index = (buffer.sliceBegin + i) % config.capacity;
231 auto sliceTimeSecond = buffer.timestamps[index];
232 assert(sliceTimeSecond >= sliceTimeFirst);
233 bufferIndexes <<
" " << index;
234 bufferTimes <<
" " << buffer.timestamps[index];
235 sliceTimeFirst = sliceTimeSecond;
238 VERBOSE_WRAP(std::cerr <<
"Buffer indexes " << bufferIndexes.str() << std::endl);
239 VERBOSE_WRAP(std::cerr <<
"Buffer time " << bufferTimes.str() << std::endl);
243bool Cogs::Core::EchoSounder::SwathPathResamplingPositions::update(
const WindowComponent* winComp,
244 const DataSetComponent* ,
245 const DataSetData* dataData)
247 const auto & config = dataData->persistent->config;
248 const auto & buffer = dataData->persistent->buffer;
260 uint32_t bufferFrontNew = buffer.sliceBegin;
261 uint32_t bufferBackNew = buffer.sliceBegin + buffer.sliceCount;
262 uint32_t dataSetClearGenNew = dataData->clearGen;
265 if ((bufferFrontNew == bufferFront) && (bufferBackNew == bufferBack) && (dataSetClearGenNew == dataSetClearGen))
return false;
266 bufferFront = bufferFrontNew;
267 bufferBack = bufferBackNew;
269 bool clearedNonEmpty =
false;
270 if (dataSetClearGen != dataSetClearGenNew) {
271 auto count = entries.count();
273 dataSetClearGen = dataSetClearGenNew;
274 VERBOSE_WRAP(std::cerr <<
"Cleared " << count <<
" entites due to data set cleared " << dataSetClearGenNew << std::endl);
275 clearedNonEmpty = count != 0;
278 if (buffer.sliceCount < 2) {
279 auto count = entries.count();
281 VERBOSE_WRAP(std::cerr <<
"Cleared " << count <<
" entites due to sliceCount " << buffer.sliceCount << std::endl);
282 return count != 0 || clearedNonEmpty;
286 VERBOSE_WRAP(std::cerr <<
"start resample update " << std::endl);
287 if (buffer.sliceCount < 50) {
288 printBuffer(config, buffer);
290 VERBOSE_WRAP(std::cerr <<
"Num entries " << entries.count() << std::endl);
293 if (entries.count() > 0) {
294 assert(buffer.timestamps[(buffer.sliceBegin + buffer.sliceCount - 1) % config.capacity] > entries.back().bufferTime &&
"got older slices than current resample path");
299 bool rv0 = retireEvictedSlices(std::max(buffer.timestamps[buffer.sliceBegin], winComp->tail));
300 bool rv1 = seedIfQueueEmpty(config, buffer);
301 bool rv2 = includeMostRecentSlices(config, buffer);
304 if (maxSlices < entries.count()) {
307 else if (entries.count() < maxSlices) {
308 rv4 = includeLessRecentSlices(config, buffer, std::max(buffer.timestamps[buffer.sliceBegin], winComp->tail));
311 bool rv = rv0 || rv1 || rv2 || rv3 || rv4;
315 auto tsBufferBegin = buffer.timestamps[buffer.sliceBegin] - 1;
316 auto tsBufferEnd = buffer.timestamps[(buffer.sliceBegin + buffer.sliceCount - 1) % config.capacity] + 1;
320 VERBOSE_WRAP(std::cerr <<
"--- SamplingPositions"
325 <<
" r4=" << rv4 <<
"\n");
327 std::string entriesStr =
"";
328 for (
auto i = entries.frontIndex(); i != entries.backIndex() + 1; i++) {
329 entriesStr +=
"{ix = " + std::to_string(entries[i].bufferIndex) +
", frac = " + std::to_string(entries[i].fractional) +
"}";
331 VERBOSE_WRAP(std::cerr <<
"Entries = " << entriesStr << std::endl);
332 auto tsPreviousEntry = tsBufferBegin;
334 for (
auto i = entries.frontIndex(); i != entries.backIndex() + 1; i++) {
335 VERBOSE_WRAP(std::cerr << i <<
": {ix=" << entries[i].bufferIndex <<
", frac=" << entries[i].fractional
336 <<
", ts=" << entries[i].bufferTime <<
"}\n");
337 auto tsCurrentIndex = buffer.timestamps[entries[i].bufferIndex];
340 assert(tsBufferBegin < tsCurrentIndex);
341 assert(tsCurrentIndex < tsBufferEnd);
343 if (spacing == 0.0f) {
344 assert(entries[i].fractional == 0.0f);
348 auto tsNextIndex = buffer.timestamps[(entries[i].bufferIndex + 1) % config.capacity];
350 assert(tsBufferBegin < tsNextIndex);
351 assert(tsNextIndex < tsBufferEnd);
354 assert(tsCurrentIndex < tsNextIndex);
356 auto tsCurrentEntry = tsCurrentIndex + (int64_t)(entries[i].fractional*(tsNextIndex - tsCurrentIndex));
358 assert(tsPreviousEntry <= tsCurrentEntry);
360 tsPreviousEntry = tsCurrentEntry;
364 assert(n == entries.count());
365 VERBOSE_WRAP(std::cerr <<
"Done update" << std::endl);