diff --git a/DroneFlightLog.csv b/DroneFlightLog.csv new file mode 100644 index 0000000..28b497a --- /dev/null +++ b/DroneFlightLog.csv @@ -0,0 +1,51 @@ +timestamp,latitude,longitude,altitude,roll,pitch,yaw,vel_x,vel_y,vel_z,battery,signal +1766265264.3021,33.68441687,73.04788259,0.00,-5.29,-0.20,282.64,-3.29,-4.73,-0.63,100.0,87.9 +1766265264.4021,33.68441183,73.04795667,2.50,-6.76,3.27,195.83,-1.39,-4.62,1.75,98.4,77.9 +1766265264.5021,33.68444842,73.04800322,5.00,-13.28,12.42,232.90,-4.49,-2.53,-0.50,96.8,71.0 +1766265264.6021,33.68445138,73.04797729,7.50,-3.25,-2.74,82.01,-1.74,4.45,-1.72,95.2,88.1 +1766265264.7021,33.68447814,73.04805944,10.00,-8.98,-1.94,170.61,-2.06,2.79,0.03,93.6,92.4 +1766265264.8021,33.68445274,73.04809570,12.50,13.31,-9.94,134.14,-3.59,-4.45,-1.47,92.0,95.2 +1766265264.9021,33.68452322,73.04802450,15.00,-1.55,-10.78,29.89,0.28,1.25,-0.62,90.4,85.8 +1766265265.0021,33.68453117,73.04810018,17.50,-13.30,0.41,127.33,-0.08,-0.28,1.22,88.8,70.8 +1766265265.1021,33.68457631,73.04805673,20.00,-1.06,-2.63,129.77,-1.34,3.59,-0.01,87.2,81.0 +1766265265.2021,33.68457987,73.04809277,22.50,-3.66,10.76,179.14,3.41,-4.76,0.89,85.6,88.9 +1766265265.3021,33.68456901,73.04817255,23.46,11.96,2.88,80.42,-0.46,-2.19,0.48,84.0,88.6 +1766265265.4021,33.68457706,73.04824395,26.76,-7.59,5.55,179.17,-0.56,-3.15,0.13,82.4,96.1 +1766265265.5021,33.68455699,73.04831181,26.85,-8.51,2.37,58.71,-2.70,3.02,-1.66,80.8,77.8 +1766265265.6021,33.68451590,73.04835658,26.69,-6.06,12.24,357.51,4.86,4.35,0.12,79.2,98.5 +1766265265.7021,33.68460338,73.04840766,24.77,-13.96,-6.21,5.57,3.75,1.56,1.42,77.6,87.8 +1766265265.8021,33.68452972,73.04838390,26.37,-0.37,-1.94,335.57,-3.33,-4.99,-1.82,76.0,89.4 +1766265265.9021,33.68453423,73.04841100,24.54,-4.31,10.91,271.26,4.37,-4.37,-1.84,74.4,74.8 +1766265266.0021,33.68444704,73.04834962,25.71,-14.64,-3.95,128.86,-0.71,4.49,0.82,72.8,77.6 +1766265266.1021,33.68438806,73.04834437,25.29,-12.25,14.41,47.57,2.01,3.74,0.98,71.2,82.4 +1766265266.2021,33.68444350,73.04829154,25.64,0.92,-13.70,236.26,-3.09,-3.09,1.74,69.6,94.2 +1766265266.3021,33.68441334,73.04835841,26.01,-5.90,-1.17,2.70,0.91,-4.17,1.01,68.0,94.2 +1766265266.4021,33.68435396,73.04845283,26.36,8.33,4.13,202.23,-4.66,-0.06,-0.15,66.4,98.0 +1766265266.5021,33.68428352,73.04854532,26.90,7.18,-5.77,140.74,-1.45,-3.59,-1.43,64.8,86.6 +1766265266.6021,33.68425663,73.04846698,23.24,5.16,-13.44,151.37,1.44,4.51,-1.66,63.2,84.0 +1766265266.7021,33.68421394,73.04848235,25.94,12.66,-14.19,155.02,-3.36,-3.57,-0.04,61.6,97.7 +1766265266.8021,33.68426366,73.04857784,26.05,10.53,-4.98,179.95,-2.60,0.27,-0.91,60.0,72.3 +1766265266.9021,33.68424767,73.04857337,23.42,5.77,-0.13,149.20,4.00,1.03,0.04,58.4,89.9 +1766265267.0021,33.68432884,73.04848689,24.23,-4.57,12.89,80.00,-3.99,2.49,1.65,56.8,75.1 +1766265267.1021,33.68429004,73.04853025,25.03,-9.54,10.45,172.33,-0.45,-1.48,1.20,55.2,80.8 +1766265267.2021,33.68436807,73.04858554,23.51,8.73,13.43,258.50,-3.13,-4.15,-0.44,53.6,84.5 +1766265267.3021,33.68444203,73.04858357,23.90,-8.60,8.34,182.51,-4.88,-1.52,-1.45,52.0,71.1 +1766265267.4021,33.68444441,73.04864998,26.88,-3.12,-8.46,355.73,-0.42,4.64,-0.96,50.4,86.3 +1766265267.5021,33.68453361,73.04874355,23.23,13.87,-11.29,13.19,-0.31,-1.06,-1.56,48.8,96.6 +1766265267.6021,33.68449752,73.04880382,25.04,14.43,-5.91,279.05,1.96,-2.42,0.32,47.2,77.4 +1766265267.7021,33.68444311,73.04880299,24.65,-8.15,0.38,285.68,-3.13,-1.99,1.48,45.6,92.8 +1766265267.8021,33.68453199,73.04886634,25.70,0.38,-0.79,274.96,-0.96,-0.30,-1.42,44.0,87.2 +1766265267.9021,33.68459557,73.04889603,24.92,10.62,-7.30,34.18,-3.20,-4.30,0.32,42.4,83.2 +1766265268.0021,33.68451936,73.04885478,25.54,-10.39,7.95,199.57,1.05,2.96,-0.09,40.8,98.6 +1766265268.1021,33.68461036,73.04875659,26.51,-11.02,4.41,4.88,-2.44,-0.57,0.80,39.2,96.1 +1766265268.2021,33.68462382,73.04867542,25.18,-0.80,12.09,243.62,2.29,-1.78,1.44,37.6,73.4 +1766265268.3021,33.68467650,73.04874415,25.00,-12.06,-5.90,66.91,0.33,-0.99,1.58,36.0,96.4 +1766265268.4021,33.68461251,73.04875903,22.50,-10.46,-11.56,189.37,-2.96,-2.13,1.29,34.4,79.7 +1766265268.5021,33.68466067,73.04881747,20.00,11.96,-6.86,342.19,-2.56,-2.14,-0.55,32.8,90.7 +1766265268.6021,33.68456133,73.04888973,17.50,-3.70,-7.92,295.38,-0.94,-2.40,-1.99,31.2,74.2 +1766265268.7021,33.68451271,73.04898235,15.00,12.30,-0.70,8.71,-0.83,-0.76,-1.14,29.6,89.9 +1766265268.8021,33.68457696,73.04904353,12.50,1.43,-8.88,9.82,-0.28,3.96,0.07,28.0,85.1 +1766265268.9021,33.68460553,73.04905423,10.00,-6.54,-9.30,332.91,3.44,4.14,-0.57,26.4,74.5 +1766265269.0021,33.68468106,73.04906902,7.50,3.11,-14.84,249.74,3.41,2.86,-0.45,24.8,81.4 +1766265269.1021,33.68466439,73.04909922,5.00,9.86,0.73,337.04,3.67,2.13,0.54,23.2,100.0 +1766265269.2021,33.68475453,73.04904076,2.50,0.70,5.01,28.93,0.20,-2.62,1.26,21.6,75.6 diff --git a/HazardDetection/GenerateHazards.py b/HazardDetection/GenerateHazards.py new file mode 100644 index 0000000..101945c --- /dev/null +++ b/HazardDetection/GenerateHazards.py @@ -0,0 +1,93 @@ +""" +Dynamic Hazard Generator for Drone Flight Simulation +""" + +import random +import time + +def generate_hazards(map_width, map_height, num_hazards, output_file): + """Generate random hazards""" + + hazard_types = { + "BIRD": {"duration": (5, 20), "severity": (2, 4), "desc": "Bird flock"}, + "DRONE": {"duration": (10, 30), "severity": (3, 5), "desc": "Unauthorized drone"}, + "WEATHER": {"duration": (30, 60), "severity": (1, 3), "desc": "Weather system"}, + "DEBRIS": {"duration": (15, 45), "severity": (3, 5), "desc": "Falling debris"}, + "AIRCRAFT": {"duration": (20, 40), "severity": (5, 5), "desc": "Aircraft nearby"} + } + + hazards = [] + + print(f"๐ŸŽฒ Generating {num_hazards} hazards for {map_width}x{map_height} map") + print() + + for i in range(num_hazards): + x = random.randint(0, map_width - 1) + y = random.randint(0, map_height - 1) + + hazard_type = random.choice(list(hazard_types.keys())) + props = hazard_types[hazard_type] + + duration = random.randint(*props["duration"]) + severity = random.randint(*props["severity"]) + timestamp = int(time.time()) + random.randint(0, 300) + + description = f"{props['desc']} at sector {i+1}" + + hazards.append({ + 'x': x, + 'y': y, + 'type': hazard_type, + 'description': description, + 'duration': duration, + 'severity': severity, + 'timestamp': timestamp + }) + + print(f"Hazard {i+1}: ({x},{y}) - {hazard_type} [Sev:{severity}/5, {duration}s]") + + # Sort by severity (highest first) + hazards.sort(key=lambda h: h['severity'], reverse=True) + + # Save to file + with open(output_file, 'w') as f: + f.write(f"# Hazard Detection Data\n") + f.write(f"# Map: {map_width}x{map_height}\n") + f.write(f"# Total: {num_hazards} hazards\n") + f.write(f"# Format: X Y TYPE DESCRIPTION DURATION SEVERITY TIMESTAMP\n\n") + + for h in hazards: + f.write(f"{h['x']} {h['y']} {h['type']} \"{h['description']}\" ") + f.write(f"{h['duration']} {h['severity']} {h['timestamp']}\n") + + print(f"\nโœ… Saved to '{output_file}'") + + # Statistics + print("\n๐Ÿ“Š STATISTICS:") + for htype in hazard_types: + count = sum(1 for h in hazards if h['type'] == htype) + print(f" {htype}: {count}") + print() + + +if __name__ == "__main__": + print("="*60) + print("HAZARD GENERATOR") + print("="*60) + print() + + # Light scenario + generate_hazards(60, 40, 5, "hazards_light.txt") + print() + + # Medium scenario + generate_hazards(60, 40, 15, "hazards_medium.txt") + print() + + # Heavy scenario + generate_hazards(60, 40, 30, "hazards_heavy.txt") + + print("="*60) + print("โœ… All scenarios generated!") + print("="*60) + diff --git a/HazardDetection/HazardDetector.cpp b/HazardDetection/HazardDetector.cpp new file mode 100644 index 0000000..7cef3d3 --- /dev/null +++ b/HazardDetection/HazardDetector.cpp @@ -0,0 +1,309 @@ +#include "HazardDetector.h" +#include +#include +#include + +using namespace std; + +// ============================================ +// HAZARD IMPLEMENTATION +// ============================================ + +Hazard::Hazard() + : x(0), y(0), type("UNKNOWN"), description(""), + timestamp(0), duration(0), severity(1) {} + +Hazard::Hazard(int xPos, int yPos, string hazardType, string desc, int dur, int sev) + : x(xPos), y(yPos), type(hazardType), description(desc), + duration(dur), severity(sev) { + timestamp = time(nullptr); +} + +bool Hazard::isActive() const { + time_t now = time(nullptr); + return (now - timestamp) < duration; +} + +int Hazard::timeRemaining() const { + time_t now = time(nullptr); + int elapsed = now - timestamp; + return max(0, duration - elapsed); +} + +void Hazard::display() const { + cout << " Location: (" << x << "," << y << ")\n"; + cout << " Type: " << type << "\n"; + cout << " Description: " << description << "\n"; + cout << " Severity: " << severity << "/5\n"; + cout << " Time remaining: " << timeRemaining() << "s\n"; +} + +// ============================================ +// HAZARD DETECTOR IMPLEMENTATION +// ============================================ + +HazardDetector::HazardDetector(int width, int height) + : mapWidth(width), mapHeight(height), totalDetected(0), totalExpired(0) { + cout << "โœ… HazardDetector initialized (" << width << "x" << height << ")" << endl; +} + +HazardDetector::~HazardDetector() { + hazardMap.clear(); +} + +int HazardDetector::hashKey(int x, int y) const { + return y * mapWidth + x; +} + +pair HazardDetector::reverseHash(int key) const { + int y = key / mapWidth; + int x = key % mapWidth; + return make_pair(x, y); +} + +bool HazardDetector::addHazard(int x, int y, string type, string description, + int duration, int severity) { + // Validate coordinates + if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) { + cerr << "โŒ Invalid coordinates: (" << x << "," << y << ")" << endl; + return false; + } + + int key = hashKey(x, y); + + // Check if exists + if (hazardMap.find(key) != hazardMap.end()) { + cout << "โš ๏ธ Updating existing hazard at (" << x << "," << y << ")" << endl; + } + + // Insert (O(1)) + hazardMap[key] = Hazard(x, y, type, description, duration, severity); + totalDetected++; + + cout << "๐Ÿšจ HAZARD ADDED at (" << x << "," << y << ")" << endl; + cout << " Type: " << type << " | Severity: " << severity << "/5" << endl; + cout << " " << description << endl; + + return true; +} + +bool HazardDetector::isHazard(int x, int y) const { + int key = hashKey(x, y); + auto it = hazardMap.find(key); + + if (it == hazardMap.end()) { + return false; + } + + return it->second.isActive(); +} + +Hazard* HazardDetector::getHazard(int x, int y) { + int key = hashKey(x, y); + auto it = hazardMap.find(key); + + if (it != hazardMap.end() && it->second.isActive()) { + return &(it->second); + } + + return nullptr; +} + +bool HazardDetector::removeHazard(int x, int y) { + int key = hashKey(x, y); + + if (hazardMap.find(key) != hazardMap.end()) { + string desc = hazardMap[key].description; + hazardMap.erase(key); + cout << "โœ… Hazard removed at (" << x << "," << y << "): " << desc << endl; + return true; + } + + cout << "โš ๏ธ No hazard at (" << x << "," << y << ")" << endl; + return false; +} + +int HazardDetector::cleanExpiredHazards() { + int removed = 0; + + for (auto it = hazardMap.begin(); it != hazardMap.end(); ) { + if (!it->second.isActive()) { + pair pos = reverseHash(it->first); + cout << "๐Ÿงน Expired: (" << pos.first << "," << pos.second + << ") - " << it->second.type << endl; + it = hazardMap.erase(it); + removed++; + totalExpired++; + } else { + ++it; + } + } + + if (removed > 0) { + cout << "โœ… Cleaned " << removed << " expired hazards" << endl; + } + + return removed; +} + +void HazardDetector::clearAllHazards() { + int count = hazardMap.size(); + hazardMap.clear(); + cout << "๐Ÿงน Cleared " << count << " hazard(s)" << endl; +} + +bool HazardDetector::isPathSafe(const vector >& path) const { + for (size_t i = 0; i < path.size(); i++) { + int x = path[i].first; + int y = path[i].second; + if (isHazard(x, y)) { + cout << "โš ๏ธ Path crosses hazard at (" << x << "," << y << ")" << endl; + return false; + } + } + return true; +} + +vector HazardDetector::getActiveHazards() const { + vector active; + + for (auto it = hazardMap.begin(); it != hazardMap.end(); ++it) { + if (it->second.isActive()) { + active.push_back(it->second); + } + } + + return active; +} + +int HazardDetector::getActiveCount() const { + return static_cast(hazardMap.size()); +} + +int HazardDetector::getTotalDetected() const { + return totalDetected; +} + +int HazardDetector::getTotalExpired() const { + return totalExpired; +} + +void HazardDetector::displayStatus() const { + cout << "\n========================================" << endl; + cout << " HAZARD DETECTION SYSTEM STATUS" << endl; + cout << "========================================" << endl; + cout << "Active hazards: " << hazardMap.size() << endl; + cout << "Total detected: " << totalDetected << endl; + cout << "Total expired: " << totalExpired << endl; + + if (hazardMap.empty()) { + cout << "โœ… Airspace clear - No active hazards" << endl; + } + + cout << "========================================\n" << endl; +} + +void HazardDetector::displayAllHazards() const { + cout << "\n========== ACTIVE HAZARDS ==========" << endl; + + if (hazardMap.empty()) { + cout << "No active hazards." << endl; + } else { + int count = 1; + for (auto it = hazardMap.begin(); it != hazardMap.end(); ++it) { + if (it->second.isActive()) { + cout << "\nHazard #" << count++ << ":" << endl; + it->second.display(); + } + } + } + cout << "====================================\n" << endl; +} + +bool HazardDetector::saveToFile(const string& filename) const { + ofstream file(filename.c_str()); + + if (!file.is_open()) { + cerr << "โŒ Cannot save to file: " << filename << endl; + return false; + } + + file << "# Hazard Detection Log\n"; + file << "# Format: X Y TYPE DESCRIPTION DURATION SEVERITY TIMESTAMP\n\n"; + + for (auto it = hazardMap.begin(); it != hazardMap.end(); ++it) { + if (it->second.isActive()) { + file << it->second.x << " " << it->second.y << " " + << it->second.type << " \"" << it->second.description << "\" " + << it->second.duration << " " << it->second.severity << " " + << it->second.timestamp << "\n"; + } + } + + file.close(); + cout << "๐Ÿ’พ Hazards saved to '" << filename << "'" << endl; + return true; +} + +bool HazardDetector::loadFromFile(const string& filename) { + ifstream file(filename.c_str()); + + if (!file.is_open()) { + cerr << "โŒ Cannot load file: " << filename << endl; + return false; + } + + string line; + int loaded = 0; + + while (getline(file, line)) { + // Skip comments and empty lines + if (line.empty() || line[0] == '#') continue; + + istringstream iss(line); + int x, y, duration, severity; + time_t timestamp; + string type, description; + + // Read x, y, type + if (!(iss >> x >> y >> type)) { + continue; + } + + // Read description (between quotes) + string rest; + getline(iss, rest); + + // Find first quote + size_t firstQuote = rest.find('"'); + if (firstQuote == string::npos) { + continue; + } + + // Find second quote + size_t secondQuote = rest.find('"', firstQuote + 1); + if (secondQuote == string::npos) { + continue; + } + + // Extract description + description = rest.substr(firstQuote + 1, secondQuote - firstQuote - 1); + + // Read duration, severity, timestamp from after second quote + istringstream restStream(rest.substr(secondQuote + 1)); + if (!(restStream >> duration >> severity >> timestamp)) { + continue; + } + + int key = hashKey(x, y); + hazardMap[key] = Hazard(x, y, type, description, duration, severity); + hazardMap[key].timestamp = timestamp; + + loaded++; + } + + file.close(); + cout << "โœ… Loaded " << loaded << " hazards from '" << filename << "'" << endl; + return true; +} + diff --git a/HazardDetection/HazardDetector.h b/HazardDetection/HazardDetector.h new file mode 100644 index 0000000..5f49852 --- /dev/null +++ b/HazardDetection/HazardDetector.h @@ -0,0 +1,81 @@ +#ifndef HAZARD_DETECTOR_H +#define HAZARD_DETECTOR_H + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// ============================================ +// HAZARD STRUCTURE +// ============================================ +struct Hazard { + int x, y; + string type; // "BIRD", "DRONE", "WEATHER", "DEBRIS" + string description; // Detailed description + time_t timestamp; // When detected + int duration; // How long it lasts (seconds) + int severity; // 1-5 (5 = most dangerous) + + Hazard(); + Hazard(int xPos, int yPos, string hazardType, string desc, int dur, int sev); + + bool isActive() const; + int timeRemaining() const; + void display() const; +}; + +// ============================================ +// HAZARD DETECTOR CLASS +// ============================================ +class HazardDetector { +private: + unordered_map hazardMap; + int mapWidth; + int mapHeight; + int totalDetected; + int totalExpired; + + // Hash function: (x,y) โ†’ unique int + int hashKey(int x, int y) const; + + // Reverse: hash key โ†’ (x,y) + pair reverseHash(int key) const; + +public: + HazardDetector(int width, int height); + ~HazardDetector(); + + // Core operations (O(1)) + bool addHazard(int x, int y, string type, string description, int duration, int severity); + bool isHazard(int x, int y) const; + Hazard* getHazard(int x, int y); + bool removeHazard(int x, int y); + + // Maintenance + int cleanExpiredHazards(); + void clearAllHazards(); + + // Path safety + bool isPathSafe(const vector >& path) const; + + // Queries + vector getActiveHazards() const; + int getActiveCount() const; + int getTotalDetected() const; + int getTotalExpired() const; + + // I/O + void displayStatus() const; + void displayAllHazards() const; + bool saveToFile(const string& filename) const; + bool loadFromFile(const string& filename); +}; + +#endif // HAZARD_DETECTOR_H + diff --git a/HazardDetection/HazardMakefile b/HazardDetection/HazardMakefile new file mode 100644 index 0000000..628fcc7 --- /dev/null +++ b/HazardDetection/HazardMakefile @@ -0,0 +1,45 @@ +# Makefile for Hazard Detection Feature + +CXX = g++ +CXXFLAGS = -std=c++11 -Wall +TARGET = hazard_demo + +# Source files +SOURCES = demo_hazards.cpp HazardDetector.cpp +OBJECTS = $(SOURCES:.cpp=.o) + +# Default target +all: $(TARGET) + +# Build executable +$(TARGET): $(OBJECTS) + $(CXX) $(OBJECTS) -o $(TARGET) + @echo "โœ… Build successful: $(TARGET)" + +# Compile objects +%.o: %.cpp HazardDetector.h + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Generate hazard data +generate: + python3 GenerateHazards.py + +# Run demo +run: $(TARGET) generate + ./$(TARGET) + +# Clean +clean: + rm -f $(OBJECTS) $(TARGET) hazards_*.txt hazard_log.txt + @echo "๐Ÿงน Cleaned build files" + +# Help +help: + @echo "Available targets:" + @echo " make -f HazardMakefile - Build the demo" + @echo " make -f HazardMakefile generate - Generate hazard data" + @echo " make -f HazardMakefile run - Build, generate data, and run" + @echo " make -f HazardMakefile clean - Remove all build files" + +.PHONY: all generate run clean help + diff --git a/HazardDetection/README.md b/HazardDetection/README.md new file mode 100644 index 0000000..a31f96c --- /dev/null +++ b/HazardDetection/README.md @@ -0,0 +1,51 @@ +Dynamic Hazard Detection System +Overview + +Tracks hazards in a 2D airspace grid and checks for safety in real-time. +Handles multiple hazard types, severity levels, and automatically removes expired hazards. + +Features + +O(1) Hazard Lookup โ€“ Instantly check any position + +Time-Based Expiration โ€“ Hazards disappear after their duration + +Multiple Types โ€“ BIRD, DRONE, WEATHER, DEBRIS, AIRCRAFT + +Severity Levels โ€“ 1-5 danger rating + +Path Safety โ€“ Check if a full path is safe + +File I/O โ€“ Save and load hazard data + +How it Works + +Uses a grid-based lookup for fast access + +Hazards can be added, checked, expired, or removed manually + +Includes a Python generator to create test hazard data + +## File Structure +``` +HazardDetection/ +โ”œโ”€โ”€ HazardDetector.h - Interface +โ”œโ”€โ”€ HazardDetector.cpp - Implementation +โ”œโ”€โ”€ demo_hazards.cpp - Demo program +โ”œโ”€โ”€ GenerateHazards.py - Data generator +โ”œโ”€โ”€ HazardMakefile - Build system +โ””โ”€โ”€ README.md - This file +``` + + +## Performance +- **Lookup**: O(1) average +- **Insert**: O(1) average +- **Delete**: O(1) average +- **Clean Expired**: O(N) where N = total hazards + +## Requirements +- C++11 or later +- Python 3.x (for generator) +- Make utility + diff --git a/HazardDetection/demo_hazards.cpp b/HazardDetection/demo_hazards.cpp new file mode 100644 index 0000000..559bb46 --- /dev/null +++ b/HazardDetection/demo_hazards.cpp @@ -0,0 +1,125 @@ +#include "HazardDetector.h" +#include + +// Cross-platform sleep +#ifdef _WIN32 +#include +#define sleep_seconds(s) Sleep((s) * 1000) +#else +#include +#define sleep_seconds(s) sleep(s) +#endif + +using namespace std; + +int main() { + cout << "\n"; + cout << "============================================\n"; + cout << " HAZARD DETECTION SYSTEM - DEMO\n"; + cout << "============================================\n\n"; + + // Initialize detector for 60x40 map + HazardDetector detector(60, 40); + + cout << "\n=== ADDING DYNAMIC HAZARDS ===" << endl; + + // Add various hazards + detector.addHazard(25, 15, "BIRD", "Flock of birds crossing", 15, 3); + detector.addHazard(40, 20, "DRONE", "Unauthorized drone detected", 30, 4); + detector.addHazard(10, 30, "WEATHER", "Storm system approaching", 60, 2); + detector.addHazard(50, 10, "DEBRIS", "Falling debris from building", 20, 5); + detector.addHazard(35, 25, "AIRCRAFT", "Small aircraft in vicinity", 45, 5); + + // Display status + detector.displayStatus(); + detector.displayAllHazards(); + + // Test path safety + cout << "\n=== PATH SAFETY TEST ===" << endl; + + vector > path1; + path1.push_back(make_pair(20, 10)); + path1.push_back(make_pair(25, 15)); + path1.push_back(make_pair(30, 20)); + + vector > path2; + path2.push_back(make_pair(5, 5)); + path2.push_back(make_pair(10, 10)); + path2.push_back(make_pair(15, 15)); + + cout << "\nChecking Path 1: "; + for (size_t i = 0; i < path1.size(); i++) { + cout << "(" << path1[i].first << "," << path1[i].second << ") "; + } + cout << endl; + bool safe1 = detector.isPathSafe(path1); + cout << "Result: " << (safe1 ? "โœ… SAFE" : "โŒ UNSAFE") << "\n"; + + cout << "\nChecking Path 2: "; + for (size_t i = 0; i < path2.size(); i++) { + cout << "(" << path2[i].first << "," << path2[i].second << ") "; + } + cout << endl; + bool safe2 = detector.isPathSafe(path2); + cout << "Result: " << (safe2 ? "โœ… SAFE" : "โŒ UNSAFE") << "\n"; + + // Test individual cell checks + cout << "\n=== INDIVIDUAL CELL CHECKS (O(1) lookup) ===" << endl; + + int testCells[][2] = {{25, 15}, {40, 20}, {5, 5}, {50, 10}}; + int numCells = 4; + + for (int i = 0; i < numCells; i++) { + int x = testCells[i][0]; + int y = testCells[i][1]; + bool hazard = detector.isHazard(x, y); + cout << "Cell (" << x << "," << y << "): " + << (hazard ? "๐Ÿšจ HAZARD" : "โœ… Clear") << endl; + + if (hazard) { + Hazard* h = detector.getHazard(x, y); + if (h) { + cout << " Type: " << h->type + << " | Time left: " << h->timeRemaining() << "s" << endl; + } + } + } + + // Simulate time passing + cout << "\n=== SIMULATING 20 SECONDS PASSING ===" << endl; + sleep_seconds(20); + + // Clean expired hazards + cout << "\nCleaning expired hazards..." << endl; + detector.cleanExpiredHazards(); + detector.displayStatus(); + + // Save to file + cout << "\n=== SAVING TO FILE ===" << endl; + detector.saveToFile("hazard_log.txt"); + + // Remove a specific hazard + cout << "\n=== MANUAL HAZARD REMOVAL ===" << endl; + detector.removeHazard(40, 20); + detector.displayStatus(); + + // O(1) performance demonstration + cout << "\n=== O(1) PERFORMANCE TEST ===" << endl; + cout << "Checking 10,000 random cells..." << endl; + + int hazardCount = 0; + for (int i = 0; i < 10000; i++) { + int x = i % 60; + int y = (i * 7) % 40; + if (detector.isHazard(x, y)) { + hazardCount++; + } + } + + cout << "Found " << hazardCount << " hazard hits in 10,000 O(1) lookups" << endl; + + cout << "\nโœ… Hazard Detection Demo Complete!\n" << endl; + + return 0; +} + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f117089 --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +# Makefile for Drone Telemetry Feature + +CXX = g++ +CXXFLAGS = -std=c++11 -Wall -Iinclude +SRC_DIR = src +INC_DIR = include +BUILD_DIR = build +TARGET = drone_telemetry + +# Source files +SOURCES = $(SRC_DIR)/main_telemetry.cpp \ + $(SRC_DIR)/DroneLogger.cpp \ + $(SRC_DIR)/WaypointBuffer.cpp \ + $(SRC_DIR)/FlightHashMap.cpp \ + $(SRC_DIR)/ErrorLog.cpp \ + $(SRC_DIR)/Quadcopter.cpp \ + $(SRC_DIR)/GPSData.cpp \ + $(SRC_DIR)/IMUData.cpp \ + $(SRC_DIR)/MotorControl.cpp + +# Object files +OBJECTS = $(SOURCES:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o) + +# Default target +all: $(BUILD_DIR) $(TARGET) + +# Create build directory +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +# Link +$(TARGET): $(OBJECTS) + $(CXX) $(OBJECTS) -o $(TARGET) + @echo "โœ… Build successful: $(TARGET)" + +# Compile source files +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Generate flight data +generate: + python3 GenerateDroneFlightData.py + +# Run the program +run: $(TARGET) generate + ./$(TARGET) + +# Clean build files +clean: + rm -rf $(BUILD_DIR) $(TARGET) DroneFlightLog.csv drone_errors.log + @echo "๐Ÿงน Cleaned build files" + +# Clean only generated data +clean-data: + rm -f DroneFlightLog.csv drone_errors.log + @echo "๐Ÿงน Cleaned data files" + +# Rebuild everything +rebuild: clean all + +# Help +help: + @echo "Available targets:" + @echo " make - Build the project" + @echo " make generate - Generate flight data (Python)" + @echo " make run - Generate data and run program" + @echo " make clean - Remove all build files and data" + @echo " make clean-data - Remove only generated data files" + @echo " make rebuild - Clean and rebuild" + @echo " make help - Show this help message" + +.PHONY: all clean clean-data rebuild generate run help + diff --git a/TelemetryLogger/DroneControl.h b/TelemetryLogger/DroneControl.h new file mode 100644 index 0000000..b7c9e5a --- /dev/null +++ b/TelemetryLogger/DroneControl.h @@ -0,0 +1,9 @@ +#ifndef DRONE_CONTROL_H +#define DRONE_CONTROL_H + +// Master header - includes all control components +#include "Quadcopter.h" +#include "MotorControl.h" + +#endif // DRONE_CONTROL_H + diff --git a/TelemetryLogger/DroneFlightLog.csv b/TelemetryLogger/DroneFlightLog.csv new file mode 100644 index 0000000..e5a735e --- /dev/null +++ b/TelemetryLogger/DroneFlightLog.csv @@ -0,0 +1,51 @@ +timestamp,latitude,longitude,altitude,roll,pitch,yaw,vel_x,vel_y,vel_z,battery,signal +1766341711.6105,33.68448728,73.04796899,0.00,-13.81,-5.15,26.57,4.09,1.80,-0.68,100.0,91.8 +1766341711.7105,33.68453953,73.04787125,2.50,14.69,-2.35,242.56,-1.45,-2.22,-0.01,98.4,99.2 +1766341711.8105,33.68445551,73.04785461,5.00,-14.99,14.35,307.74,4.09,-4.42,0.18,96.8,96.0 +1766341711.9105,33.68452601,73.04788045,7.50,0.92,0.76,197.48,4.42,1.59,0.58,95.2,82.4 +1766341712.0105,33.68460955,73.04781039,10.00,8.50,-10.67,359.11,-4.24,-1.75,-1.66,93.6,76.4 +1766341712.1105,33.68454290,73.04787003,12.50,5.48,-1.00,71.82,1.23,1.88,-1.83,92.0,94.6 +1766341712.2105,33.68451581,73.04792668,15.00,14.41,5.65,122.64,-2.36,-4.34,-0.21,90.4,91.9 +1766341712.3105,33.68456910,73.04798395,17.50,3.65,9.06,168.73,1.35,0.54,0.51,88.8,70.6 +1766341712.4105,33.68462706,73.04799990,20.00,1.65,-12.31,225.92,1.45,-2.31,1.29,87.2,71.5 +1766341712.5105,33.68459504,73.04809730,22.50,8.24,7.31,47.45,-0.00,-3.99,1.28,85.6,99.2 +1766341712.6105,33.68469026,73.04805622,23.14,-3.93,11.38,334.66,3.56,-0.86,-0.38,84.0,84.7 +1766341712.7105,33.68476245,73.04795899,24.25,8.60,12.18,178.58,4.44,-1.61,1.32,82.4,72.6 +1766341712.8105,33.68470843,73.04790171,24.15,8.33,5.89,278.74,0.28,3.77,-1.39,80.8,90.4 +1766341712.9105,33.68475885,73.04784274,26.96,5.21,9.87,79.01,-1.40,0.22,1.20,79.2,73.9 +1766341713.0105,33.68476802,73.04777223,23.02,6.06,-8.47,312.27,-3.47,-0.25,1.97,77.6,76.4 +1766341713.1105,33.68476418,73.04773716,25.85,11.59,-14.92,249.40,-3.50,2.23,-1.93,76.0,74.9 +1766341713.2105,33.68478991,73.04771140,25.42,-12.67,12.64,153.30,0.91,0.84,1.34,74.4,88.4 +1766341713.3105,33.68480074,73.04765199,24.66,2.89,-6.00,77.55,-4.63,-3.45,-1.36,72.8,83.4 +1766341713.4105,33.68483749,73.04762461,23.16,-2.16,-5.10,344.84,2.65,4.78,-0.42,71.2,70.8 +1766341713.5105,33.68481246,73.04764079,23.86,-1.99,13.92,191.13,1.00,4.47,0.66,69.6,97.7 +1766341713.6105,33.68472785,73.04765228,26.39,-10.15,-7.25,334.74,-3.43,2.14,-1.61,68.0,99.8 +1766341713.7105,33.68469699,73.04763990,23.36,4.81,14.79,186.19,-3.85,4.89,-0.09,66.4,73.0 +1766341713.8105,33.68477560,73.04771037,24.76,-3.96,-5.47,17.58,1.43,4.19,-1.84,64.8,83.6 +1766341713.9105,33.68484713,73.04772129,25.40,14.70,11.94,260.66,-1.33,-3.25,1.35,63.2,70.2 +1766341714.0115,33.68488074,73.04767914,25.73,4.81,12.64,87.97,-4.02,2.53,0.72,61.6,77.0 +1766341714.1115,33.68494015,73.04771756,23.54,2.44,-14.87,113.37,0.84,-1.15,-0.72,60.0,99.6 +1766341714.2115,33.68486705,73.04771120,23.13,9.75,13.23,40.42,0.83,-3.43,-1.15,58.4,73.0 +1766341714.3115,33.68482793,73.04775382,24.99,-10.87,-14.69,161.84,-1.51,-4.29,-0.13,56.8,96.7 +1766341714.4115,33.68477340,73.04782354,24.74,12.09,1.32,120.53,3.93,-2.72,0.15,55.2,93.7 +1766341714.5115,33.68475099,73.04791513,23.62,6.50,-9.02,161.96,4.96,-0.47,0.58,53.6,89.7 +1766341714.6115,33.68466301,73.04789038,25.14,6.27,6.18,59.59,-1.39,4.33,-1.95,52.0,83.8 +1766341714.7115,33.68459915,73.04788645,23.04,-4.18,-7.66,133.60,-4.23,1.20,0.48,50.4,90.8 +1766341714.8115,33.68456739,73.04793957,26.70,-14.30,2.35,37.58,-2.79,4.80,-1.16,48.8,78.6 +1766341714.9115,33.68448651,73.04784182,25.29,6.90,-7.63,16.49,-0.87,-1.43,-1.91,47.2,74.4 +1766341715.0115,33.68454483,73.04793978,23.03,1.75,13.48,181.72,3.55,3.18,1.91,45.6,90.4 +1766341715.1115,33.68459154,73.04785365,26.96,-14.88,-4.23,25.75,1.29,0.07,-0.07,44.0,82.5 +1766341715.2115,33.68452098,73.04794272,25.78,3.46,-13.50,254.30,-4.98,1.05,-0.36,42.4,95.5 +1766341715.3115,33.68446209,73.04801603,26.60,-2.49,-12.97,268.86,4.91,4.07,1.56,40.8,97.4 +1766341715.4115,33.68442470,73.04792286,25.46,-14.22,8.50,244.82,-2.42,4.62,0.13,39.2,84.8 +1766341715.5115,33.68447922,73.04790528,24.10,9.01,8.47,298.88,-0.17,-1.27,-1.91,37.6,94.0 +1766341715.6115,33.68446563,73.04793755,25.00,6.44,12.04,276.08,2.29,-2.62,-0.22,36.0,75.6 +1766341715.7115,33.68449425,73.04785884,22.50,12.72,-2.50,191.42,-0.85,4.17,-0.98,34.4,73.1 +1766341715.8115,33.68444151,73.04776929,20.00,-2.41,4.18,131.86,-4.74,2.10,-0.71,32.8,70.8 +1766341715.9115,33.68448948,73.04781345,17.50,2.74,13.74,345.64,4.97,1.84,2.00,31.2,94.8 +1766341716.0115,33.68452779,73.04782071,15.00,3.98,-1.57,199.00,-3.09,-0.61,-0.79,29.6,93.0 +1766341716.1115,33.68459839,73.04780535,12.50,-1.44,11.26,226.04,-1.73,-4.49,-0.31,28.0,84.7 +1766341716.2115,33.68454429,73.04775940,10.00,13.79,14.47,161.61,-1.35,-2.95,1.94,26.4,78.9 +1766341716.3115,33.68455002,73.04766259,7.50,8.27,-1.62,6.90,-1.80,1.67,0.19,24.8,90.8 +1766341716.4115,33.68447831,73.04763646,5.00,-5.68,-11.93,165.75,1.95,-2.61,-0.87,23.2,74.6 +1766341716.5115,33.68446931,73.04769871,2.50,9.49,-10.39,167.98,0.81,0.89,0.02,21.6,99.3 diff --git a/TelemetryLogger/DroneLogger.cpp b/TelemetryLogger/DroneLogger.cpp new file mode 100644 index 0000000..2dac959 --- /dev/null +++ b/TelemetryLogger/DroneLogger.cpp @@ -0,0 +1,217 @@ +#include "DroneLogger.h" +#include +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +FlightData::FlightData() + : timestamp(0), latitude(0), longitude(0), altitude(0), + roll(0), pitch(0), yaw(0), + vel_x(0), vel_y(0), vel_z(0), + battery(0), signal(0), + next(nullptr), prev(nullptr) {} + +DroneLogger::DroneLogger(std::string filename) + : head(nullptr), tail(nullptr), dataCount(0), logFilename(filename) { + std::cout << "๐Ÿ“‹ DroneLogger initialized for file: " << filename << std::endl; +} + +DroneLogger::~DroneLogger() { + FlightData* current = head; + while (current != nullptr) { + FlightData* next = current->next; + delete current; + current = next; + } +} + +void DroneLogger::ReadFromFile() { + std::ifstream file(logFilename); + + if (!file.is_open()) { + std::cerr << "โŒ Error: Cannot open " << logFilename << std::endl; + return; + } + + std::string line; + std::getline(file, line); // Skip header + + std::cout << "๐Ÿ“– Reading flight data..." << std::endl; + + while (std::getline(file, line)) { + FlightData* data = new FlightData(); + + std::stringstream ss(line); + std::string value; + + std::getline(ss, value, ','); data->timestamp = std::stod(value); + std::getline(ss, value, ','); data->latitude = std::stod(value); + std::getline(ss, value, ','); data->longitude = std::stod(value); + std::getline(ss, value, ','); data->altitude = std::stod(value); + std::getline(ss, value, ','); data->roll = std::stod(value); + std::getline(ss, value, ','); data->pitch = std::stod(value); + std::getline(ss, value, ','); data->yaw = std::stod(value); + std::getline(ss, value, ','); data->vel_x = std::stod(value); + std::getline(ss, value, ','); data->vel_y = std::stod(value); + std::getline(ss, value, ','); data->vel_z = std::stod(value); + std::getline(ss, value, ','); data->battery = std::stod(value); + std::getline(ss, value, ','); data->signal = std::stod(value); + + // Insert at tail (DOUBLY LINKED LIST) + if (head == nullptr) { + head = tail = data; + } else { + data->prev = tail; + tail->next = data; + tail = data; + } + + timestampCache[static_cast(data->timestamp)] = data; + dataCount++; + } + + file.close(); + std::cout << "โœ… Loaded " << dataCount << " flight data points" << std::endl; +} + +FlightData* DroneLogger::getLatestReading() { + return tail; +} + +std::vector DroneLogger::getLastNReadings(int N) { + std::vector result; + + if (tail == nullptr) return result; + + FlightData* current = tail; + int count = 0; + + // Traverse backward using PREV pointer + while (current != nullptr && count < N) { + result.push_back(*current); + current = current->prev; + count++; + } + + std::reverse(result.begin(), result.end()); + return result; +} + +double DroneLogger::MaxAltitude() { + double maxAlt = 0.0; + FlightData* current = head; + + while (current != nullptr) { + if (current->altitude > maxAlt) { + maxAlt = current->altitude; + } + current = current->next; + } + + return maxAlt; +} + +double DroneLogger::AverageVelocity() { + double sum = 0.0; + int count = 0; + FlightData* current = head; + + while (current != nullptr) { + double vel = std::sqrt( + current->vel_x * current->vel_x + + current->vel_y * current->vel_y + + current->vel_z * current->vel_z + ); + sum += vel; + count++; + current = current->next; + } + + return (count > 0) ? sum / count : 0.0; +} + +double DroneLogger::TotalDistance() { + double totalDist = 0.0; + FlightData* current = head; + + while (current != nullptr && current->next != nullptr) { + double lat1 = current->latitude; + double lon1 = current->longitude; + double lat2 = current->next->latitude; + double lon2 = current->next->longitude; + + double dlat = (lat2 - lat1) * 111000; + double dlon = (lon2 - lon1) * 111000 * std::cos(lat1 * M_PI / 180.0); + + double dist = std::sqrt(dlat*dlat + dlon*dlon); + totalDist += dist; + + current = current->next; + } + + return totalDist; +} + +void DroneLogger::DisplayAll() { + std::cout << "\n" << std::string(100, '=') << "\n"; + std::cout << "COMPLETE FLIGHT LOG\n"; + std::cout << std::string(100, '=') << "\n"; + + std::cout << std::setw(12) << "Time" + << std::setw(12) << "Lat" + << std::setw(12) << "Lon" + << std::setw(10) << "Alt(m)" + << std::setw(8) << "Roll" + << std::setw(8) << "Pitch" + << std::setw(8) << "Yaw" + << std::setw(10) << "Battery" + << "\n"; + std::cout << std::string(100, '-') << "\n"; + + FlightData* current = head; + while (current != nullptr) { + std::cout << std::fixed << std::setprecision(1); + std::cout << std::setw(12) << (int)current->timestamp + << std::setprecision(6) + << std::setw(12) << current->latitude + << std::setw(12) << current->longitude + << std::setprecision(1) + << std::setw(10) << current->altitude + << std::setw(8) << current->roll + << std::setw(8) << current->pitch + << std::setw(8) << current->yaw + << std::setw(10) << current->battery + << "\n"; + current = current->next; + } + + std::cout << std::string(100, '=') << "\n"; +} + +void DroneLogger::DisplayReverse(int N) { + std::cout << "\n=== REVERSE TRAVERSAL (Last " << N << " readings) ===\n"; + + FlightData* current = tail; + int count = 0; + + while (current != nullptr && count < N) { + std::cout << "T=" << (int)current->timestamp + << " Alt=" << current->altitude << "m" + << " Battery=" << current->battery << "%\n"; + current = current->prev; // DOUBLY LINKED LIST FEATURE + count++; + } + + std::cout << "\n"; +} + +int DroneLogger::getDataCount() const { + return dataCount; +} + diff --git a/TelemetryLogger/DroneLogger.h b/TelemetryLogger/DroneLogger.h new file mode 100644 index 0000000..aaa5e71 --- /dev/null +++ b/TelemetryLogger/DroneLogger.h @@ -0,0 +1,58 @@ +#ifndef DRONE_LOGGER_H +#define DRONE_LOGGER_H + +#include +#include +#include + +// Flight data structure with DOUBLY LINKED LIST +struct FlightData { + double timestamp; + double latitude; + double longitude; + double altitude; + double roll; + double pitch; + double yaw; + double vel_x; + double vel_y; + double vel_z; + double battery; + double signal; + + // DOUBLY LINKED LIST POINTERS + FlightData* next; + FlightData* prev; + + FlightData(); +}; + +// Main telemetry logger class +class DroneLogger { +private: + FlightData* head; + FlightData* tail; + std::unordered_map timestampCache; + int dataCount; + std::string logFilename; + +public: + DroneLogger(std::string filename = "DroneFlightLog.csv"); + ~DroneLogger(); + + void ReadFromFile(); + FlightData* getLatestReading(); + std::vector getLastNReadings(int N); + + double MaxAltitude(); + double AverageVelocity(); + double TotalDistance(); + + void DisplayAll(); + void DisplayReverse(int N = 10); + + int getDataCount() const; +}; + +#endif // DRONE_LOGGER_H + diff --git a/TelemetryLogger/DroneSensors.h b/TelemetryLogger/DroneSensors.h new file mode 100644 index 0000000..1daac6d --- /dev/null +++ b/TelemetryLogger/DroneSensors.h @@ -0,0 +1,9 @@ +#ifndef DRONE_SENSORS_H +#define DRONE_SENSORS_H + +// Master header - includes all sensor components +#include "GPSData.h" +#include "IMUData.h" + +#endif // DRONE_SENSORS_H + diff --git a/TelemetryLogger/ErrorLog.cpp b/TelemetryLogger/ErrorLog.cpp new file mode 100644 index 0000000..fb4f194 --- /dev/null +++ b/TelemetryLogger/ErrorLog.cpp @@ -0,0 +1,60 @@ +#include "ErrorLog.h" +#include +#include + +std::string ErrorLog::getCurrentTime() { + time_t now = time(nullptr); + char buffer[80]; + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localtime(&now)); + return std::string(buffer); +} + +ErrorLog::ErrorLog(std::string fname) : filename(fname) { + logFile.open(filename, std::ios::app); + if (!logFile.is_open()) { + std::cerr << "Warning: Cannot open error log file\n"; + } +} + +ErrorLog::~ErrorLog() { + if (logFile.is_open()) { + logFile.close(); + } +} + +void ErrorLog::warning(std::string message) { + std::string timestamp = getCurrentTime(); + std::string logEntry = "[" + timestamp + "] [WARNING] " + message; + + std::cout << "โš ๏ธ " << logEntry << std::endl; + + if (logFile.is_open()) { + logFile << logEntry << std::endl; + logFile.flush(); + } +} + +void ErrorLog::critical(std::string message) { + std::string timestamp = getCurrentTime(); + std::string logEntry = "[" + timestamp + "] [CRITICAL] " + message; + + std::cout << "๐Ÿšจ " << logEntry << std::endl; + + if (logFile.is_open()) { + logFile << logEntry << std::endl; + logFile.flush(); + } +} + +void ErrorLog::info(std::string message) { + std::string timestamp = getCurrentTime(); + std::string logEntry = "[" + timestamp + "] [INFO] " + message; + + std::cout << "โ„น๏ธ " << logEntry << std::endl; + + if (logFile.is_open()) { + logFile << logEntry << std::endl; + logFile.flush(); + } +} + diff --git a/TelemetryLogger/ErrorLog.h b/TelemetryLogger/ErrorLog.h new file mode 100644 index 0000000..2d4c320 --- /dev/null +++ b/TelemetryLogger/ErrorLog.h @@ -0,0 +1,25 @@ +#ifndef ERROR_LOG_H +#define ERROR_LOG_H + +#include +#include + +// Error logging to file and console +class ErrorLog { +private: + std::ofstream logFile; + std::string filename; + + std::string getCurrentTime(); + +public: + ErrorLog(std::string fname = "drone_errors.log"); + ~ErrorLog(); + + void warning(std::string message); + void critical(std::string message); + void info(std::string message); +}; + +#endif // ERROR_LOG_H + diff --git a/TelemetryLogger/FlightHashMap.cpp b/TelemetryLogger/FlightHashMap.cpp new file mode 100644 index 0000000..26b1660 --- /dev/null +++ b/TelemetryLogger/FlightHashMap.cpp @@ -0,0 +1,34 @@ +#include "FlightHashMap.h" +#include + +FlightHashMap::FlightHashMap() { + std::cout << "๐Ÿ—‚๏ธ FlightHashMap initialized\n"; +} + +void FlightHashMap::insert(std::string key, std::string value) { + dataMap[key] = value; +} + +std::string FlightHashMap::get(std::string key) { + if (dataMap.find(key) != dataMap.end()) { + return dataMap[key]; + } + return ""; +} + +bool FlightHashMap::exists(std::string key) { + return dataMap.find(key) != dataMap.end(); +} + +void FlightHashMap::displayAll() { + std::cout << "\n=== FlightHashMap Contents ===\n"; + for (auto& pair : dataMap) { + std::cout << pair.first << " => " << pair.second << "\n"; + } + std::cout << "\n"; +} + +int FlightHashMap::size() const { + return dataMap.size(); +} + diff --git a/TelemetryLogger/FlightHashMap.h b/TelemetryLogger/FlightHashMap.h new file mode 100644 index 0000000..8bd86f6 --- /dev/null +++ b/TelemetryLogger/FlightHashMap.h @@ -0,0 +1,24 @@ +#ifndef FLIGHT_HASHMAP_H +#define FLIGHT_HASHMAP_H + +#include +#include + +// Fast retrieval using hash map +class FlightHashMap { +private: + std::unordered_map dataMap; + +public: + FlightHashMap(); + + void insert(std::string key, std::string value); + std::string get(std::string key); + bool exists(std::string key); + void displayAll(); + + int size() const; +}; + +#endif // FLIGHT_HASHMAP_H + diff --git a/TelemetryLogger/GPSData.cpp b/TelemetryLogger/GPSData.cpp new file mode 100644 index 0000000..5487170 --- /dev/null +++ b/TelemetryLogger/GPSData.cpp @@ -0,0 +1,40 @@ +#include "GPSData.h" +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +GPSCoordinate::GPSCoordinate(double lat, double lon, double alt) + : latitude(lat), longitude(lon), altitude(alt) {} + +double GPSCoordinate::distanceTo(const GPSCoordinate& other) const { + // Haversine formula for great-circle distance + double lat1 = latitude * M_PI / 180.0; + double lat2 = other.latitude * M_PI / 180.0; + double lon1 = longitude * M_PI / 180.0; + double lon2 = other.longitude * M_PI / 180.0; + + double dlat = lat2 - lat1; + double dlon = lon2 - lon1; + + double a = std::sin(dlat/2) * std::sin(dlat/2) + + std::cos(lat1) * std::cos(lat2) * + std::sin(dlon/2) * std::sin(dlon/2); + double c = 2 * std::atan2(std::sqrt(a), std::sqrt(1-a)); + + // Earth radius in meters + double earthRadius = 6371000.0; + double distance = earthRadius * c; + + // Add altitude difference + double altDiff = std::abs(altitude - other.altitude); + return std::sqrt(distance * distance + altDiff * altDiff); +} + +void GPSCoordinate::display() const { + std::cout << "GPS: (" << latitude << ", " << longitude + << ") Alt: " << altitude << "m" << std::endl; +} + diff --git a/TelemetryLogger/GPSData.h b/TelemetryLogger/GPSData.h new file mode 100644 index 0000000..d510647 --- /dev/null +++ b/TelemetryLogger/GPSData.h @@ -0,0 +1,16 @@ +#ifndef GPS_DATA_H +#define GPS_DATA_H + +// GPS coordinate structure +struct GPSCoordinate { + double latitude; + double longitude; + double altitude; + + GPSCoordinate(double lat = 0.0, double lon = 0.0, double alt = 0.0); + double distanceTo(const GPSCoordinate& other) const; + void display() const; +}; + +#endif // GPS_DATA_H + diff --git a/TelemetryLogger/GenerateDroneFlightData.py b/TelemetryLogger/GenerateDroneFlightData.py new file mode 100644 index 0000000..fdf0dd6 --- /dev/null +++ b/TelemetryLogger/GenerateDroneFlightData.py @@ -0,0 +1,71 @@ +import time +import random +import math + +START_LAT = 33.6844 +START_LON = 73.0479 +NUM_WAYPOINTS = 50 + +waypoints = [] +current_lat = START_LAT +current_lon = START_LON +current_alt = 0.0 + +for i in range(NUM_WAYPOINTS): + timestamp = time.time() + i * 0.1 + + current_lat += random.uniform(-0.0001, 0.0001) + current_lon += random.uniform(-0.0001, 0.0001) + + if i < NUM_WAYPOINTS * 0.2: + current_alt = i * 2.5 + elif i < NUM_WAYPOINTS * 0.8: + current_alt = 25.0 + random.uniform(-2, 2) + else: + descent = (i - NUM_WAYPOINTS * 0.8) / (NUM_WAYPOINTS * 0.2) + current_alt = 25.0 * (1 - descent) + + roll = random.uniform(-15, 15) + pitch = random.uniform(-15, 15) + yaw = random.uniform(0, 360) + vel_x = random.uniform(-5, 5) + vel_y = random.uniform(-5, 5) + vel_z = random.uniform(-2, 2) + battery = 100 - (i / NUM_WAYPOINTS) * 80 + signal = random.uniform(70, 100) + + waypoints.append({ + 'timestamp': timestamp, + 'latitude': current_lat, + 'longitude': current_lon, + 'altitude': current_alt, + 'roll': roll, + 'pitch': pitch, + 'yaw': yaw, + 'vel_x': vel_x, + 'vel_y': vel_y, + 'vel_z': vel_z, + 'battery': battery, + 'signal': signal + }) + +with open("DroneFlightLog.csv", "w") as f: + f.write("timestamp,latitude,longitude,altitude,roll,pitch,yaw,") + f.write("vel_x,vel_y,vel_z,battery,signal\n") + + for wp in waypoints: + f.write(f"{wp['timestamp']:.4f},") + f.write(f"{wp['latitude']:.8f},") + f.write(f"{wp['longitude']:.8f},") + f.write(f"{wp['altitude']:.2f},") + f.write(f"{wp['roll']:.2f},") + f.write(f"{wp['pitch']:.2f},") + f.write(f"{wp['yaw']:.2f},") + f.write(f"{wp['vel_x']:.2f},") + f.write(f"{wp['vel_y']:.2f},") + f.write(f"{wp['vel_z']:.2f},") + f.write(f"{wp['battery']:.1f},") + f.write(f"{wp['signal']:.1f}\n") + +print(f"Generated {NUM_WAYPOINTS} waypoints -> DroneFlightLog.csv") + diff --git a/TelemetryLogger/IMUData.cpp b/TelemetryLogger/IMUData.cpp new file mode 100644 index 0000000..1705bd1 --- /dev/null +++ b/TelemetryLogger/IMUData.cpp @@ -0,0 +1,18 @@ +#include "IMUData.h" +#include +#include + +IMUData::IMUData(double r, double p, double y) + : roll(r), pitch(p), yaw(y) {} + +void IMUData::display() const { + std::cout << "IMU: Roll=" << roll << "ยฐ Pitch=" << pitch + << "ยฐ Yaw=" << yaw << "ยฐ" << std::endl; +} + +bool IMUData::isLevel() const { + const double LEVEL_THRESHOLD = 5.0; // degrees + return std::abs(roll) < LEVEL_THRESHOLD && + std::abs(pitch) < LEVEL_THRESHOLD; +} + diff --git a/TelemetryLogger/IMUData.h b/TelemetryLogger/IMUData.h new file mode 100644 index 0000000..7799def --- /dev/null +++ b/TelemetryLogger/IMUData.h @@ -0,0 +1,16 @@ +#ifndef IMU_DATA_H +#define IMU_DATA_H + +// IMU (Inertial Measurement Unit) data +struct IMUData { + double roll; + double pitch; + double yaw; + + IMUData(double r = 0.0, double p = 0.0, double y = 0.0); + void display() const; + bool isLevel() const; +}; + +#endif // IMU_DATA_H + diff --git a/TelemetryLogger/Makefile b/TelemetryLogger/Makefile new file mode 100644 index 0000000..64226aa --- /dev/null +++ b/TelemetryLogger/Makefile @@ -0,0 +1,57 @@ +# Makefile for Telemetry Logger Feature + +CXX = g++ +CXXFLAGS = -std=c++11 -Wall -I. +TARGET = drone_telemetry + +# Source files +SOURCES = main_telemetry.cpp \ + DroneLogger.cpp \ + WaypointBuffer.cpp \ + FlightHashMap.cpp \ + ErrorLog.cpp \ + Quadcopter.cpp \ + GPSData.cpp \ + IMUData.cpp \ + MotorControl.cpp + +# Object files +OBJECTS = $(SOURCES:.cpp=.o) + +# Default target +all: $(TARGET) + @echo "โœ… Build successful: $(TARGET)" + +# Build executable +$(TARGET): $(OBJECTS) + $(CXX) $(OBJECTS) -o $(TARGET) + +# Compile objects +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Generate flight data +generate: + python3 GenerateDroneFlightData.py + @echo "โœ… Generated DroneFlightLog.csv" + +# Run the program +run: $(TARGET) generate + ./$(TARGET) + +# Clean build files +clean: + rm -f $(OBJECTS) $(TARGET) DroneFlightLog.csv drone_errors.log + @echo "๐Ÿงน Cleaned build files" + +# Help +help: + @echo "Available targets:" + @echo " make - Build the drone_telemetry executable" + @echo " make generate - Run Python script to create DroneFlightLog.csv" + @echo " make run - Build, generate data, and run" + @echo " make clean - Remove build artifacts" + @echo " make help - Show this help message" + +.PHONY: all generate run clean help + diff --git a/TelemetryLogger/MotorControl.cpp b/TelemetryLogger/MotorControl.cpp new file mode 100644 index 0000000..1a4091e --- /dev/null +++ b/TelemetryLogger/MotorControl.cpp @@ -0,0 +1,22 @@ +#include "MotorControl.h" + +namespace MotorControl { + double calculatePWM(double base, double rollCorrection, double pitchCorrection) { + double pwm = base + rollCorrection + pitchCorrection; + + // Clamp to valid range + if (pwm < 0.0) pwm = 0.0; + if (pwm > 100.0) pwm = 100.0; + + return pwm; + } + + bool isSafePWM(double pwm) { + return pwm >= 0.0 && pwm <= 100.0; + } + + void emergencyStop(double& pwm) { + pwm = 0.0; + } +} + diff --git a/TelemetryLogger/MotorControl.h b/TelemetryLogger/MotorControl.h new file mode 100644 index 0000000..86bfe6a --- /dev/null +++ b/TelemetryLogger/MotorControl.h @@ -0,0 +1,12 @@ +#ifndef MOTOR_CONTROL_H +#define MOTOR_CONTROL_H + +// Motor control utility functions +namespace MotorControl { + double calculatePWM(double base, double rollCorrection, double pitchCorrection); + bool isSafePWM(double pwm); + void emergencyStop(double& pwm); +} + +#endif // MOTOR_CONTROL_H + diff --git a/TelemetryLogger/Quadcopter.cpp b/TelemetryLogger/Quadcopter.cpp new file mode 100644 index 0000000..1b792d1 --- /dev/null +++ b/TelemetryLogger/Quadcopter.cpp @@ -0,0 +1,63 @@ +#include "Quadcopter.h" +#include + +Motor::Motor(int id) + : motorID(id), currentPWM(0), targetPWM(0), isActive(false) {} + +void Motor::setPWM(double pwm) { + if (pwm < 0) pwm = 0; + if (pwm > 100) pwm = 100; + targetPWM = pwm; + currentPWM = pwm; +} + +void Motor::display() { + std::cout << "Motor " << motorID << ": " + << currentPWM << "% PWM " + << (isActive ? "[ACTIVE]" : "[IDLE]") << "\n"; +} + +QuadcopterSystem::QuadcopterSystem(int num) : numMotors(num) { + for (int i = 0; i < numMotors; i++) { + motors.push_back(Motor(i + 1)); + } + std::cout << "๐Ÿš Quadcopter initialized with " << numMotors << " motors\n"; +} + +void QuadcopterSystem::armMotors() { + std::cout << "๐Ÿ”ง Arming motors...\n"; + for (auto& motor : motors) { + motor.isActive = true; + motor.setPWM(10.0); + } +} + +void QuadcopterSystem::disarmMotors() { + std::cout << "๐Ÿ”’ Disarming motors...\n"; + for (auto& motor : motors) { + motor.isActive = false; + motor.setPWM(0.0); + } +} + +void QuadcopterSystem::stabilize(double roll, double pitch) { + double basePWM = 50.0; + double rollCorrection = roll * 0.5; + double pitchCorrection = pitch * 0.5; + + if (motors.size() >= 4) { + motors[0].setPWM(basePWM - rollCorrection - pitchCorrection); // FL + motors[1].setPWM(basePWM + rollCorrection - pitchCorrection); // FR + motors[2].setPWM(basePWM + rollCorrection + pitchCorrection); // RR + motors[3].setPWM(basePWM - rollCorrection + pitchCorrection); // RL + } +} + +void QuadcopterSystem::displayStatus() { + std::cout << "\n--- Quadcopter Status ---\n"; + for (auto& motor : motors) { + motor.display(); + } + std::cout << "\n"; +} + diff --git a/TelemetryLogger/Quadcopter.h b/TelemetryLogger/Quadcopter.h new file mode 100644 index 0000000..5d65827 --- /dev/null +++ b/TelemetryLogger/Quadcopter.h @@ -0,0 +1,34 @@ +#ifndef QUADCOPTER_H +#define QUADCOPTER_H + +#include + +// Individual motor +struct Motor { + int motorID; + double currentPWM; + double targetPWM; + bool isActive; + + Motor(int id); + void setPWM(double pwm); + void display(); +}; + +// Quadcopter control system +class QuadcopterSystem { +private: + std::vector motors; + int numMotors; + +public: + QuadcopterSystem(int num = 4); + + void armMotors(); + void disarmMotors(); + void stabilize(double roll, double pitch); + void displayStatus(); +}; + +#endif // QUADCOPTER_H + diff --git a/TelemetryLogger/README.md b/TelemetryLogger/README.md new file mode 100644 index 0000000..5aa432e --- /dev/null +++ b/TelemetryLogger/README.md @@ -0,0 +1,150 @@ +# Drone Telemetry Logger System + +## Overview + +Comprehensive telemetry logging and flight data management system for drone operations. Tracks flight data, manages waypoints, logs errors, and simulates drone control systems. + +## Features + +### Data Structures +- **Doubly Linked List** - Flight data with bidirectional traversal +- **Singly Linked List** - Waypoint buffer for navigation points +- **Hash Map** - Fast flight data retrieval by timestamp +- **Vector** - Motor control and sensor data storage + +### Core Components + +#### TelemetryLogger (Master Header) +- `DroneLogger` - Main flight data logger with CSV I/O +- `WaypointBuffer` - Navigation waypoint management +- `FlightHashMap` - Fast data lookup and caching +- `ErrorLog` - File and console error logging + +#### DroneControl (Master Header) +- `QuadcopterSystem` - Multi-motor quadcopter control +- `MotorControl` - PWM calculation and safety checks + +#### DroneSensors (Master Header) +- `GPSData` - GPS coordinate tracking with distance calculations +- `IMUData` - Inertial measurement unit (roll, pitch, yaw) + +## File Structure + +``` +TelemetryLogger/ +โ”œโ”€โ”€ TelemetryLogger.h - Master header (logger components) +โ”œโ”€โ”€ DroneControl.h - Master header (control components) +โ”œโ”€โ”€ DroneSensors.h - Master header (sensor components) +โ”œโ”€โ”€ DroneLogger.h - Flight data logger interface +โ”œโ”€โ”€ DroneLogger.cpp - Flight data logger implementation +โ”œโ”€โ”€ WaypointBuffer.h - Waypoint buffer interface +โ”œโ”€โ”€ WaypointBuffer.cpp - Waypoint buffer implementation +โ”œโ”€โ”€ FlightHashMap.h - Hash map interface +โ”œโ”€โ”€ FlightHashMap.cpp - Hash map implementation +โ”œโ”€โ”€ ErrorLog.h - Error logging interface +โ”œโ”€โ”€ ErrorLog.cpp - Error logging implementation +โ”œโ”€โ”€ Quadcopter.h - Quadcopter system interface +โ”œโ”€โ”€ Quadcopter.cpp - Quadcopter system implementation +โ”œโ”€โ”€ MotorControl.h - Motor control utilities +โ”œโ”€โ”€ MotorControl.cpp - Motor control implementation +โ”œโ”€โ”€ GPSData.h - GPS data interface +โ”œโ”€โ”€ GPSData.cpp - GPS data implementation +โ”œโ”€โ”€ IMUData.h - IMU data interface +โ”œโ”€โ”€ IMUData.cpp - IMU data implementation +โ”œโ”€โ”€ main_telemetry.cpp - Main program entry point +โ”œโ”€โ”€ GenerateDroneFlightData.py - Flight data generator +โ”œโ”€โ”€ Makefile - Build system +โ””โ”€โ”€ README.md - This file +``` + +## Build Instructions + +### Prerequisites +- C++11 or later compiler (g++ recommended) +- Python 3.x (for data generation) +- Make utility + +### Building + +```bash +cd TelemetryLogger +make # Build the executable +make generate # Generate flight data +make run # Build, generate, and run +make clean # Remove build artifacts +``` + +## Usage + +1. **Generate Flight Data**: + ```bash + make generate + ``` + Creates `DroneFlightLog.csv` with 50 waypoints + +2. **Run the Program**: + ```bash + make run + ``` + Or build and run separately: + ```bash + make + ./drone_telemetry + ``` + +3. **Clean Build Files**: + ```bash + make clean + ``` + +## Data Flow + +``` +main_telemetry.cpp + โ†“ includes + โ”œโ”€โ–บ TelemetryLogger.h (Master) + โ”‚ โ†“ includes + โ”‚ โ”œโ”€โ–บ DroneLogger.h โ†’ DroneLogger.cpp + โ”‚ โ”œโ”€โ–บ WaypointBuffer.h โ†’ WaypointBuffer.cpp + โ”‚ โ”œโ”€โ–บ FlightHashMap.h โ†’ FlightHashMap.cpp + โ”‚ โ””โ”€โ–บ ErrorLog.h โ†’ ErrorLog.cpp + โ”‚ + โ”œโ”€โ–บ DroneControl.h (Master) + โ”‚ โ†“ includes + โ”‚ โ”œโ”€โ–บ Quadcopter.h โ†’ Quadcopter.cpp + โ”‚ โ””โ”€โ–บ MotorControl.h โ†’ MotorControl.cpp + โ”‚ + โ””โ”€โ–บ DroneSensors.h (Master) + โ†“ includes + โ”œโ”€โ–บ GPSData.h โ†’ GPSData.cpp + โ””โ”€โ–บ IMUData.h โ†’ IMUData.cpp +``` + +## Performance + +- **Flight Data Loading**: O(N) where N = number of data points +- **Waypoint Insert**: O(1) - Insert at tail +- **Hash Map Lookup**: O(1) average case +- **Reverse Traversal**: O(N) - Using doubly linked list prev pointers +- **Distance Calculation**: O(1) - Haversine formula + +## Output Files + +- `DroneFlightLog.csv` - Generated flight data (timestamp, GPS, IMU, battery, etc.) +- `drone_errors.log` - Error and info log entries with timestamps +- `drone_telemetry` - Compiled executable + +## Key Algorithms + +- **Haversine Formula** - GPS distance calculation between coordinates +- **Doubly Linked List** - Bidirectional traversal for efficient reverse access +- **Hash Map** - Fast timestamp-based data retrieval +- **PWM Control** - Motor stabilization with roll/pitch corrections + +## Requirements + +- C++11 or later +- Python 3.x (for data generation) +- Make utility +- Standard C++ libraries (iostream, fstream, vector, unordered_map, etc.) + diff --git a/TelemetryLogger/TelemetryLogger.h b/TelemetryLogger/TelemetryLogger.h new file mode 100644 index 0000000..61f70d7 --- /dev/null +++ b/TelemetryLogger/TelemetryLogger.h @@ -0,0 +1,11 @@ +#ifndef TELEMETRY_LOGGER_H +#define TELEMETRY_LOGGER_H + +// Master header - includes all logger components +#include "DroneLogger.h" +#include "WaypointBuffer.h" +#include "FlightHashMap.h" +#include "ErrorLog.h" + +#endif // TELEMETRY_LOGGER_H + diff --git a/TelemetryLogger/WaypointBuffer.cpp b/TelemetryLogger/WaypointBuffer.cpp new file mode 100644 index 0000000..f4ae89e --- /dev/null +++ b/TelemetryLogger/WaypointBuffer.cpp @@ -0,0 +1,55 @@ +#include "WaypointBuffer.h" +#include + +WaypointNode::WaypointNode(double lat, double lon, double alt) + : latitude(lat), longitude(lon), altitude(alt), next(nullptr) {} + +WaypointBuffer::WaypointBuffer() + : head(nullptr), tail(nullptr), count(0) {} + +WaypointBuffer::~WaypointBuffer() { + WaypointNode* current = head; + while (current != nullptr) { + WaypointNode* next = current->next; + delete current; + current = next; + } +} + +void WaypointBuffer::Insert(double lat, double lon, double alt) { + WaypointNode* newNode = new WaypointNode(lat, lon, alt); + + if (head == nullptr) { + head = tail = newNode; + } else { + tail->next = newNode; + tail = newNode; + } + + count++; +} + +void WaypointBuffer::Display() { + std::cout << "Waypoint Buffer (" << count << " points):\n"; + + WaypointNode* current = head; + int index = 0; + + while (current != nullptr) { + std::cout << " [" << index << "] " + << "Lat: " << current->latitude << ", " + << "Lon: " << current->longitude << ", " + << "Alt: " << current->altitude << "m\n"; + current = current->next; + index++; + } +} + +int WaypointBuffer::getCount() const { + return count; +} + +WaypointNode* WaypointBuffer::getHead() const { + return head; +} + diff --git a/TelemetryLogger/WaypointBuffer.h b/TelemetryLogger/WaypointBuffer.h new file mode 100644 index 0000000..a932303 --- /dev/null +++ b/TelemetryLogger/WaypointBuffer.h @@ -0,0 +1,32 @@ +#ifndef WAYPOINT_BUFFER_H +#define WAYPOINT_BUFFER_H + +// Simple waypoint buffer using singly linked list +struct WaypointNode { + double latitude; + double longitude; + double altitude; + WaypointNode* next; + + WaypointNode(double lat, double lon, double alt); +}; + +class WaypointBuffer { +private: + WaypointNode* head; + WaypointNode* tail; + int count; + +public: + WaypointBuffer(); + ~WaypointBuffer(); + + void Insert(double lat, double lon, double alt); + void Display(); + + int getCount() const; + WaypointNode* getHead() const; +}; + +#endif // WAYPOINT_BUFFER_H + diff --git a/TelemetryLogger/main_telemetry.cpp b/TelemetryLogger/main_telemetry.cpp new file mode 100644 index 0000000..da25383 --- /dev/null +++ b/TelemetryLogger/main_telemetry.cpp @@ -0,0 +1,91 @@ +#include +#include + +// Cross-platform sleep +#ifdef _WIN32 +#include +#define sleep_for(ms) Sleep(ms) +#else +#include +#define sleep_for(ms) usleep((ms) * 1000) +#endif + +// Only 3 master includes +#include "TelemetryLogger.h" +#include "DroneControl.h" +#include "DroneSensors.h" + +int main() { + std::cout << "\n============================================\n"; + std::cout << " DRONE TELEMETRY SYSTEM - D-1 FEATURE\n"; + std::cout << "============================================\n\n"; + + ErrorLog errorLog; + errorLog.info("System startup initiated"); + + DroneLogger logger("DroneFlightLog.csv"); + logger.ReadFromFile(); + errorLog.info("Flight data loaded successfully"); + + std::vector last10 = logger.getLastNReadings(10); + + std::cout << "\n=== Last 10 Flight Readings ===\n"; + for (size_t i = 0; i < last10.size(); i++) { + std::cout << "[" << i << "] Alt: " << last10[i].altitude << "m, " + << "Battery: " << last10[i].battery << "%\n"; + } + + QuadcopterSystem drone(4); + drone.armMotors(); + + WaypointBuffer buffer; + for (auto& data : last10) { + buffer.Insert(data.latitude, data.longitude, data.altitude); + } + buffer.Display(); + + std::cout << "\n=== FLIGHT SIMULATION ===\n"; + + bool landed = false; + int iteration = 0; + FlightHashMap flightCache; + + while (!landed && iteration < static_cast(last10.size())) { + FlightData& current = last10[iteration]; + + std::cout << "Iteration " << iteration << ":\n"; + std::cout << " Alt: " << current.altitude << "m, Battery: " + << current.battery << "%\n"; + + drone.stabilize(current.roll, current.pitch); + + std::string key = "T_" + std::to_string(iteration); + flightCache.insert(key, "Alt:" + std::to_string(current.altitude)); + + if (current.altitude < 1.0 || current.battery < 25.0) { + landed = true; + std::cout << "๐Ÿ›ฌ Landing...\n"; + } + + sleep_for(500); + iteration++; + } + + drone.disarmMotors(); + + std::cout << "\n" << std::string(60, '=') << "\n"; + std::cout << "STATISTICS\n"; + std::cout << std::string(60, '=') << "\n"; + std::cout << "Max Altitude: " << logger.MaxAltitude() << "m\n"; + std::cout << "Avg Velocity: " << logger.AverageVelocity() << " m/s\n"; + std::cout << "Total Distance: " << logger.TotalDistance() << "m\n"; + std::cout << std::string(60, '=') << "\n"; + + logger.DisplayReverse(5); + + errorLog.info("Mission completed"); + std::cout << "\nโœ… Complete!\n\n"; + + return 0; +} + diff --git a/drone_errors.log b/drone_errors.log new file mode 100644 index 0000000..5814ac6 --- /dev/null +++ b/drone_errors.log @@ -0,0 +1,9 @@ +[2025-12-21 02:17:07] [INFO] System startup initiated +[2025-12-21 02:17:07] [INFO] Flight data loaded successfully +[2025-12-21 02:17:11] [INFO] Mission completed +[2025-12-21 02:20:53] [INFO] System startup initiated +[2025-12-21 02:20:53] [INFO] Flight data loaded successfully +[2025-12-21 02:20:57] [INFO] Mission completed +[2025-12-21 02:20:57] [INFO] System startup initiated +[2025-12-21 02:20:57] [INFO] Flight data loaded successfully +[2025-12-21 02:21:01] [INFO] Mission completed