• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • Compute Graph Framework SDK Reference  5.10
    All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
    dwSensorDrainerTemplate.hpp
    Go to the documentation of this file.
    1
    2// This code contains NVIDIA Confidential Information and is disclosed
    3// under the Mutual Non-Disclosure Agreement.
    4//
    5// Notice
    6// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
    7// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
    8// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
    9// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
    10//
    11// NVIDIA Corporation assumes no responsibility for the consequences of use of such
    12// information or for any infringement of patents or other rights of third parties that may
    13// result from its use. No license is granted by implication or otherwise under any patent
    14// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
    15// expressly authorized by NVIDIA. Details are subject to change without notice.
    16// This code supersedes and replaces all information previously supplied.
    17// NVIDIA Corporation products are not authorized for use as critical
    18// components in life support devices or systems without express written approval of
    19// NVIDIA Corporation.
    20//
    21// Copyright (c) 2020-2022 NVIDIA Corporation. All rights reserved.
    22//
    23// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
    24// rights in and to this software and related documentation and any modifications thereto.
    25// Any use, reproduction, disclosure or distribution of this software and related
    26// documentation without an express license agreement from NVIDIA Corporation is
    27// strictly prohibited.
    28//
    30#ifndef DWFRAMEWORK_DWNODES_SENSORS_DWSENSORNODE_DWSENSORDRAINERTEMPLATE_HPP_
    31#define DWFRAMEWORK_DWNODES_SENSORS_DWSENSORNODE_DWSENSORDRAINERTEMPLATE_HPP_
    32
    43#include <dw/core/base/Types.h>
    44#include <dw/sensors/Sensors.h>
    45#include <dw/sensors/canbus/CAN.h>
    46#include <dw/sensors/radar/Radar.h>
    47#include <dwcgf/Exception.hpp>
    48#include <dwcgf/node/Node.hpp>
    49#include <memory>
    50#include <unistd.h>
    51#if defined(DW_SDK_BUILD_EXPERIMENTAL) && defined(LINUX)
    52#include <dwexperimental/sensors/lockstep/Lockstep.h>
    53#include <dwexperimental/sensors/Sensors.h>
    54#endif
    55
    56namespace dw
    57{
    58namespace framework
    59{
    60
    62{
    63 const char* nodeName;
    64 dwTime_t blockingTimeout; // Blocking timeout must be > 1/f_sensor
    65 dwTime_t nonBlockingTimeout; // Nonblocking timeout must be < 1/f_sensor
    66 bool isVirtual; // true if this sensor reads from dataset
    67 bool autoReset; // true to reset the sensor at the end of stream (for playback loop option)
    68 bool drainStaleData; // true if drainer should read from sensor until DW SAL is empty
    69 bool waitForNewData; // true if drainer should block until new data is available
    71 const char* frameReadMask;
    72};
    73
    74template <typename ProcessedDataType, typename ReadProcessedDataFunc, typename DataSourceType>
    76{
    77public:
    78 static constexpr char LOG_TAG[] = "dwBaseDrainerTemplate";
    79
    80 // WAR: This is a guard for drain out sensor data, avoid huge sensor data make too long loop time, eg: drain out can msg > 100 ms, current find 50 is good enough
    81 static constexpr int32_t DRAIN_SENSOR_DATA_COUNT_MAX = 50;
    82 using OnDataDropped = dw::core::Function<void(dwTime_t const)>;
    83
    84 explicit dwBaseDrainerTemplate(dwSensorDrainerParams params, std::unique_ptr<ReadProcessedDataFunc> readProcessedDataFunc, DataSourceType dataSource)
    85 : m_dataSource(dataSource)
    86 , m_name(params.nodeName)
    87 , m_blockingTimeout(params.blockingTimeout)
    88 , m_nonBlockingTimeout(params.nonBlockingTimeout)
    89 , m_isVirtual(params.isVirtual)
    90 , m_dropStaleData(params.drainStaleData)
    91 , m_waitForNewData(params.waitForNewData)
    92 , m_readProcessedDataFunc(std::move(readProcessedDataFunc))
    93 , m_frameReadMask(params.frameReadMask)
    94 , m_isLockstep(params.isLockstep)
    95 {
    96 if (m_frameReadMask.size() > 0)
    97 {
    98 m_frameSkipEnabled = true;
    99 }
    100 }
    101
    102 void setOnDataDropped(OnDataDropped onDataDropped)
    103 {
    104 m_onDataDropped = onDataDropped;
    105 }
    106
    107 virtual dwStatus getNextTimestamp(dwTime_t& timestamp, dwTime_t timeout)
    108 {
    109 // If dwSensor_getNextTimestamp API not available, get timestamp by looking ahead in dataset
    110 if (!m_nextDataReady)
    111 {
    113 {
    114 dwStatus status = m_readProcessedDataFunc->readNextData(timeout, m_dataSource);
    115 if (status != DW_SUCCESS)
    116 {
    117 m_nextDataReady = false;
    118 return status;
    119 }
    120 m_framesRead++;
    121 m_nextDataReady = true;
    122 }
    123 else
    124 {
    125 auto ret = readNextWithFrameMask(timeout);
    126 if (ret != DW_SUCCESS)
    127 {
    128 return ret;
    129 }
    130 }
    131 }
    132
    133 return m_readProcessedDataFunc->getNextDataTimestamp(timestamp);
    134 }
    135
    136 virtual dwStatus getNextData(ProcessedDataType* outFrame, dwTime_t timeout)
    137 {
    138 if (!m_nextDataReady)
    139 {
    141 {
    142 // Do the read here if look ahead did not happen
    143 dwStatus status = m_readProcessedDataFunc->readNextData(timeout, m_dataSource);
    144 if (status != DW_SUCCESS)
    145 {
    146 DW_LOGE << "getNextData: readNextData error!" << Logger::State::endl;
    147 m_nextDataReady = false;
    148 return status;
    149 }
    150 m_framesRead++;
    151 m_nextDataReady = true;
    152 }
    153 else
    154 {
    155 auto ret = readNextWithFrameMask(timeout);
    156 if (ret != DW_SUCCESS)
    157 {
    158 DW_LOGE << "getNextData: readNextData error!" << Logger::State::endl;
    159 return ret;
    160 }
    161 }
    162 }
    163 return m_readProcessedDataFunc->getNextData(outFrame, m_dataSource);
    164 }
    165
    166 dwStatus readNextWithFrameMask(dwTime_t timeout)
    167 {
    168 // Keep reading until a valid frame is found (1 in the frame mask)
    169 do
    170 {
    171 dwStatus status = m_readProcessedDataFunc->readNextData(timeout, m_dataSource);
    172 if (status != DW_SUCCESS)
    173 {
    174 m_nextDataReady = false;
    175 return status;
    176 }
    177 m_framesRead++;
    178 m_nextDataReady = true;
    179 } while (m_frameReadMask[(m_framesRead - 1) % m_frameReadMask.size()] == '0');
    180
    181 return DW_SUCCESS;
    182 }
    183
    184 virtual dwStatus tryRead(ProcessedDataType* outFrame,
    185 dwTime_t& latestTimestamp,
    186 dwTime_t timeout,
    187 bool isDroppingData = false)
    188 {
    189 dwStatus status = DW_FAILURE;
    190 dwTime_t nextTime{};
    192 {
    194 {
    195 return DW_TIME_OUT;
    196 }
    197 nextTime = m_stashedNextTime;
    199 }
    200 else
    201 {
    202 dwStatus status = getNextTimestamp(nextTime, timeout);
    203 if (status != DW_SUCCESS)
    204 {
    205 return status;
    206 }
    207 }
    208
    209 // Check if next data is ready. If not, mimic Live Sensor DW SAL buffer empty with a DW_TIME_OUT
    210 if (m_isVirtual && !isVirtualDataReady(nextTime, timeout))
    211 {
    212 m_stashedNextTime = nextTime;
    213 return DW_TIME_OUT;
    214 }
    215
    216 status = getNextData(outFrame, timeout);
    217 if (status != DW_SUCCESS)
    218 {
    219 DW_LOGE << "tryRead: getNextData error!" << Logger::State::endl;
    220 return status;
    221 }
    222
    223 if (isDroppingData)
    224 {
    225 DW_LOGW << m_name << " Dropping data" << Logger::State::endl;
    226 if (m_onDataDropped)
    227 {
    228 m_onDataDropped(latestTimestamp);
    229 }
    230 }
    231
    232 latestTimestamp = nextTime;
    233 m_nextDataReady = false;
    234 m_outputAvailable = true;
    235
    236 return status;
    237 }
    238
    239 virtual dwStatus reset()
    240 {
    242 m_nextDataReady = false;
    244 return DW_SUCCESS;
    245 }
    246
    247 virtual dwTime_t getReadTimeout() const
    248 {
    250 }
    251
    252 virtual void setVirtualSyncTime(dwTime_t virtualSyncTime)
    253 {
    254 m_virtualSyncTime = virtualSyncTime;
    255 }
    256
    258 {
    260 }
    261
    262 // This function is original designed for mimicing real time live sensors for non-determinisitc mode.
    263 // But now removed the sleep before return as deterministic mode is the only supported dataset mode.
    264 // Returns true if the next sensor data should be available
    265 virtual bool isVirtualDataReady(dwTime_t dataTime, dwTime_t timeout)
    266 {
    268 {
    269 if (dataTime <= m_virtualSyncTime)
    270 {
    271 return true;
    272 }
    273 return false;
    274 }
    275
    276 dwTime_t timeToNextData = dataTime - m_virtualSyncTime;
    277
    278 // For dataset, the first frame's m_virtualSyncTime is 0. Return true directly and set m_virtualSyncTime = -1
    279 // so that the second round tryRead will return DW_TIME_OUT and use the first frame.
    280 if (m_virtualSyncTime == 0)
    281 {
    282 // WAR, fix this
    284 return true;
    285 }
    286 if (timeToNextData >= timeout)
    287 {
    288 // Next sensor data is far in the future. Timeout specified not sufficient to reach next sensor data
    289 // Technically, we should still usleep(timeout) to mimic live sensor, but can skip this for perf
    290 // TODO(Oven): WAR to guarantee some data must be read when timeout is m_blockingTimeout,
    291 // otherwise we may send out uninitialized sensor data to downstreams
    292 if (timeout == m_blockingTimeout)
    293 {
    294 DW_LOGD << "isVirtualDataReady: timeToNextData is larger than m_blockingTimeout, must read some data. "
    295 << "timeToNextData: " << timeToNextData << ", dataTime: " << dataTime << Logger::State::endl;
    296 }
    297 else
    298 {
    299 return false;
    300 }
    301 }
    302 if (timeToNextData <= 0)
    303 {
    304 // Next sensor data is in the past. Should be available.
    305 return true;
    306 }
    307 return true;
    308 }
    309
    310 // Utility to read Sensor data from DW SAL in a consistent way across live/virtual sensor
    311 // May block on new sensor data, or drop stale data. See dwSensorDrainerParams
    312 // Retuns DW_SUCCESS if processedOutput and timestampOutput is valid
    313 // nextTimestampOutput will always be valid for virtual case
    314 //
    315 // [out] processedOutput the latest valid sensor frame
    316 // [out] timestampOutput timestamp associated with the latest valid sensor frame
    317 // [out] nextTimestampOutput timestamp associated with the next sensor frame. Only available in virtual case
    318 // [in] virtualSyncTime current timestamp to decide whether virtual data is ready to be sent
    319 // [in] sensor handle to sensor
    320 virtual dwStatus drainProcessedData(ProcessedDataType* processedOutput,
    321 dwTime_t& timestampOutput,
    322 dwTime_t& nextTimestampOutput,
    323 dwTime_t virtualSyncTime)
    324 {
    325 m_virtualSyncTime = virtualSyncTime;
    326
    327 dwStatus status = DW_SUCCESS;
    328 m_outputAvailable = false;
    329
    330 // Blocking read guarantees some data is read, and slows processing down to data rate
    331 dwTime_t readTimeout = getReadTimeout();
    332 int32_t drainCount = 0;
    333
    334 // For determinisitic mode, camera/radar/imugps will always return available frame at the first loop with longer readTimeout.
    335 // They will return DW_TIME_OUT with shorter m_nonBlockingTimeout to guarentee deterministic for each frame at second loop.
    336 // Note: This do-while has different behavior when reach EndOfStream for flag m_dropStaleData. Assume dataset has 0~100 frames.
    337 // If true, the first loop will read frame 100 successfully. Then enter the second loop and hit EndOfStream. It will reset
    338 // the sensor and tryRead again. Which means it will return frame 0 and drop frame 100. Later, getNextTimestamp will return
    339 // frame 1's timestamp. So the final result is: processedOutput = frame 0, nextTimestampOutput = frame 1' timestamp
    340 // If false, the first loop will read frame 100 successfully and exit do-while loop directly. Later, nextTimestampOutput is
    341 // reset to 0 and failed getNextTimestamp. So the final result is: processedOutput = frame 100, nextTimestampOutput = 0
    342 do
    343 {
    344 status = readProcessedData(processedOutput, timestampOutput, readTimeout, drainCount > 0);
    345 // Non-blocking read and drop stale data to drain the DW SAL buffer, send newest available data
    346 readTimeout = m_nonBlockingTimeout;
    347
    348#if defined(DW_SDK_BUILD_EXPERIMENTAL) && defined(LINUX)
    349 isLockstepDataAvailable(status, readTimeout);
    350#endif
    351 } while (status == DW_SUCCESS && m_dropStaleData && (drainCount++ < DRAIN_SENSOR_DATA_COUNT_MAX));
    352
    354 {
    355 DW_LOGE << m_name << " blockingTimeout not sufficient to successfully waitForNewData. No data available!" << Logger::State::endl;
    356 }
    357 else if (status == DW_TIME_OUT && m_outputAvailable)
    358 {
    359 // DW_TIME_OUT indicates that DW SAL has been successfully drained
    360 status = DW_SUCCESS;
    361 }
    362
    363 populateNextTimestamp(nextTimestampOutput);
    364 return status;
    365 }
    366
    367 virtual dwStatus readProcessedData(ProcessedDataType* outFrame, dwTime_t& latestTimestamp, dwTime_t timeout, bool isDroppingData = false) = 0;
    368
    369 virtual void isLockstepDataAvailable(dwStatus& status, dwTime_t& readTimeout) {}
    370
    371 void populateNextTimestamp(dwTime_t& nextTimestampOutput)
    372 {
    374 {
    375 // In virtual case, send out the timestamp of next sensor data
    376 nextTimestampOutput = 0;
    377 const dwStatus nextTimeStatus = getNextTimestamp(nextTimestampOutput, m_blockingTimeout);
    378 if (nextTimeStatus != DW_SUCCESS)
    379 {
    380 DW_LOGD << m_name << " Failed to get next timestamp: " << dwGetStatusName(nextTimeStatus);
    381 }
    382 }
    383 }
    384
    385protected:
    386 DataSourceType m_dataSource;
    387
    388 std::unique_ptr<ReadProcessedDataFunc> m_readProcessedDataFunc;
    389
    390 dwTime_t m_blockingTimeout = 60000;
    391 dwTime_t m_nonBlockingTimeout = 100;
    392 dwTime_t m_virtualSyncTime = 0;
    393 dwTime_t m_stashedNextTime = -1;
    395 bool m_outputAvailable = false;
    396 bool m_nextDataReady = false;
    397 bool m_isVirtual = false;
    398 bool m_dropStaleData = false;
    399 bool m_waitForNewData = false;
    400 bool m_frameSkipEnabled = false;
    401 uint32_t m_framesRead = 0;
    402 FixedString<32> m_frameReadMask;
    403 bool m_isLockstep = false;
    405
    407
    408 static constexpr dwTime_t REPLAY_SENSOR_READ_TIMEOUT = 10000000;
    409};
    410
    411template <typename ProcessedDataType, typename ReadProcessedDataFunc>
    412class dwSensorDrainerTemplate : public dwBaseDrainerTemplate<ProcessedDataType, ReadProcessedDataFunc, dwSensorHandle_t>
    413{
    414public:
    415 static constexpr char LOG_TAG[] = "dwSensorDrainerTemplate";
    417
    418 explicit dwSensorDrainerTemplate(dwSensorDrainerParams params, std::unique_ptr<ReadProcessedDataFunc> readProcessedDataFunc, dwSensorHandle_t hsensor)
    419 : dwBaseDrainerTemplate<ProcessedDataType, ReadProcessedDataFunc, dwSensorHandle_t>(params, std::move(readProcessedDataFunc), hsensor), m_autoReset(params.autoReset), m_isLockstep(params.isLockstep)
    420 {
    421 }
    422
    423 virtual ~dwSensorDrainerTemplate() = default;
    424
    425 dwStatus getNextTimestamp(dwTime_t& timestamp,
    426 dwTime_t timeout) override
    427 {
    428#if defined(DW_SDK_BUILD_EXPERIMENTAL) && defined(LINUX)
    430 {
    431 dwStatus nextStatus = dwSensor_getNextTimestamp(&timestamp, Base::m_dataSource);
    432 if (nextStatus == DW_SUCCESS || nextStatus == DW_END_OF_STREAM)
    433 {
    434 return nextStatus;
    435 }
    436 }
    437#endif
    438
    439 return Base::getNextTimestamp(timestamp, timeout);
    440 }
    441
    442 virtual dwStatus reset() override
    443 {
    444 dwStatus res = Base::reset();
    445 if (res != DW_SUCCESS)
    446 {
    447 return res;
    448 }
    449 return dwSensor_reset(Base::m_dataSource);
    450 }
    451
    452 // Reads a piece of sensor data from sensor
    453 // In virtual sensor case, uses m_virtualSyncTime and timeout to determine
    454 // whether next piece of sensor data should be available
    455 //
    456 // [out] outFrame output sensor frame
    457 // [in/out] latestTimestamp timestamp associated with the sensor frame
    458 // [in] timeout sensor reading timeout in microseconds
    459 // [in] isDroppingData indicates if data is being dropped
    460 dwStatus readProcessedData(ProcessedDataType* outFrame,
    461 dwTime_t& latestTimestamp,
    462 dwTime_t timeout,
    463 bool isDroppingData = false) override
    464 {
    465 dwStatus status = Base::tryRead(outFrame, latestTimestamp, timeout, isDroppingData);
    466 if (status == DW_END_OF_STREAM && m_autoReset)
    467 {
    468 // Reset the sensor and try to read again, but propagate the DW_END_OF_STREAM
    469 // Use blocking read after reset since camera prefetch may not be ready
    470 reset();
    471 timeout = Base::m_blockingTimeout;
    472 Base::tryRead(outFrame, latestTimestamp, timeout);
    473 }
    474 return status;
    475 }
    476
    477 // Utility to drop sensor frames according to the events to be replayed
    478 // until the next non-drop event is read or there are no more replay events
    479 // @param [output] processedOutput the latest frame read from the sensor
    480 // @param [output] dataEvent the next non-drop event to be replayed.
    481 // @param [input] sensor the sensor to replay frames from
    482 // @param [input] readCb the callback to read replay events
    483 dwStatus replayDroppedFrames(ProcessedDataType* processedOutput,
    484 SensorNode::DataEvent& dataEvent,
    486 {
    487 // Process any number of drop events.
    488 bool isDropEvent;
    489 do
    490 {
    491 // Read next data event
    492 if (!readCb(dataEvent)) // no more events to be replayed
    493 {
    494 DW_LOGW << "replayDroppedFrames: Trace cannot be read." << Logger::State::endl;
    495 return DW_END_OF_STREAM;
    496 }
    497
    498 // Drop the sensor frame (if applicable)
    499 isDropEvent = dataEvent.dataEventType == SensorNode::DataEventType::DROP;
    500 if (isDropEvent)
    501 {
    502 dwTime_t timestampOutput{};
    503 dwStatus status = readProcessedData(processedOutput, timestampOutput, Base::REPLAY_SENSOR_READ_TIMEOUT);
    504 if (status == DW_END_OF_STREAM)
    505 {
    506 return status;
    507 }
    508 else if (status == DW_SUCCESS)
    509 {
    510 // For now we assume that the timestamps read from the sensor need to match the trace exactly
    511 // so if there isn't a match then there is no valid way to continue, throw an exception.
    512 if (timestampOutput != dataEvent.timestamp)
    513 {
    514 DW_LOGE << "replayDroppedFrames: Data/trace mismatch: current: " << timestampOutput << " recorded: " << dataEvent.timestamp << Logger::State::endl;
    515 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: replayDroppedFrames: data/trace mismatch.");
    516 }
    517 }
    518 else
    519 {
    520 DW_LOGE << "replayDroppedFrames: Cannot read next data." << Logger::State::endl;
    521 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: replayDroppedFrames: cannot read next data.");
    522 }
    523 }
    524 } while (isDropEvent);
    525
    526 return DW_SUCCESS;
    527 }
    528
    529 // Replay the next event for the sensor node-run.
    530 // @param [output] processedOutput the frame replayed from the sensor
    531 // @param [output] timestampOutput the timestamp of the frame replayed from the sensor
    532 // @param [input] sensor the sensor to replay frames from
    533 // @param [input] readCb the callback to read replay events
    534 virtual dwStatus replayProcessedData(ProcessedDataType* processedOutput,
    535 dwTime_t& timestampOutput,
    537 {
    538 // First drop frames according to the replay event
    539 // also, retrieve the first non-drop event.
    541 dwStatus status = replayDroppedFrames(processedOutput, de, readCb);
    542
    543 // When end of stream was reached, just read the next frame and ignore the replay event.
    544 if (status == DW_END_OF_STREAM)
    545 {
    546 readProcessedData(processedOutput, timestampOutput, Base::REPLAY_SENSOR_READ_TIMEOUT);
    547 return status;
    548 }
    549
    550 // If some unexpected status was returned from the sensor just return the status as this is an error.
    551 if (status != DW_SUCCESS)
    552 {
    553 return status;
    554 }
    555
    556 // otherwise, if no data was produced for this event, then just return the status that was recorded
    557 // (usually this is DW_NOT_AVAILABLE or DW_TIME_OUT)
    558 if (de.dataEventType == SensorNode::DataEventType::NONE)
    559 {
    560 status = de.status;
    561 }
    562 // if data was produced, read the next data from the sensor and make sure it has the timetamp we expect.
    563 else if (de.dataEventType == SensorNode::DataEventType::PRODUCE)
    564 {
    565 status = readProcessedData(processedOutput, timestampOutput, Base::REPLAY_SENSOR_READ_TIMEOUT);
    566 if (status != DW_SUCCESS && status != DW_END_OF_STREAM)
    567 {
    568 DW_LOGE << "replayProcessedData: Cannot read next data." << Logger::State::endl;
    569 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: replayProcessedData: cannot read next data.");
    570 }
    571 // For now we assume that the timestamps read from the sensor need to match the trace exactly
    572 // so if there isn't a match then there is no valid way to continue, throw an exception.
    573 if (timestampOutput != de.timestamp)
    574 {
    575 DW_LOGE << "replayProcessedData: Data/trace mismatch." << Logger::State::endl;
    576 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: replayProcessedData: data/trace mismatch.");
    577 }
    578 }
    579 else
    580 {
    581 DW_LOGE << "replayProcessedData: UnhandledEventType." << Logger::State::endl;
    582 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: unhandled event type");
    583 }
    584
    585 return status;
    586 }
    587
    588#if defined(DW_SDK_BUILD_EXPERIMENTAL) && defined(LINUX)
    589 void isLockstepDataAvailable(dwStatus& status, dwTime_t& readTimeout) override
    590 {
    592 {
    593 bool isDataAvailable = false;
    594 if (dwLockstep_isDataAvailable(&isDataAvailable, Base::m_dataSource) != DW_SUCCESS)
    595 {
    596 char8_t const* protocol;
    597 dwSensor_getProtocol(&protocol, Base::m_dataSource);
    598 throw Exception(DW_FAILURE, "dwSensorDrainerTemplate: can't get the data available flag from:", protocol, " sensor");
    599 }
    600
    601 if (!isDataAvailable && status != DW_SUCCESS)
    602 {
    603 status = DW_TIME_OUT;
    604 }
    605 else
    606 {
    607 status = DW_SUCCESS;
    608 readTimeout = Base::m_blockingTimeout;
    609 }
    610 }
    611 }
    612#endif
    613
    614protected:
    615 bool m_autoReset = false;
    616 bool m_isLockstep = false;
    617};
    618
    619template <typename ProcessedDataType, typename ReadProcessedDataFunc, typename DataSourceType>
    621
    622template <typename ProcessedDataType, typename ReadProcessedDataFunc>
    624} // namespace framework
    625} // namespace dw
    626
    627#endif // DWFRAMEWORK_DWNODES_SENSORS_DWSENSORNODE_DWSENSORDRAINERTEMPLATE_HPP_
    FixedString< MAX_NAME_LEN > Name_t
    Definition: Node.hpp:68
    ISensorNode::DataEventReadCallback DataEventReadCallback
    Definition: Node.hpp:398
    void populateNextTimestamp(dwTime_t &nextTimestampOutput)
    virtual dwStatus tryRead(ProcessedDataType *outFrame, dwTime_t &latestTimestamp, dwTime_t timeout, bool isDroppingData=false)
    static constexpr int32_t DRAIN_SENSOR_DATA_COUNT_MAX
    void setOnDataDropped(OnDataDropped onDataDropped)
    dw::core::Function< void(dwTime_t const)> OnDataDropped
    virtual dwStatus getNextTimestamp(dwTime_t &timestamp, dwTime_t timeout)
    virtual dwStatus getNextData(ProcessedDataType *outFrame, dwTime_t timeout)
    virtual void setLockstepDeterministicMode(bool enable)
    dwBaseDrainerTemplate(dwSensorDrainerParams params, std::unique_ptr< ReadProcessedDataFunc > readProcessedDataFunc, DataSourceType dataSource)
    virtual dwStatus drainProcessedData(ProcessedDataType *processedOutput, dwTime_t &timestampOutput, dwTime_t &nextTimestampOutput, dwTime_t virtualSyncTime)
    virtual void setVirtualSyncTime(dwTime_t virtualSyncTime)
    virtual bool isVirtualDataReady(dwTime_t dataTime, dwTime_t timeout)
    virtual void isLockstepDataAvailable(dwStatus &status, dwTime_t &readTimeout)
    std::unique_ptr< ReadProcessedDataFunc > m_readProcessedDataFunc
    virtual dwStatus readProcessedData(ProcessedDataType *outFrame, dwTime_t &latestTimestamp, dwTime_t timeout, bool isDroppingData=false)=0
    static constexpr dwTime_t REPLAY_SENSOR_READ_TIMEOUT
    dwStatus readNextWithFrameMask(dwTime_t timeout)
    dwStatus readProcessedData(ProcessedDataType *outFrame, dwTime_t &latestTimestamp, dwTime_t timeout, bool isDroppingData=false) override
    dwSensorDrainerTemplate(dwSensorDrainerParams params, std::unique_ptr< ReadProcessedDataFunc > readProcessedDataFunc, dwSensorHandle_t hsensor)
    virtual dwStatus replayProcessedData(ProcessedDataType *processedOutput, dwTime_t &timestampOutput, SensorNode::DataEventReadCallback readCb)
    dwStatus getNextTimestamp(dwTime_t &timestamp, dwTime_t timeout) override
    dwStatus replayDroppedFrames(ProcessedDataType *processedOutput, SensorNode::DataEvent &dataEvent, SensorNode::DataEventReadCallback readCb)
    Definition: Buffer.hpp:40
    人人超碰97caoporen国产