### Modern C++20 Application Structure Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Presents a complete application example integrating various C++20 features like designated initializers, concepts, and coroutines within a builder pattern for configuration. This showcases a modern, robust approach to building the pedestrian detection system. Requires 'ModernCpp20Application.h'. ```cpp #include "App/inc/ModernCpp20Application.h" using namespace pedestrian_detection::modern; int main() { // Create application with designated initializers auto config = ModernConfiguration{ .detectionConfig = { .hitThreshold = 0.6f, .scaleFactor = 1.1f, .minNeighbors = 3 }, .enableLogging = true, .frameInterval = std::chrono::milliseconds{33}, .maxDetectionResults = 20 }; // Build application using builder pattern auto app = ApplicationBuilder{} .withDetectionConfig(config.detectionConfig) .withFrameInterval(std::chrono::milliseconds{50}) .withMaxDetections(15) .withLogging(true) .build(); // Initialize and start if (auto error = app->initialize()) { std::println("Failed to initialize: {}", constants::getErrorDescription(*error)); return -1; } // Start async processing auto startTask = app->startAsync(); // Get formatted statistics std::println("{}", app->getFormattedStatistics()); return 0; } ``` -------------------------------- ### Logging with std::format in C++ Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Demonstrates using std::format and std::println for modern, type-safe formatted output in C++. It iterates through detection results, logging individual detections and a summary. Requires C++23 for std::println. ```cpp #include #include // C++23 preview void logDetectionResults(const std::vector& results) { // Modern formatted output std::println("Detection Results:"); for (const auto& [index, result] : std::views::enumerate(results)) { std::println(" [{}] Confidence: {:.2f}, Angle: {:.1f}°, Box: {}x{}", index, result.confidence, result.angle, result.boundingBox.width, result.boundingBox.height); } // Summary with formatting auto summary = std::format( "Summary: {} detections, avg confidence: {:.2f}", results.size(), std::ranges::fold_left(results | ranges::confidences, 0.0f, std::plus{}) / results.size() ); std::println("{}", summary); } ``` -------------------------------- ### Structured Bindings and Modern Syntax in C++ Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Illustrates the use of structured bindings for unpacking tuples and return values, along with range-based for loops and modern error handling with std::optional. This enhances code readability and simplifies data extraction. ```cpp void modernSyntaxExample() { // Structured bindings auto detectionResults = detectPedestrians(); auto [count, avgConfidence, maxAngle] = analyzeResults(detectionResults); // Range-based processing with structured bindings for (const auto& [confidence, angle, box] : detectionResults | views::transform([](const auto& det) { return std::tuple{det.confidence, det.angle, det.boundingBox}; })) { if (confidence > 0.8f) { processHighConfidenceDetection(angle, box); } } // Modern error handling if (auto result = processFrame(); result.has_value()) { auto& [detections, processingTime] = *result; logResults(detections, processingTime); } } ``` -------------------------------- ### Async Processing with C++20 Coroutines Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Implements asynchronous frame processing and streaming detection using C++20 coroutines. This allows for non-blocking operations and efficient handling of continuous data streams. Requires 'AsyncDetection.h'. ```cpp #include "Common/inc/AsyncDetection.h" using namespace pedestrian_detection::async; // Async frame processing Task> processFrameAsync() { cv::Mat frame = captureFrame(); auto service = createAsyncDetectionService(); co_return co_await service->processFrameAsync(std::move(frame)); } // Streaming detection with generator void streamingDetection() { auto service = createAsyncDetectionService(); auto frameSource = []() { return captureFrame(); }; for (auto results : service->processFrameStream(frameSource)) { // Process each detection result as it arrives std::println("Detected {} objects", results.size()); } } ``` -------------------------------- ### Concepts-Constrained Templates in C++ Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Showcases the implementation of a generic `OptimizedProcessor` class using C++20 concepts. This approach enforces compile-time constraints on template parameters, ensuring type safety and interface compliance for detection algorithms and configurations. It also demonstrates static_assert for compile-time validation. ```cpp template requires concepts::ConfigurableAlgorithm class OptimizedProcessor { public: OptimizedProcessor(Algorithm algo, Config config) : m_algorithm{std::move(algo)}, m_config{config} { // Compile-time validation static_assert(requires { config.isValid(); }); m_algorithm.configure(m_config); } auto processFrame(const cv::Mat& frame) -> std::expected, global::RC_t> { if (!frame.empty()) { return m_algorithm.detectRange(frame); } return std::unexpected(global::RC_ERROR_BAD_PARAM); } private: Algorithm m_algorithm; Config m_config; }; ``` -------------------------------- ### Performance Monitoring with Chrono in C++ Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Implements a `PerformanceMonitor` class using the C++ `` library to measure the duration of operations. It provides functionality to time arbitrary callable objects and retrieve statistics like minimum, maximum, and average execution times. Supports C++20 ranges for statistics calculation. ```cpp #include class PerformanceMonitor { public: template auto timeOperation(F&& operation) { using namespace std::chrono; auto start = high_resolution_clock::now(); auto result = std::invoke(std::forward(operation)); auto end = high_resolution_clock::now(); auto duration = duration_cast(end - start); m_measurements.push_back(duration); return std::pair{std::move(result), duration}; } auto getStatistics() const { using namespace std::ranges; if (m_measurements.empty()) return std::nullopt; auto [min, max] = minmax_element(m_measurements); auto avg = fold_left(m_measurements, std::chrono::microseconds{0}, std::plus{}) / m_measurements.size(); return std::optional{std::tuple{*min, *max, avg}}; } private: std::vector m_measurements; }; ``` -------------------------------- ### Serial Communication with UART (C++) Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Handles serial communication using a UART interface. This example demonstrates initializing UART, transmitting a custom protocol packet, and receiving data. It requires specific device paths and configures baud rate, parity, and data bits. ```cpp #include "./HAL/inc/CUart.h" #include #include #include // UART protocol packet transmission example int main() { // Initialize UART on /dev/ttyTHS1 (NVIDIA Jetson) // Raspberry Pi: /dev/ttyAMA0 or /dev/serial0 CUart uart("/dev/ttyTHS1", O_RDWR | O_NOCTTY | O_SYNC, S_IRWXU); LOG_INFO("Main", "UART initialized at 115200 baud"); // Protocol packet format: [SOP][DLC][Theta][Delta_Theta][Reserved][EOP] char txPacket[7]; txPacket[0] = 0xFA; // Start of Protocol txPacket[1] = 0x04; // Data Length Code (4 bytes payload) txPacket[2] = -15; // Theta: pedestrian at -15° from center txPacket[3] = 8; // Delta Theta: 8° angular width txPacket[4] = 0x00; // Reserved txPacket[5] = 0x00; // Reserved txPacket[6] = 0xFD; // End of Protocol // Transmit packet ssize_t bytesWritten; global::RC_t result = uart.write(txPacket, sizeof(txPacket), bytesWritten); if (result == global::RC_SUCCESS) { LOG_INFO("Main", "Transmitted " + std::to_string(bytesWritten) + " bytes"); // Print hex dump std::stringstream ss; for (int i = 0; i < bytesWritten; i++) { ss << std::hex << std::setw(2) << std::setfill('0') << (int)(unsigned char)txPacket[i] << " "; } LOG_INFO("Main", "TX: " + ss.str()); } else { LOG_ERROR("Main", "UART transmission failed"); } // Receive data from UART char rxBuffer[128]; ssize_t bytesRead; result = uart.read(rxBuffer, sizeof(rxBuffer), bytesRead); if (result == global::RC_SUCCESS && bytesRead > 0) { LOG_INFO("Main", "Received " + std::to_string(bytesRead) + " bytes"); // Parse received packet if (rxBuffer[0] == 0xFA && rxBuffer[bytesRead-1] == 0xFD) { LOG_INFO("Main", "Valid protocol packet received"); // Extract data int8_t theta = rxBuffer[2]; int8_t deltaTheta = rxBuffer[3]; LOG_INFO("Main", "Pedestrian angle: " + std::to_string(theta) + "°"); LOG_INFO("Main", "Angular width: " + std::to_string(deltaTheta) + "°"); } } else if (result == global::RC_ERROR_TIME_OUT) { LOG_WARNING("Main", "UART receive timeout"); } return 0; } ``` -------------------------------- ### Compile-time Evaluation with C++20 Constants Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Demonstrates the use of modern C++20 constants for compile-time calculations and evaluations, enhancing performance and safety. This includes trigonometric conversions, size calculations, and validation checks performed at compile time. Requires 'ModernConstants.h'. ```cpp #include "Common/inc/ModernConstants.h" using namespace pedestrian_detection::constants; // Compile-time calculations constexpr auto angleInRadians = degreesToRadians(45.0f); constexpr auto optimalSize = calculateOptimalSize(640, 480, 1.2f); // Constexpr validation static_assert(AlgorithmConstants::isValidThreshold(0.5f)); static_assert(MathUtils::calculateAngle(320, 320, 640) == 0.0f); // Runtime usage with compile-time constants void setupDetection() { auto config = IDetectionAlgorithm::DetectionConfig{ .hitThreshold = AlgorithmConstants::DEFAULT_HIT_THRESHOLD, .scaleFactor = AlgorithmConstants::DEFAULT_SCALE_FACTOR, .minNeighbors = AlgorithmConstants::DEFAULT_MIN_NEIGHBORS }; } ``` -------------------------------- ### Type Safety with C++20 Concepts Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Ensures only compatible detection algorithms are used with functions by leveraging C++20 concepts. This prevents compile-time errors by enforcing specific interfaces for template parameters. Requires the 'Concepts.h' header. ```cpp #include "Common/inc/Concepts.h" #include "Detection/inc/HOGDetectionAlgorithm.h" // Function that only accepts detection algorithms template void processWithAlgorithm(T& algorithm, const cv::Mat& frame) { auto results = algorithm.detectRange(frame); // Process results... } // Usage HOGDetectionAlgorithm hog; processWithAlgorithm(hog, frame); // ✓ Compiles // processWithAlgorithm(someOtherClass, frame); // ✗ Compile error ``` -------------------------------- ### Initialize and Run Pedestrian Detection Application in C++ Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt The main entry point for the pedestrian detection system. It initializes the logging subsystem to output messages to both the console and a file. Subsequently, it creates an instance of the CApplication class, which automatically sets up and starts all necessary service threads (camera capture, detection, communication). The main thread is kept alive indefinitely to ensure the process continues running. ```cpp #include "./App/inc/CApplication.h" #include "./Common/inc/Logger.h" #include "./global.h" int main(int argc, char** argv) { // Initialize logging subsystem Logger& logger = Logger::getInstance(); logger.addDestination(std::make_unique(true)); logger.addDestination(std::make_unique("pedestrian_detection.log")); logger.setMinLevel(LogLevel::INFO); LOG_INFO("Main", "Program Started with PID: " + std::to_string(getpid())); // Create application instance - automatically initializes all service threads CApplication pedestrian; // Start all threads (camera, detection, communication services) pedestrian.run(); // Keep main thread alive to maintain process while (1) { sleep(1); } return 0; } ``` -------------------------------- ### CSemaphore: POSIX Semaphore Wrapper for Synchronization Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt The CSemaphore class provides a C++ wrapper for POSIX semaphores, supporting both named and unnamed semaphores. It is used for thread synchronization and managing access to a finite number of resources. The example illustrates its application in a classic producer-consumer problem, coordinating buffer access between multiple producer and consumer threads. ```cpp #include "./OS/inc/CSemaphore.h" #include #include // Producer-Consumer pattern with semaphore #define BUFFER_SIZE 10 int circularBuffer[BUFFER_SIZE]; int writeIndex = 0; int readIndex = 0; CSemaphore emptySlots(BUFFER_SIZE); // Initially BUFFER_SIZE empty slots CSemaphore filledSlots(0); // Initially 0 filled slots CMutex bufferMutex; void producer(int producerId, int itemCount) { for (int i = 0; i < itemCount; i++) { int item = producerId * 1000 + i; // Wait for empty slot emptySlots.wait(); // Critical section - add item to buffer bufferMutex.lock(); circularBuffer[writeIndex] = item; writeIndex = (writeIndex + 1) % BUFFER_SIZE; LOG_INFO("Producer", "Producer " + std::to_string(producerId) + " produced item: " + std::to_string(item)); bufferMutex.unlock(); // Signal filled slot available emptySlots.post(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } void consumer(int consumerId, int itemCount) { for (int i = 0; i < itemCount; i++) { // Wait for filled slot filledSlots.wait(); // Critical section - remove item from buffer bufferMutex.lock(); int item = circularBuffer[readIndex]; readIndex = (readIndex + 1) % BUFFER_SIZE; LOG_INFO("Consumer", "Consumer " + std::to_string(consumerId) + " consumed item: " + std::to_string(item)); bufferMutex.unlock(); // Signal empty slot available emptySlots.post(); std::this_thread::sleep_for(std::chrono::milliseconds(15)); } } // Example usage int main() { const int NUM_PRODUCERS = 3; const int NUM_CONSUMERS = 2; const int ITEMS_PER_PRODUCER = 20; std::vector threads; // Start producer threads for (int i = 0; i < NUM_PRODUCERS; i++) { threads.emplace_back(producer, i, ITEMS_PER_PRODUCER); } // Start consumer threads int itemsPerConsumer = (NUM_PRODUCERS * ITEMS_PER_PRODUCER) / NUM_CONSUMERS; for (int i = 0; i < NUM_CONSUMERS; i++) { threads.emplace_back(consumer, i, itemsPerConsumer); } // Wait for all threads for (auto& t : threads) { t.join(); } LOG_INFO("Main", "Producer-Consumer completed successfully"); return 0; } ``` -------------------------------- ### Data Processing with C++20 Ranges Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Utilizes C++20 ranges for efficient and expressive data processing, including filtering, transforming, and grouping detection results. This approach simplifies complex data manipulations and improves code readability. Requires 'RangesUtilities.h'. ```cpp #include "Common/inc/RangesUtilities.h" using namespace pedestrian_detection::ranges; using namespace std::ranges; void processDetections(std::span detections) { // Filter high-confidence detections using ranges auto highConfidence = detections | confidence_filter(0.8f) | views::take(10); // Take top 10 // Extract bounding boxes auto boxes = highConfidence | bounding_boxes; // Calculate average confidence auto avgConfidence = DetectionProcessor::calculateAverageConfidence(detections); // Group by angle ranges auto grouped = DetectionProcessor::groupByAngle(detections, 15.0f); // Transform to centers auto centers = detections | extractCenters; } ``` -------------------------------- ### Modern Error Handling with std::expected in C++ Source: https://github.com/curioussingularity/pedestrain-detection-autonomousdriving/blob/master/Examples/Cpp20Usage.md Demonstrates modern C++ error handling using `std::expected` (C++23 feature) and `std::optional`. The code shows how to return either a successful value or an error code, and how to propagate errors through a pipeline of operations using monadic-like chaining. ```cpp #include // C++23 feature #include // Using std::expected for error handling std::expected loadFrame(const std::string& path) { cv::Mat frame = cv::imread(path); if (frame.empty()) { return std::unexpected(global::RC_ERROR_OPEN); } return frame; } // Modern error propagation auto processImagePipeline(const std::string& imagePath) -> std::expected, global::RC_t> { // Chain operations with error propagation auto frame = loadFrame(imagePath); if (!frame) return std::unexpected(frame.error()); auto algorithm = createDetectionAlgorithm(); if (!algorithm) return std::unexpected(global::RC_ERROR_MEMORY); return algorithm->detectRange(*frame); } ``` -------------------------------- ### CMutex: RAII Mutex Wrapper for Thread Safety Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt The CMutex class wraps POSIX mutexes, offering RAII-style critical section management. It ensures locks are automatically acquired upon entering a scope and released upon exiting, preventing deadlocks. This simplifies thread-safe access to shared resources. Dependencies include `` and the custom `CMutex.h` header. ```cpp #include "./OS/inc/CMutex.h" #include // Shared resource protected by mutex int sharedCounter = 0; CMutex counterMutex; void incrementCounter(int threadId, int iterations) { for (int i = 0; i < iterations; i++) { // Acquire lock (blocks if already locked) if (counterMutex.lock() == global::RC_SUCCESS) { // Critical section - only one thread at a time int temp = sharedCounter; std::this_thread::sleep_for(std::chrono::microseconds(1)); sharedCounter = temp + 1; // Release lock counterMutex.unlock(); } } LOG_INFO("Thread", "Thread " + std::to_string(threadId) + " completed"); } // RAII-style usage with scope guard void safeIncrement() { class MutexGuard { CMutex& mutex; public: MutexGuard(CMutex& m) : mutex(m) { mutex.lock(); } ~MutexGuard() { mutex.unlock(); } }; MutexGuard guard(counterMutex); // Auto-lock sharedCounter++; // Auto-unlock when guard goes out of scope } // Example with multiple threads int main() { const int NUM_THREADS = 10; const int ITERATIONS = 1000; std::vector threads; // Spawn multiple threads accessing shared resource for (int i = 0; i < NUM_THREADS; i++) { threads.emplace_back(incrementCounter, i, ITERATIONS); } // Wait for all threads to complete for (auto& t : threads) { t.join(); } // Verify thread-safe increment LOG_INFO("Main", "Final counter value: " + std::to_string(sharedCounter)); LOG_INFO("Main", "Expected: " + std::to_string(NUM_THREADS * ITERATIONS)); return 0; } ``` -------------------------------- ### CResource: Base Class for Mutex-Protected Hardware Resource I/O Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt An abstract base class for hardware resources that utilizes file descriptors for I/O operations, ensuring thread safety through internal mutex protection. It handles device configuration and resource cleanup via its destructor. ```cpp #include "./OS/inc/CResource.h" #include "./OS/inc/CMutex.h" #include class CustomDevice : public CResource { private: global::RC_t configure() override { // Device-specific configuration LOG_INFO("CustomDevice", "Configuring device..."); return global::RC_SUCCESS; } public: CustomDevice(std::string devPath, int flags, mode_t mode) : CResource(devPath, flags, mode) { this->configure(); } ~CustomDevice() {} }; // Usage example int main() { // Open device with read/write access CustomDevice device("/dev/mydevice", O_RDWR | O_NOCTTY, S_IRWXU); // Write data (thread-safe with internal mutex) char writeBuffer[128] = "Hello Device"; ssize_t bytesWritten; global::RC_t result = device.write(writeBuffer, strlen(writeBuffer), bytesWritten); if (result == global::RC_SUCCESS) { LOG_INFO("Main", "Wrote " + std::to_string(bytesWritten) + " bytes"); } // Read data (thread-safe with internal mutex) char readBuffer[128] = {0}; ssize_t bytesRead; result = device.read(readBuffer, sizeof(readBuffer), bytesRead); if (result == global::RC_SUCCESS) { LOG_INFO("Main", "Read " + std::to_string(bytesRead) + " bytes: " + std::string(readBuffer)); } else if (result == global::RC_ERROR_READ_ONLY) { LOG_ERROR("Main", "Device is write-only"); } // Resource automatically closed in destructor return 0; } ``` -------------------------------- ### CThread: POSIX Thread Wrapper for Service Threads (C++) Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt A base class for service threads that abstracts POSIX threads. It provides a virtual `run()` method for thread-specific implementation and manages thread creation, joining, and detaching. Dependencies include CThread.h, pthread.h, and thread.h. It takes a thread index and a lambda function for the thread's entry point. ```cpp #include "./OS/inc/CThread.h" #include #include class MyCustomThread : public CThread { private: void run() override { // Thread implementation while (true) { LOG_INFO("MyThread", "Thread running with ID: " + std::to_string(pthread_self())); std::this_thread::sleep_for(std::chrono::seconds(1)); } } public: MyCustomThread(int index) : CThread(index, [this]() { this->run(); }) {} ~MyCustomThread() {} }; // Usage example int main() { MyCustomThread worker(0); // Create and start thread if (worker.create() == global::RC_SUCCESS) { LOG_INFO("Main", "Thread created successfully"); // Get thread information LOG_INFO("Main", "Thread Index: " + std::to_string(worker.getThreadIndex())); LOG_INFO("Main", "Thread ID: " + std::to_string(worker.getThreadID())); // Option 1: Wait for thread completion worker.join(); // Option 2: Run independently // worker.detach(); } return 0; } ``` -------------------------------- ### C++ Camera Service Frame Capture and Ring Buffer Storage Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt This C++ code defines a Camera Service that captures frames from camera hardware using gstreamer and stores them in a ring buffer. The service runs in a loop, waiting for the correct frame timing and handling potential capture or buffer write errors. A custom clone function is used for deep copying cv::Mat objects into the buffer. ```cpp #include "./App/inc/CCameraService.h" #include "./Lib/inc/CRingBuffer.h" #include #include // Global frame buffer shared with detection thread CRingBuffer g_framesBuffer; // Camera configuration constants // Resolution: 1280x720 captured, resized to 960x540 // Framerate: 30 FPS // FOV: 62.2° horizontal, 48.8° vertical void CCameraService::run() { cv::Mat image; ssize_t bytesRead; LOG_INFO("CCameraService", "Camera Service started"); while (1) { // Wait for next frame timing (33.33ms for 30 FPS) this->waitForNewFrame(); // Capture frame from camera hardware via gstreamer if (this->m_primaryCamera.read(&image, 0, bytesRead) != global::RC_SUCCESS) { LOG_ERROR("CCameraService", "Frame capture failed"); continue; } // Store frame to ring buffer with custom copy function if (g_framesBuffer.writeData(image, cloneMat) != global::RC_SUCCESS) { LOG_ERROR("CCameraService", "Ring buffer write error - buffer full"); } } } // Static helper for deep copying cv::Mat in ring buffer void CCameraService::cloneMat(cv::Mat& destination, const cv::Mat& source) { destination = source.clone(); } // Example instantiation and usage int main() { // Create camera service thread (opens /dev/video0) CCameraService cameraThread(THREAD_CAMERA_SERVICE); // Start camera capture thread if (cameraThread.create() == global::RC_SUCCESS) { LOG_INFO("Main", "Camera service thread created successfully"); // Thread runs independently, capturing frames at 30 FPS cameraThread.detach(); } return 0; } ``` -------------------------------- ### CComRxService: Monitor UART and Route Commands (C++) Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Implements a service thread that continuously monitors UART for incoming commands, parses them, and routes them to appropriate services using a mailbox system. It logs received object data and sends configuration updates. Dependencies include CComRxService.h, CSerialProtocol.h, and CMailBox.h. It takes no direct input but reads from UART and outputs logs and mailbox messages. ```cpp #include "./App/inc/CComRxService.h" #include "./App/inc/CSerialProtocol.h" #include "./OS/inc/CMailBox.h" void CComRxService::run() { LOG_INFO("CComRxService", "Communication Rx Service started"); std::vector receivedObjects; CUart rxUart("/dev/ttyTHS1", O_RDWR | O_NOCTTY | O_SYNC, S_IRWXU); while (1) { // Parse incoming protocol packets from UART global::RC_t result = m_protocol.readRequest(receivedObjects, &rxUart); if (result == global::RC_SUCCESS && !receivedObjects.empty()) { // Process received LIDAR data or commands for (const auto& obj : receivedObjects) { LOG_INFO("CComRxService", "Received object - Angle: " + std::to_string(obj.angle) + ", Distance: " + std::to_string(obj.distance) + "cm"); } // Route commands to appropriate service threads via mailbox // Example: send configuration update to detection thread extern CMailBox g__Mailboxes[THREAD_TOTAL_COUNT]; CMailBox::MailBoxData cmdMsg = { .sid = global::SID_DETECTION_CONFIG, .lid = global::LID_DETECTION_ALGO, .dynamicData = nullptr }; g__Mailboxes[THREAD_DETECTION_SERVICE].send( THREAD_COM_RX_SERVICE, cmdMsg ); receivedObjects.clear(); } usleep(10000); // 10ms polling interval } } // Example instantiation int main() { CComRxService rxService(THREAD_COM_RX_SERVICE); rxService.create(); rxService.detach(); // Run independently return 0; } ``` -------------------------------- ### C++ Communication Transmission Service (CComTxService) Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Implements the CComTxService, a mailbox-driven component responsible for receiving object detection data and transmitting it via UART. It defines the protocol format, message processing, data serialization, and UART write operations. Dependencies include custom OS and serial protocol headers. ```cpp #include "./App/inc/CComTxService.h" #include "./App/inc/CSerialProtocol.h" #include "./OS/inc/CMailBox.h" #include // Protocol format: // [SOP(0xFA)][DLC(0x04)][Theta][Delta_Theta][Reserved(2 bytes)][EOP(0xFD)] void CComTxService::run() { extern CMailBox g__Mailboxes[THREAD_TOTAL_COUNT]; int senderId = 0; CMailBox::MailBoxData receivedMsg = {0}; LOG_INFO("CComTxService", "Communication Tx Service started"); while (1) { // Block waiting for mailbox message from detection thread if (g__Mailboxes[THREAD_COM_TX_SERVICE].receive(senderId, receivedMsg) != global::RC_SUCCESS) { continue; } // Route message based on sender switch (senderId) { case THREAD_DETECTION_SERVICE: this->processRecvdMsg(receivedMsg); break; default: LOG_WARNING("CComTxService", "Unknown sender: " + std::to_string(senderId)); break; } } } global::RC_t CComTxService::processDataForTx(CMailBox::MailBoxData& data) { CSerialProtocol::object_detection_frame_t* detectionData = static_cast(data.dynamicData); if (!detectionData) { return global::RC_ERROR_NULL; } // Build protocol packet char txBuffer[PROTOCOL_BUF_MAX_SIZE]; memset(txBuffer, 0, sizeof(txBuffer)); int index = 0; txBuffer[index++] = 0xFA; // Start of Protocol txBuffer[index++] = 0x04; // Data Length Code // Pack detection blocks (angle and delta angle for each pedestrian) for (const auto& block : detectionData->blks) { txBuffer[index++] = block.theta; // Angle at which pedestrian is present txBuffer[index++] = block.delta_theta; // Angular width of detection } txBuffer[index++] = 0x00; // Reserved txBuffer[index++] = 0x00; // Reserved txBuffer[index++] = 0xFD; // End of Protocol // Transmit via UART (/dev/ttyTHS1 at 115200 baud) ssize_t bytesWritten; global::RC_t result = this->m_primaryUart.write(txBuffer, index, bytesWritten); if (result == global::RC_SUCCESS) { LOG_INFO("CComTxService", "Transmitted " + std::to_string(bytesWritten) + " bytes"); } // Cleanup dynamic memory delete detectionData; return result; } ``` ```cpp // Example usage with mailbox messaging int main() { extern CMailBox g__Mailboxes[THREAD_TOTAL_COUNT]; // Simulate sending detection data to Tx service CSerialProtocol::object_detection_frame_t* detection = new CSerialProtocol::object_detection_frame_t(); CSerialProtocol::object_detection_block_t pedestrian = { .theta = -15, // Pedestrian at -15° from vehicle center .delta_theta = 8 // Occupies 8° of field of view }; detection->blks.push_back(pedestrian); CMailBox::MailBoxData msg = { .sid = global::SID_TX_DATA, .lid = CUart::UART_CHANNEL_1, .dynamicData = static_cast(detection) }; // Send to communication service mailbox g__Mailboxes[THREAD_COM_TX_SERVICE].send(THREAD_DETECTION_SERVICE, msg); return 0; } ``` -------------------------------- ### C++ Logger: Multi-Destination Logging Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Implements a singleton logger with support for multiple output destinations like console and files. It allows configurable log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL) for effective debugging and monitoring. The logger can also handle structured data and performance measurements. ```cpp #include "./Common/inc/Logger.h" int main() { // Get logger singleton instance Logger& logger = Logger::getInstance(); // Add console output with color support logger.addDestination(std::make_unique(true)); // Add file output logger.addDestination(std::make_unique("app.log")); // Set minimum log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) logger.setMinLevel(LogLevel::INFO); // Log messages with different severity levels LOG_DEBUG("Main", "Debug message - not displayed (below INFO level)"); LOG_INFO("Main", "Application started - PID: " + std::to_string(getpid())); LOG_WARNING("Main", "Camera frame rate dropped to 25 FPS"); LOG_ERROR("Main", "Failed to open UART device: " + std::string(strerror(errno))); LOG_CRITICAL("Main", "Out of memory - terminating"); // Log with context and structured data int detectionCount = 5; float avgAngle = -12.5f; LOG_INFO("Detection", "Frame processed - Detections: " + std::to_string(detectionCount) + ", Avg Angle: " + std::to_string(avgAngle) + "°"); // Performance measurement logging double startTime = cv::getTickCount(); // ... perform operations ... double elapsed = (cv::getTickCount() - startTime) / cv::getTickFrequency(); LOG_INFO("Performance", "Detection cycle completed in " + std::to_string(elapsed * 1000.0) + "ms"); return 0; } ``` -------------------------------- ### CMailBox: Thread-Safe Inter-Thread Communication with POSIX Pipes Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Implements a mailbox system using POSIX pipes for blocking receive and non-blocking send operations, ensuring thread-safe message passing between threads. It requires global mailboxes and defines message structures for data exchange. ```cpp #include "./OS/inc/CMailBox.h" #include "./global.h" // Global mailboxes array - one per thread CMailBox g__Mailboxes[THREAD_TOTAL_COUNT] = { CMailBox(THREAD_BACKGROUND), CMailBox(THREAD_COM_TX_SERVICE), CMailBox(THREAD_COM_RX_SERVICE), CMailBox(THREAD_CAMERA_SERVICE), CMailBox(THREAD_DETECTION_SERVICE) }; // Producer thread: Send detection data to communication service void producerThread() { // Prepare message with service ID and local ID for routing CMailBox::MailBoxData message = { .sid = global::SID_TX_DATA, // Service identifier .lid = CUart::UART_CHANNEL_1, // Local identifier (channel) .dynamicData = malloc(sizeof(int)) // Optional dynamic payload }; int* data = static_cast(message.dynamicData); *data = 42; // Send to communication Tx service (non-blocking) global::RC_t result = g__Mailboxes[THREAD_COM_TX_SERVICE].send( THREAD_DETECTION_SERVICE, // Sender ID message ); if (result == global::RC_SUCCESS) { LOG_INFO("Producer", "Message sent successfully"); } else if (result == global::RC_ERROR_BUFFER_FULL) { LOG_ERROR("Producer", "Mailbox full - message dropped"); free(message.dynamicData); } } // Consumer thread: Receive and process messages void consumerThread() { int senderId = 0; CMailBox::MailBoxData receivedMsg = {0}; // Blocking receive - waits until message available global::RC_t result = g__Mailboxes[THREAD_COM_TX_SERVICE].receive( senderId, // Reference to store sender's thread ID receivedMsg // Reference to store message data ); if (result == global::RC_SUCCESS) { LOG_INFO("Consumer", "Received message from thread: " + std::to_string(senderId)); LOG_INFO("Consumer", "Service ID: " + std::to_string(receivedMsg.sid)); LOG_INFO("Consumer", "Local ID: " + std::to_string(receivedMsg.lid)); if (receivedMsg.dynamicData) { int* value = static_cast(receivedMsg.dynamicData); LOG_INFO("Consumer", "Dynamic data value: " + std::to_string(*value)); free(receivedMsg.dynamicData); } } } // Example multi-thread communication int main() { // Create producer and consumer threads std::thread producer(producerThread); std::thread consumer(consumerThread); producer.join(); consumer.join(); return 0; } ``` -------------------------------- ### Capture Video Frames with OpenCV and GStreamer (C++) Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Captures video frames from a camera device using OpenCV's VideoCapture and a gstreamer pipeline. It processes frames, displays them, and calculates FPS. Assumes the presence of camera device nodes and OpenCV library. ```cpp #include "./HAL/inc/CCamera.h" #include #include // Camera configuration // Raspberry Pi Camera v2: 62.2° H-FOV, 48.8° V-FOV // Capture: 1280x720 @ 30 FPS // Processing: resized to 960x540 int main() { // Initialize camera device CCamera camera("/dev/video0", O_RDWR | O_NOCTTY | O_SYNC, S_IRWXU); cv::Mat frame; ssize_t bytesRead; int frameCount = 0; double fpsStartTime = cv::getTickCount(); LOG_INFO("Main", "Starting camera capture..."); while (frameCount < 300) { // Capture 300 frames (10 seconds @ 30 FPS) // Read frame from camera (blocking call) global::RC_t result = camera.read(&frame, 0, bytesRead); if (result == global::RC_SUCCESS) { frameCount++; // Process frame - example: calculate angle for pixel position int pixelX = 480; // Center of 960px width frame float angleResolution = HORIZONTAL_FOV / RESOLUTION_RESIZED_WIDTH; float zeroPixelAngle = -HORIZONTAL_FOV / 2.0f; float angle = (pixelX * angleResolution) + zeroPixelAngle; LOG_INFO("Camera", "Frame " + std::to_string(frameCount) + " captured - size: " + std::to_string(frame.cols) + "x" + std::to_string(frame.rows)); // Display frame (if connected to display) cv::imshow("Camera Feed", frame); if (cv::waitKey(1) == 'q') { break; } } else { LOG_ERROR("Camera", "Frame capture failed"); } // FPS calculation every 30 frames if (frameCount % 30 == 0) { double fpsTime = (cv::getTickCount() - fpsStartTime) / cv::getTickFrequency(); double fps = 30.0 / fpsTime; LOG_INFO("Camera", "FPS: " + std::to_string(fps)); fpsStartTime = cv::getTickCount(); } } cv::destroyAllWindows(); LOG_INFO("Main", "Camera capture completed - " + std::to_string(frameCount) + " frames"); return 0; } ``` -------------------------------- ### CSerialProtocol: UART Communication for Detection Data in C++ Source: https://context7.com/curioussingularity/pedestrain-detection-autonomousdriving/llms.txt Handles protocol encoding and decoding for pedestrian detection data transmission via UART. It defines a structured packet format for sending angle and width information, and also supports receiving LIDAR data. Dependencies include CUart for serial communication. ```cpp #include "./App/inc/CSerialProtocol.h" #include "./HAL/inc/CUart.h" // Protocol format: // [SOP(0xFA)][DLC(0x04)][Theta][Delta_Theta][Reserved(2)][EOP(0xFD)] // Total size: 7 bytes per detection int main() { CSerialProtocol protocol; CUart uart("/dev/ttyTHS1", O_RDWR | O_NOCTTY | O_SYNC, S_IRWXU); // Create detection frame with multiple pedestrians CSerialProtocol::object_detection_frame_t detectionFrame; // Pedestrian 1: -20° angle, 10° width CSerialProtocol::object_detection_block_t ped1 = { .theta = -20, .delta_theta = 10 }; detectionFrame.blks.push_back(ped1); // Pedestrian 2: 15° angle, 8° width CSerialProtocol::object_detection_block_t ped2 = { .theta = 15, .delta_theta = 8 }; detectionFrame.blks.push_back(ped2); // Encode and transmit each detection for (const auto& detection : detectionFrame.blks) { char packet[PROTOCOL_BUF_MAX_SIZE]; int index = 0; // Build packet packet[index++] = SOP; // 0xFA packet[index++] = DLC; // 0x04 packet[index++] = detection.theta; packet[index++] = detection.delta_theta; packet[index++] = 0x00; // Reserved packet[index++] = 0x00; // Reserved packet[index++] = EOP; // 0xFD // Transmit ssize_t bytesWritten; uart.write(packet, index, bytesWritten); LOG_INFO("Protocol", "Transmitted detection - Angle: " + std::to_string(detection.theta) + "°, Width: " + std::to_string(detection.delta_theta) + "°"); } // Receive and decode LIDAR data std::vector lidarObjects; global::RC_t result = protocol.readRequest(lidarObjects, &uart); if (result == global::RC_SUCCESS) { LOG_INFO("Protocol", "Received " + std::to_string(lidarObjects.size()) + " LIDAR objects"); for (const auto& obj : lidarObjects) { LOG_INFO("Protocol", "LIDAR Object - Angle: " + std::to_string(obj.angle) + "°, Distance: " + std::to_string(obj.distance) + "cm, " + "Area Angle: " + std::to_string(obj.area_angle) + "°"); } } return 0; } ```