{"id":22733833,"url":"https://github.com/samthinkgit/jorgescript","last_synced_at":"2026-07-03T10:02:40.625Z","repository":{"id":267429654,"uuid":"901217610","full_name":"SamthinkGit/jorgescript","owner":"SamthinkGit","description":null,"archived":false,"fork":false,"pushed_at":"2024-12-23T17:53:28.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-05T04:32:30.877Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SamthinkGit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-10T08:56:54.000Z","updated_at":"2024-12-23T17:53:31.000Z","dependencies_parsed_at":"2025-02-05T04:42:26.971Z","dependency_job_id":null,"html_url":"https://github.com/SamthinkGit/jorgescript","commit_stats":null,"previous_names":["samthinkgit/jorgescript"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamthinkGit%2Fjorgescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamthinkGit%2Fjorgescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamthinkGit%2Fjorgescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamthinkGit%2Fjorgescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SamthinkGit","download_url":"https://codeload.github.com/SamthinkGit/jorgescript/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246266245,"owners_count":20749754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-10T20:16:21.505Z","updated_at":"2026-07-03T10:02:35.596Z","avatar_url":"https://github.com/SamthinkGit.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cdiv align=\"center\"\u003eJorgeScript 🚀\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExZTY3aXo0MGpxbHc2aGNvcDNkMWd4cmZyNDd0eTFrZXVpY20ybGM2ZCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/BzDvnHUHdcinvusgn5/giphy.webp\" alt=\"Racing Gif\" width=450\u003e\n\n|       |                                                                                                                                                                        |\n| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Code  | ![GitHub](https://img.shields.io/badge/License-Proprietary-blue) ![GitHub](https://img.shields.io/badge/Version-1.0-blue) ![GitHub](https://img.shields.io/badge/release-done-orange) ![GitHub](https://img.shields.io/badge/docs-README-white) ![GitHub](https://img.shields.io/badge/Tasks-FreeRTOS-green)|\n\u003c/div\u003e\n\n\u003cimg src=\"https://user-images.githubusercontent.com/73097560/115834477-dbab4500-a447-11eb-908a-139a6edaec5c.gif\"\u003e\u003cbr\u003e\u003cbr\u003e\n\n# Practice 4: Line Following\n\nThis README describes the implementation of Practice 4, aimed at designing a line-following system using Arduino and ESP. Below, you will find details about the components used, the code structure, and the implemented functionalities.\n\n---\n\n## 🔧 System Description\n\nThe system is designed to follow a line using an Arduino UNO and communicates with an ESP to manage critical events. It includes:\n\n| **Component**         | **Function**                                                                                   |\n|-----------------------|-----------------------------------------------------------------------------------------------|\n| Kalman Filter         | Reduces sensor noise and improves precise line detection.                                    |\n| PID Controller        | Adjusts motor speeds to keep the vehicle on the line.                                        |\n| Obstacle Detection    | Avoids collisions by detecting objects on the vehicle's path.                                |\n| Task System           | Divides the code into independent modules for better efficiency and organization.            |\n| Indicator LEDs        | Provide real-time visual information about the system's status.                              |\n| Communication Protocol| Maintains a system report updated using MQTT                                                |\n\n\n---\n\n## 🌐 Arduino-ESP Communication\n\nCommunication between the Arduino and the ESP is done via the serial port using a structured message protocol. This allows coordination of key system events:\n\n| **Message**                  | **Description**                                                                         |\n|-------------------------------|-----------------------------------------------------------------------------------------|\n| `\u003cLINE_LOST:0\u003e`              | Indicates the line has been lost.                                                      |\n| `\u003cLINE_FOUND:0\u003e`             | Indicates the line has been found.                                                     |\n| `\u003cOBSTACLE_DETECTED:dist\u003e`   | Reports an obstacle detected at a distance `dist`.                                     |\n| `\u003cVISIBLE_LINE:perc\u003e`        | Indicates the percentage of visible line during a lap.                                 |\n| `\u003cEND_LAP:0\u003e`                | Marks the end of a lap.                                                                |\n\nFor the communication we are using a simple handcrafted protocol:\n```python \n\"\u003cOBSTACLE_DISTANCE:7\u003e\"\n```\n- **Message structure:**\n  1. Before colon is the type of message.\n  2. After colon is the value if needed, if not is set to 0.\n \n- **Delimiter:**\n  1. The message starts with a '\u003c' and ends '\u003e', with this we ensure the message arrived correctly.\n\n### Protocol Implementation\n\n1. **Message sending**\n   Arduino sends message through serial port every time it needs to communicate with MQTT.\n\n2. **Message receiving**\n   Esp32 loop is always checking for new data, before processing it, the message is checked.\n\n3. **Initialization**\n  - Esp32 sends a message when the WiFi and MQTT is ready to work.\n  - In Arduino's setup the a clausele which doesn't start until this message arrives.\n\n### Problems\n\nMost of the problems of the serial communication are related to secure the message goes in time and also are taken the right way. For example the int value will corrupt first test of the serial.\n\n\n## MQTT\n\nMQTT is used to update a topic about what the robot is doing. This can range from starting the lap to losing the line.\nFor the requirements of the practice, messages are sent as JSON. These JSON structures are provided by the professor as a requirement for the practice. Here's an example:\n\n```json\n{\n\t\"team_name\": \"$YOUR_TEAM_NAME\",\n\t\"id\": \"$TEAM_ID\",\n\t\"action\": \"START_LAP\"\n}\n```\n\n### Class\n\nTo simplify the use of MQTT, we implemented a small class called MqttSetr. This class includes encapsulated methods for a faster approach. The methods and constructor are as follows:\n\n```c++\nMqttSetr(char*, int, char*, char*);  // MqttSetr(ip_of_server , server_port, user, password);\nvoid reconnect();\nbool publish(char*);\nvoid recive();\nbool ready();\n```\n\n### Implementation\n\nThe MQTT implementation is only on the ESP32. The complete process to send a message is as follows:\n\n1. Receive the message from serial without processing.\n2. Process the message to extract the information.\n3. Convert the information into a JSON object.\n4. Serialize the JSON object to create a char*.\n5. Send the serialized JSON to the pre-established topic.\n\nFor creating JSON objects, we used the ArduinoJson [library](https://arduinojson.org) .\n\n### Problems\n\nThe main problems with MQTT were related to understanding the [Adafruit MQTT Library](https://docs.arduino.cc/libraries/adafruit-mqtt-library/).\n\n---\n\n## 🔨 Navigation\n\nBelow are the three different implemented approaches for line following:\n\n1. **WeightDetector**: This method assigned turn probabilities to each sensor based on the system's global state and perception time. A sigmoid function was then used to translate these weights into control speeds. This approach was very efficient for complex turns (example below), but when the line to follow was too thin, the weights' responsiveness was too slow.\n2. **FastDetector**: An optimized, case-based implementation replicating the weight system with manually adjusted values. However, this option was extremely sensitive to noise.\n3. **Kalman Filter**: Finally, this approach was chosen for its balance between speed and robustness. Using the data (weights) from the first method, a system was modeled to track the line and dynamically update using Kalman.\n\n### 3. **Kalman Filter**:\n\nThe Kalman filter was chosen for its balance between speed and robustness. This method leverages data obtained from **ITR20001** sensors connected to analog pins A0, A1, and A2, modeling a system that continuously predicts and updates the line’s position. The implementation follows these key steps:\n\n#### **Prediction and Update**\n1. **Prediction**: Using the system model, the Kalman filter estimates the next state of the line (i.e., its expected position). This calculation relies solely on previous states.\n\n2. **Update**: When new sensor readings arrive, they are compared to the prediction. The filter adjusts its current estimate based on the discrepancy between the expected and measured values. This adjustment includes a gain factor that prioritizes reliable readings over noise.\n\n```cpp\n\n// Convert sensor detection to weights (FSM methodology)\nfloat measurement = detector.measure(); \n\n// Predict the next state\ndetector.predict();\n\n// Compare the prediction to the detection\ndetector.update(measurement);\n\n// Get a new estimation\nfloat position_estimate = detector.getEstimate();\n```\n\n#### **Behavior During Line Loss**\nWhen the line is completely lost (no sensor detects the line), the Kalman filter does not interfere. Instead, control shifts to the **PID controller**, where the integrator takes full action. This allows the system to recover the line quickly using accumulated control values. The Kalman filter is designed to \"step back\" in these moments, avoiding additional noise or overcomplications during the correction process.\n\n\u003e Note: This methodology has been accomplished by adapting an online tutorial in [this page](https://www.robotsforroboticists.com/kalman-filtering/).\n---\n\n## 🚗 Dynamic PID Control System\n\nWe realized that line detection could not maintain a uniform PID for all scenarios. Thus, we use laser detection to determine when the vehicle is exiting a curve—when no sensor detects the line. In such cases, the system increases aggressiveness to react effectively, returning to a smooth PID when the line is detected again.\n\n1. **Linear Mode (smooth)**: Used when the line is stably detected by the sensors.\n2. **Aggressive Mode**: Activated when no sensor detects the line (indicating curve exit). This mode increases the Kp value and activates **drifting**.\n\n## ⚡ Drifting\n\nIn aggressive mode, drifting allows one of the motors to take negative speeds, facilitating sharp turns and quick course corrections. The PID integrator plays a crucial role here, providing the appropriate power for these adjustments and ensuring drifting is efficient and controlled. The combined use of the integrator and negative speeds enables the robot to react quickly to sharp curves or extreme deviations, maximizing both style and movement effectiveness.\n\n```cpp\nif (detector.lost()) {\n  minSpeed(-255); // Drifting activated\n  pid.setKp(AGGRESIVE_KP);\n  pid.setKi(0.001);\n} else {\n  minSpeed(0);\n  pid.setKp(LINEAR_KP);\n  pid.setKi(0.0);\n}\n```\n\n## 📊 Task System with SimpleRT\n\nThe **SimpleRT** library acts as a wrapper over FreeRTOS, simplifying the creation and management of periodic tasks in the system. Its naming and usage are inspired by asynchronous Python libraries like asyncio, enabling developers to transfer prior knowledge to a microcontroller environment. Its purpose is to make the code more readable and maintainable while leveraging FreeRTOS's multitasking capabilities.\n\n### Basic Usage of SimpleRT\n\n- **Initialize a task**: Allows defining tasks with specific priorities.\n  \n```cpp\nSimpleRT::newTask(\"taskName\", taskFunction, priority);\n```\n\n- **Wait for the next iteration of a periodic task**: Ensures the system can handle periodic operations seamlessly.\n\n```cpp\nSimpleRT rt(20); // Tarea periódica cada 20 ms\nrt.awaitNextIteration();\n```\n\n- **Pause execution for a defined time**: Temporarily halts task execution to synchronize with the system's timing needs.\n  \n```cpp\n  rt.await(100); // Pausa la ejecución durante 100 ms\n```\n\n## ⏱️ Measuring Task Frequencies\n\nThe system design ensures that all tasks meet their deadlines in a real-time environment. The most critical task is navigation, with a period of **10 ms**, whose compliance is vital for the robot's functioning. To ensure the RT system operates effectively, task timing has been measured using our custom `NonBlockingTimer`. This library is used to measure the exact time each function takes to execute. It verifies if the consumed time stays within the task's period limit.\n\nSteps followed for this:\n\n1. **Task Measurement**: Time estimates for each task were obtained by running each function multiple times and taking the highest elapsed time plus a margin of error.\n\n```cpp\nNonBlockingTimer timer;\ntimer.start();\n\n// Código de la tarea\nwork()\n\nunsigned long elapsed = timer.getMsElapsedTime();\nSerial.println(elapsed);\n```\n\n2. **Deadlines in Critical Functions**: Functions like obstacle detection include time limits. If the function exceeds the allowed time, it is interrupted to avoid system delays.\n\n### Advantages\n\n- **Maximum Frequency**: Ensures that critical tasks are not delayed by less important functions.\n- **Robustness**: Deadline control ensures the system remains stable even under unexpected loads.\n- **Predictable Times**: Allows analyzing the temporal cost of each task and adjusting periods if necessary.\n\n## 🎥 Results\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003eWeighDetector Tracking\u003c/h3\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cvideo src=\"https://github.com/user-attachments/assets/8510b777-f50c-4221-9b84-02a3c6fea754\" height=\"200\" /\u003e\n\u003c/div\u003e\n\t  \n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003e(Final) Kalman Tracking on Custom Track\u003c/h3\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cvideo src=\"https://github.com/user-attachments/assets/6f437f8a-2796-4e94-89d8-7aca0afc6e48\" height=\"200\" /\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003e(Final) Kalman on Exam Track\u003c/h3\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cvideo src=\"https://github.com/user-attachments/assets/ec319da2-20a1-4b47-b527-0dbce1e16eab\" height=\"200\" /\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamthinkgit%2Fjorgescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamthinkgit%2Fjorgescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamthinkgit%2Fjorgescript/lists"}