mirror of
https://gitlab.fdmci.hva.nl/technische-informatica-sm3/ti-projectten/rooziinuubii79.git
synced 2025-08-05 12:54:57 +00:00
Compare commits
8 Commits
OpenCV
...
61651a9a02
Author | SHA1 | Date | |
---|---|---|---|
|
61651a9a02 | ||
|
e5881f1b37 | ||
50b6b83299 | |||
10597ba37d | |||
6ab5716797 | |||
50b90e461f | |||
2811036595 | |||
58f1a931a6 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,3 +32,4 @@ Makefile
|
|||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
src/C++/OpenCV/main
|
src/C++/OpenCV/main
|
||||||
|
.vs
|
50
docs/code/Mqtt.md
Normal file
50
docs/code/Mqtt.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# MQTT
|
||||||
|
|
||||||
|
## What is MQTT?
|
||||||
|
MQTT is a lightweight messaging protocol made for IOT devices. It allows efficient communication between IoT devices, servers, and applications by allowing them to
|
||||||
|
publish and subscribe to messages.
|
||||||
|
|
||||||
|
|
||||||
|
## How to connect
|
||||||
|
To connect to a MQTT server you need to create a instance of the class.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```cpp
|
||||||
|
// server adress, Client ID, Client Username, Client Password
|
||||||
|
MqttClient client("ws://145.92.224.21/ws/", "KobukiRPI", "rpi", "rpiwachtwoordofzo"); // create a client object
|
||||||
|
```
|
||||||
|
Later in the setup function you need to call ```client.connect();``` to connect to the mqtt server.
|
||||||
|
```cpp
|
||||||
|
client.connect();
|
||||||
|
```
|
||||||
|
|
||||||
|
When you've connected and the instance is initiated you can subscribe to topics or send messages to topics.
|
||||||
|
|
||||||
|
|
||||||
|
## Subscribing and receiving messages
|
||||||
|
Example subscribing to a topic:
|
||||||
|
```cpp
|
||||||
|
void setup(){
|
||||||
|
client.subscribe("home/commands");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example receiving latest message from a topic:
|
||||||
|
```cpp
|
||||||
|
std::string foo(){
|
||||||
|
std::string latestMqttMessage = "";
|
||||||
|
latestMqttMessage = client.getLastMessage();
|
||||||
|
return latestMqttMessage;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to subscribe to mulitple topics you need to initiate multiple instances of the mqtt class.
|
||||||
|
|
||||||
|
## Publishing messages
|
||||||
|
Example publishing a message:
|
||||||
|
```cpp
|
||||||
|
void foo(std::string Message){
|
||||||
|
//channel, payload
|
||||||
|
client.publishMessage("kobuki/example", Message);
|
||||||
|
}
|
||||||
|
```
|
@@ -1,20 +1,69 @@
|
|||||||
# OpenCV
|
# OpenCV
|
||||||
## Requirements
|
## Requirements
|
||||||
For the camera we want it to detect what is happening on the video feed and identify it so it can identify dangers.
|
We want that the camera we want it to detect what is happening on the video feed and identify it so it can identify dangers.
|
||||||
|
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
* OpenCL not grabbing gpu
|
* OpenCL not grabbing gpu
|
||||||
* Solution: https://github.com/Smorodov/Multitarget-tracker/issues/93
|
* Solution: https://github.com/Smorodov/Multitarget-tracker/issues/93
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
### Dependencies
|
### Dependencies
|
||||||
* glew
|
* glew (for openGL)
|
||||||
* opencv
|
* opencv C++ lib
|
||||||
|
|
||||||
|
How to install OpenCV
|
||||||
|
```bash
|
||||||
|
sudo apt-get install libopencv-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code explanation
|
||||||
|
|
||||||
|
### Opening the camera with OpenCV
|
||||||
|
```cpp
|
||||||
|
VideoCapture cap(0); //Open the default camera (0), points to /dev/video0. You could also change the number to the preferred camera
|
||||||
|
if (!cap.isOpened()) { //if camera is not opened throw a error message
|
||||||
|
cerr << "Error: Could not open camera" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Taking a picture and storing it in a variable
|
||||||
|
```cpp
|
||||||
|
Mat frame; //create a new Matrix variable called frame
|
||||||
|
while (true) {
|
||||||
|
cap >> frame; // Capture a new image frame.
|
||||||
|
if (frame.empty()) { //if the variable frame is not filled return a error
|
||||||
|
cerr << "Error: Could not capture image" << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Encoding the image for sending it over MQTT
|
||||||
|
```cpp
|
||||||
|
vector<uchar> buf; //create a dyanmic buffer for the image
|
||||||
|
imencode(".jpg", frame, buf); //encode the image to the buffer
|
||||||
|
auto* enc_msg = reinterpret_cast<unsigned char*>(buf.data());
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
|
||||||
|
void CapnSend() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Convert the image to a byte array
|
||||||
|
|
||||||
|
|
||||||
|
// Publish the image data
|
||||||
|
client.publishMessage("kobuki/cam", string(enc_msg, enc_msg + buf.size()));
|
||||||
|
cout << "Sent image" << endl;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(300)); // Send image every 1000ms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Sources
|
## Sources
|
||||||
* https://github.com/UnaNancyOwen/OpenCVDNNSample/tree/master
|
* https://github.com/UnaNancyOwen/OpenCVDNNSample/tree/master
|
25
docs/code/kobuki-driver.md
Normal file
25
docs/code/kobuki-driver.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Kobuki driver
|
||||||
|
|
||||||
|
## How do i communicate with the kobuki
|
||||||
|
You can communicate with the kobuki by usb serial or the big serial port on the front. We chose the usb port paired with a raspberry Pi.
|
||||||
|
|
||||||
|
The Kobuki sends a message every 200ms with a baudrate of 115200. It sends all the sensordata and the message always starts with the same 2 bytes 0xAA and 0x55.
|
||||||
|
|
||||||
|
## Kobuki payloads
|
||||||
|
To communicate with the kobuki we need to send payloads to the kobuki. These are structured the same as the payloads that the kobuki sends.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
unsigned char KobukiPayload[11] = {
|
||||||
|
0xaa, // Start byte 1
|
||||||
|
0x55, // Start byte 2
|
||||||
|
0x08, // Payload length (the first 2 bytes dont count)
|
||||||
|
0x01, // payload type (0x01 = control command)
|
||||||
|
0x04, // Control byte or additional identifier
|
||||||
|
actual_speed % 256, // Lower byte of speed value (max actual_speed 1024)
|
||||||
|
actual_speed >> 8, // Upper byte of speed value
|
||||||
|
0x00, // Placeholder for radius
|
||||||
|
0x00, // Placeholder for radius
|
||||||
|
0x00 // Placeholder for checksum (will be applied later)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
You can also find the documentation about the payloads on the kobuki website
|
@@ -592,6 +592,8 @@ void CKobuki::robotSafety() {
|
|||||||
std::cout << "Safety condition triggered!" << std::endl; // Debug print
|
std::cout << "Safety condition triggered!" << std::endl; // Debug print
|
||||||
forward(-100); // reverse the robot
|
forward(-100); // reverse the robot
|
||||||
}
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(100)));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
//moet checkenvalue gebruiken of moet kijken naar de payloadlength welke dingen er extra zijn
|
//moet checkenvalue gebruiken of moet kijken naar de payloadlength welke dingen er extra zijn
|
||||||
int KobukiParser::parseKobukiMessage(TKobukiData &output, unsigned char *data) {
|
int KobukiParser::parseKobukiMessage(TKobukiData &output, unsigned char *data) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(20))); //avoid busy waiting. The kobuki sends a message every 20ms
|
||||||
|
|
||||||
int rtrnvalue = checkChecksum(data);
|
int rtrnvalue = checkChecksum(data);
|
||||||
if (rtrnvalue != 0) {
|
if (rtrnvalue != 0) {
|
||||||
// std::cerr << "Invalid checksum" << std::endl;
|
// std::cerr << "Invalid checksum" << std::endl;
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
#define KOBUKIPARSER_H
|
#define KOBUKIPARSER_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
struct TRawGyroData {
|
struct TRawGyroData {
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
|
@@ -36,7 +36,11 @@ int main()
|
|||||||
std::thread sendMqtt([&]() { sendKobukiData(robot.parser.data); });
|
std::thread sendMqtt([&]() { sendKobukiData(robot.parser.data); });
|
||||||
|
|
||||||
while(true){
|
while(true){
|
||||||
parseMQTT(readMQTT());
|
std::string message = readMQTT();
|
||||||
|
if (!message.empty()){
|
||||||
|
parseMQTT(message);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMqtt.join();
|
sendMqtt.join();
|
||||||
@@ -46,10 +50,13 @@ int main()
|
|||||||
|
|
||||||
std::string readMQTT()
|
std::string readMQTT()
|
||||||
{
|
{
|
||||||
message = client.getLastMessage();
|
static std::string lastMessage;
|
||||||
if (!message.empty())
|
|
||||||
|
std::string message = client.getLastMessage();
|
||||||
|
if (!message.empty() && message != lastMessage)
|
||||||
{
|
{
|
||||||
std::cout << "MQTT Message: " << message << std::endl;
|
std::cout << "MQTT Message: " << message << std::endl;
|
||||||
|
lastMessage = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a small delay to avoid busy-waiting
|
// Add a small delay to avoid busy-waiting
|
||||||
|
@@ -3,7 +3,6 @@ import paho.mqtt.client as mqtt
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
kobuki_message = "empty"
|
|
||||||
def on_message(client, userdata, message):
|
def on_message(client, userdata, message):
|
||||||
global kobuki_message, latest_image
|
global kobuki_message, latest_image
|
||||||
if message.topic == "kobuki/data":
|
if message.topic == "kobuki/data":
|
||||||
@@ -11,10 +10,11 @@ def on_message(client, userdata, message):
|
|||||||
elif message.topic == "kobuki/cam":
|
elif message.topic == "kobuki/cam":
|
||||||
latest_image = message.payload
|
latest_image = message.payload
|
||||||
|
|
||||||
|
|
||||||
# Create an MQTT client instance
|
# Create an MQTT client instance
|
||||||
mqtt_client = mqtt.Client()
|
mqtt_client = mqtt.Client()
|
||||||
mqtt_client.username_pw_set("server", "serverwachtwoordofzo")
|
mqtt_client.username_pw_set("server", "serverwachtwoordofzo")
|
||||||
mqtt_client.connect("localhost", 80, 60)
|
mqtt_client.connect("localhost", 1884, 60)
|
||||||
mqtt_client.loop_start()
|
mqtt_client.loop_start()
|
||||||
mqtt_client.subscribe("kobuki/data")
|
mqtt_client.subscribe("kobuki/data")
|
||||||
mqtt_client.subscribe("kobuki/cam")
|
mqtt_client.subscribe("kobuki/cam")
|
||||||
@@ -49,7 +49,6 @@ def move():
|
|||||||
def data():
|
def data():
|
||||||
return kobuki_message
|
return kobuki_message
|
||||||
|
|
||||||
|
|
||||||
@app.route('/image')
|
@app.route('/image')
|
||||||
def image():
|
def image():
|
||||||
global latest_image
|
global latest_image
|
||||||
|
@@ -25,9 +25,12 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||||||
|
|
||||||
// Fetch data from the server
|
// Fetch data from the server
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
|
try{
|
||||||
const response = await fetch("/data");
|
const response = await fetch("/data");
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data;
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the data and show it on the website
|
// Parse the data and show it on the website
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
import sys
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logging.basicConfig(stream=sys.stderr)
|
|
||||||
sys.path.insert(0, "/home/ishak/rooziinuubii79/src/Python/flask/web")
|
|
||||||
|
|
||||||
from app import app as application
|
|
Reference in New Issue
Block a user