Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
| ||||||
![]() |
|
This is simple engine that uses a rpi hailo+ hat rpi 5 8mb and a pico as IOThere are 4 elements in this.1. change of the default detection.py in the hailo-rpi5-examples/basic_pipelines directory. It sends a text string for every detection to std::cout.
2. This is a c++ program that takes the text from a named pipe and checks for matches in the text string. If a match is found it sends detection coordinates to the pico via usb serialport. It also takes return answer from the pico and show it on the std output.
3. This is an arduino code that controls the pico I am using earlpilhowers extensions to arduino. https://github.com/earlephilhower/arduino-pico
4. Is a script that starts it all up located in the hailo-rpi5-examples folder.
To reproduce it you will need to use https://github.com/hailo-ai/hailo-rpi5-examples installedc++ -> the cmake and the gcc toolbox.pico -> arduino ide with the earlphillhower extension.
start -> starthailo.sh in the hailo-rpi5-examples directory.
This is a small test settings but it is easy for makers to change it to somethings else. In my setup it controls a Pimoroni Pan-Tilt HAT with 2 servos mounted with a rpi 3 wide camera module.
In my setup the camera will follow a label "person" with the lowest track ID.
Use the official mounting videos for mounting the pi ai+hat and the camera.I am using a external 5v psu 2 amps to power the servoes and a direct connect to the pico gnd to gnd and GP2 to the horizontals servo and GP3 to the vertical servo. When using a 3.3 v cpu you can NOT get a full 180 d.gr. turn. yellow wire gnd = brown wire.
#pragma once
#include <iostream>
#include <mutex>
#include <thread>
#include <string>
#include <stdio.h>
#include <queue>
#include <chrono>
// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
#include <cstring>
#include <sys/file.h>
namespace comport {
class comportACM0{
private:
std::string port ;
int serial_port = 0;
int hastighed = 0;
bool resiverthreadrunning = false;
std::queue<std::string> *resiverstring = new std::queue<std::string>;
void signal_handler_IO (int status); //for initialising
std::thread resv;
std::mutex mtx;
protected:
public:
comportACM0(std::string portnavn = "/dev/ttyACM0" , int speed = B115200) { //default ACM0
this->port = portnavn;
this->hastighed = speed;
resv = std::thread(&comportACM0::resiverthread, this);
}
~comportACM0(void) { //default ACM0
flock(serial_port , LOCK_UN);
close(this->serial_port);
delete(resiverstring);
}
int resvsize(void){
return resiverstring->size();
}
bool resvempty (void){
return this->resiverstring->empty();
}// end resvempty
bool isresvrunning(void){
return resiverthreadrunning;
}//end isre**
int hentdatalinie(std::string *data){
if (not this->resiverstring->empty()){
mtx.lock();
*data = this->resiverstring->front();
this->resiverstring->pop();
mtx.unlock();
}//end if
return data->size();
}//end hent data linie
int senddatalinie(std::string *data){
int ret = 0;
if(serial_port > 0)
ret = write(serial_port, data->c_str(), data->size());
return ret;
}//end senddata
private:
int portsetup(void){
// Open the serial port. Change device path as needed (currently set to an standard FTDI USB-UART cable type device)+
serial_port = open(port.c_str(), O_RDWR );
int error = flock(serial_port , LOCK_EX);
// Create new termios struct, we call it 'tty' for convention
std::cout << "portnavn : " << port << " Serial port : " << serial_port << std::endl;
struct termios tty;
// Read in existing settings, and handle any error
if(tcgetattr(serial_port, &tty) != 0) {
std::cerr << "Error from tcgetattr: " << errno << std::endl;
return 1;
}
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
tty.c_cflag |= CS8; // 8 bits per byte (most common)
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO; // Disable echo
tty.c_lflag &= ~ECHOE; // Disable erasure
tty.c_lflag &= ~ECHONL; // Disable new-line echo
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
// tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
// tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)
tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
tty.c_cc[VMIN] = 0;
// Set in/out baud rate to be 115200
cfsetspeed(&tty, B115200);
//cfsetospeed(&tty, B115200);
//resv= std::thread([this]() { resiverthread(); });
//resv = std::thread(&comportACM0::resiverthread, this);
// Save tty settings, also checking for error
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
std::cerr << "Error from tcsetattr: " << errno << std::endl;
return 1;
}
return 0;
}
void resiverthread()
{
if(portsetup() == 0)
this->resiverthreadrunning = true;
char buffer ;
std::string modtagerlinie = "";
int modtaget = 0;
while(modtaget >= 0){
//int num_bytes = read(serial_port, &read_buf, sizeof(read_buf));
modtaget = read(this->serial_port , &buffer , 1);
if(modtaget > 0){
modtagerlinie += buffer;
//std::cout << buffer;
if(buffer == '\n'){
mtx.lock();
this->resiverstring->push(modtagerlinie);
mtx.unlock();
modtagerlinie = "";
}//end if
}//end if
}//end while
std::cout << "Error reading: " << errno << " \nResiver thread stopper " << std::endl;
}
};
}
new detection.py
Pythonput it in the hailo-rpi5-examples/basic_pipelines directory
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
import os
import numpy as np
import cv2
import hailo
import sys
from hailo_apps_infra.hailo_rpi_common import (
get_caps_from_pad,
get_numpy_from_buffer,
app_callback_class,
)
from hailo_apps_infra.detection_pipeline import GStreamerDetectionApp
# -----------------------------------------------------------------------------------------------
# User-defined class to be used in the callback function
# -----------------------------------------------------------------------------------------------
# Inheritance from the app_callback_class
class user_app_callback_class(app_callback_class):
def __init__(self):
super().__init__()
self.new_variable = 42 # New variable example
def new_function(self): # New function example
return "The meaning of life is: "
# -----------------------------------------------------------------------------------------------
# User-defined callback function
# -----------------------------------------------------------------------------------------------
# This is the callback function that will be called when data is available from the pipeline
def app_callback(pad, info, user_data):
# Get the GstBuffer from the probe info
buffer = info.get_buffer()
# Check if the buffer is valid
if buffer is None:
return Gst.PadProbeReturn.OK
# Using the user_data to count the number of frames
user_data.increment()
#user_data.use_frame = True
string_to_print = f"Frame count: {user_data.get_count()} "
# Get the caps from the pad
format, width, height = get_caps_from_pad(pad)
string_to_print += f"Width: {width} Heigth: {height}\n"
# If the user_data.use_frame is set to True, we can get the video frame from the buffer
frame = None
label = None
if user_data.use_frame and format is not None and width is not None and height is not None:
# Get video frame
frame = get_numpy_from_buffer(buffer, format, width, height)
#string_to_print += " frame ok "
# Get the detections from the buffer
roi = hailo.get_roi_from_buffer(buffer)
detections = roi.get_objects_typed(hailo.HAILO_DETECTION)
# Parse the detections
detection_count = 0
for detection in detections:
detection_count += 1
label = detection.get_label()
if label != None:
bbox = detection.get_bbox()
confidence = detection.get_confidence()
# Get track ID
track_id = 0
track = detection.get_objects_typed(hailo.HAILO_UNIQUE_ID)
if len(track) == 1:
track_id = track[0].get_id()
string_to_print += (f"Label: {label} ID: {track_id} Confidence: {confidence:.2f} Detection count: {detection_count} ")
bbox = detection.get_bbox()
# Call the coordinate methods
x_min = bbox.xmin()
y_min = bbox.ymin()
box_width = bbox.width()
box_height = bbox.height()
# Calculate max coordinates
x_max = x_min + box_width
y_max = y_min + box_height
# Calculate center point (these are normalized 0-1)
center_x = x_min + (box_width / 2)
center_y = (y_min + (box_height / 2) - 0.22) * 1.83
# Debug print for coordinates
string_to_print += (f"Position: center=({center_x:.4f}, {center_y:.4f}) "
f"Bounds: xmin={x_min:.4f}, ymin={y_min:.4f}, xmax={x_max:.4f}, ymax={y_max:.4f}\n")
if user_data.use_frame:
cv2.rectangle(frame, ((int)(x_min * width),(int) (y_min* height)), ((int)(x_max * width),(int) (y_max * height)), (255, 255, 255),1)
cv2.putText(frame, label,((int)(x_min * width),(int) ((y_min* height) - 10)), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1)
if user_data.use_frame:
cv2.putText(frame,f"Frame count: {user_data.get_count()}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
if user_data.use_frame and label != None:
# Note: using imshow will not work here, as the callback function is not running in the main thread
# Let's print the detection count to the frame
cv2.putText(frame, f"Label: {label} ID: {track_id} Confidence: {confidence:.2f} Detection count: {detection_count}", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Example of how to use the new_variable and new_function from the user_data
# Let's print the new_variable and the result of the new_function to the frame
#cv2.putText(frame, f"{user_data.new_function()} {user_data.new_variable}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# Convert the frame to BGR
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
user_data.set_frame(frame)
elif user_data.use_frame :
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
user_data.set_frame(frame)
print(string_to_print)
sys.stdout.flush()
return Gst.PadProbeReturn.OK
if __name__ == "__main__":
# Create an instance of the user app callback class
user_data = user_app_callback_class()
app = GStreamerDetectionApp(app_callback, user_data)
app.run()
hailopipe
C/C++make a sub directory named hailopipe and put hailopipe.cpp in it.
void label_do_something(void) is run for every detection.
void new_frame(void) is run for every new frame.
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
//c++
#include <chrono>
#include <iostream>
#include <cstdio>
#include "comport.cpp"
#include <climits>
//#include <bits/stdc++.h>
#define max_count 10
namespace hailofifo {
class hailofifo{
private:
std::string pipename = "", label = "";
int pipeindifier = -1 , id = -1 , countnumber = 0;
comport::comportACM0 *cport;
std::thread piperead;
bool pipethreadisrunning = false;
std::mutex mtx;
bool runmode = true , labeldetekt = false ,newframe = false, trackperson = true;
ulong framecount = 0;
int width = 0 , heigth = 0;
float confidence = 0.0 , center_x = 0.0 , center_y = 0.0 , xmin = 0.0 , ymin = 0.0 , xmax = 0.0 , ymax = 0.0;
int person_count = 0;
bool light_on = false , person_label = false;
std::queue<std::string> *resiverstrings = new std::queue<std::string>;
int person_track_id = INT_MAX;
float person_track_x , person_track_y , person_track_xmax , person_track_ymax;
bool person_track_detect = false;
void init(void){
int unlink((const char )*this->pipename.c_str());
mkfifo(this->pipename.c_str(), 0666);
this->pipeindifier = open(this->pipename.c_str(), O_RDONLY);
}//end init
void pipereadthread( void) {
mtx.lock();
this->pipethreadisrunning = true;
mtx.unlock();
char buffer = 0;
std::string resiverline = "";
int readnumber = 0;
while(pipeindifier >=0){
readnumber =read(pipeindifier, &buffer, sizeof(buffer));
if(readnumber > 0){
resiverline += buffer;
if(buffer == '\n'){
mtx.lock();
resiverstrings->push(resiverline);
mtx.unlock();
resiverline = "";
}//end if
}else {
std::this_thread::sleep_for(std::chrono::microseconds(10));
}//end if
}//end while
}//end piperead thread
void detection_string(void){
mtx.lock();
std::string resvtxt = resiverstrings->front();
resiverstrings->pop();
mtx.unlock();
//std::cout << resvtxt ;
std::string substring = "Frame count:";
int found = resvtxt.find(substring);
if(found == 0){
newframe = true;
int from = substring.size() + 1;
substring = "Width:";
found = resvtxt.find(substring ,from);
std::string number = resvtxt.substr(from , found - 1 );
this->framecount = std::stoi(number);
from = found + substring.size() + 1;
substring = "Heigth:";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->width = std::stoi(number);
from = found + substring.size() + 1;
number = resvtxt.substr(from , resvtxt.size()-1);
this->heigth = std::stoi(number);
//std::cout << "Framenumber : " << this->framecount << " width : " << this->width << " heigth : " << this->heigth << std::endl;
}else{
substring = "Label:";
found = resvtxt.find(substring);
int from = substring.size() + 1;
if(found == 0){
labeldetekt = true;
from = substring.size() + 1;
substring = "ID:";
found = resvtxt.find(substring );
this->label = resvtxt.substr(from , (found - 1) - from );
from = found + substring.size() + 1;
substring = "Confidence:";
found = resvtxt.find(substring , from);
std::string number = resvtxt.substr(from , found - 1 );
this->id = std::stoi(number);
from = found + substring.size() + 1;
substring = "Detection count:";
found = resvtxt.find(substring, from);
number = resvtxt.substr(from , found - 1 );
this->confidence = std::stof(number);
from = found + substring.size() + 1;
substring = "Position:";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->countnumber = std::stoi(number);
substring = "center=(";
found = resvtxt.find(substring , from);
from = found + substring.size() + 1;
substring = ",";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->center_x = std::stof(number);
from = found + 1;
substring = ")";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->center_y = std::stof(number);
from = found+1;
substring = "xmin=";
found = resvtxt.find(substring , from);
from = found + substring.size();
substring = ",";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->xmin = std::stof(number);
from = found+1;
substring = "ymin=";
found = resvtxt.find(substring , from);
from = found + substring.size();
substring = ",";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->ymin = std::stof(number);
from = found+1;
substring = "xmax=";
found = resvtxt.find(substring , from);
from = found + substring.size();
substring = ",";
found = resvtxt.find(substring , from);
number = resvtxt.substr(from , found - 1 );
this->xmax = std::stof(number);
from = found+1;
substring = "ymax=";
found = resvtxt.find(substring , from);
from = found + substring.size();
number = resvtxt.substr(from , resvtxt.size());
this->ymax = std::stof(number);
//std::cout << "label : " << this->label << " id : " << this->id << " conf : " << this->confidence << " Detection count number : " << this->countnumber << " center x : " << this->center_x << " center y : " << this->center_y << " xmin : " << this->xmin << " ymin : " << this->ymin << " xmax : " << this->xmax << " ymax : " << this->ymax << std::endl << std::endl;
} else {
substring = "Shutting down...";
found = resvtxt.find(substring);
if(found == 0){
runmode = false; //quit
std::cout <<"\nend of program \n";
return; // end of program
}//end if
}//end if
}//end if
}
void label_do_something(void){
labeldetekt = false;
std::string detval = "person";
if(this->label == detval){
person_label = true;
if(this->trackperson ){
if(this->person_track_id >= this->id){
this->person_track_detect = true;
this->person_track_x = this->center_x;
this->person_track_y = this->center_y ;
this->person_track_xmax = this->xmax - this->xmin;
this->person_track_ymax = this->ymax - this->ymin;
}//end if
}//end if
}//end if
}//end label_do_something
void new_frame(void){
std::string datatxt = "";
newframe = false;
//std::cout << "frame number : " << this->framecount << std::endl;
if(person_label){
person_label = false;
if(this->person_count < max_count and this->confidence > 0.40){
++this->person_count;
}else{
if(this->person_count > 0)
person_count--;
}//end if
if(this->person_count == max_count){
if(this->light_on == false){
std::cout << "light on" << std::endl;
datatxt = "light on \n";
cport->senddatalinie(&datatxt);
this->light_on = true;
std::cout << "person detected \n";
}// end if
} //end if
if(this->person_track_detect){
datatxt = "Track:";
datatxt += "Width:";
datatxt += std::to_string(this->width);
datatxt += "Heigth:";
datatxt += std::to_string(this->heigth);
datatxt += "cx:";
datatxt += std::to_string(this->person_track_x);
datatxt += "cy:";
datatxt += std::to_string(this->person_track_y );
datatxt += "bx:";
datatxt +=std::to_string(this->person_track_xmax);
datatxt += "by:";
datatxt += std::to_string(this->person_track_ymax);
datatxt += "\n";
cport->senddatalinie(&datatxt);
//std::cout << datatxt;
}//end if
}else{
if(this->person_count > 0)
person_count--;
}//end if
//std::cout << "Person Count : " << person_count << std::endl;
if(person_count == 0 and light_on == true){
std::cout << "light off" << std::endl;
datatxt = "light off\n";
cport->senddatalinie(&datatxt);
this->light_on = false;
std::cout << "person NOT detected \n";
}//end if
this->person_track_detect = false;
int person_track_id = INT_MAX;
}//end new_frame
void resetcam(void){
std::string txt =("reset \n");
cport->senddatalinie(&txt);
}//end reset
public:
hailofifo(std::string pipe = "/tmp/hailo")
{
this->pipename = pipe;
//this->cport = new comport::comportACM0((std::string) "/dev/ttyACM1" , (int) B115200);
this->cport = new comport::comportACM0; // default /dev/ttyacm0 B115200
init();
if(pipeindifier != -1){
piperead = std::thread(&hailofifo::pipereadthread, this);
}else runmode = false; //quit
}//end hailofifo
~hailofifo()
{
delete cport;
delete resiverstrings;
int unlink((const char )*this->pipename.c_str());
}//end destructor
void run(void){
resetcam();
if(pipeindifier == -1) runmode = false;
while(this->runmode == true){
while(not resiverstrings->empty()){
detection_string();
if(newframe){
new_frame();
} else if(labeldetekt){
label_do_something();
}//end if
if(not cport->resvempty()){
std::string txt = "";
cport->hentdatalinie(&txt);
//std::cout << "frame number : " << this->framecount << std::endl;
std::cout << "Comport : " << txt;
}//end if
}//end while
std::this_thread::sleep_for(std::chrono::microseconds(10));
}//end while
}//end run
};//end class
}
int main() {
//hailofifo::hailofifo *hailo = new hailofifo::hailofifo("./hailo");//new pipename
hailofifo::hailofifo *hailo = new hailofifo::hailofifo();
hailo->run();
return 0;
}
cmakelist
ActionScriptset(CMAKE_CXX_STANDARD 11) is equal to opencv
cmake_minimum_required(VERSION 2.8)
project(hailopipe)
set(CMAKE_CXX_STANDARD 11)
add_executable( hailopipe hailopipe.cpp )
target_link_libraries( hailopipe )
Pico driver
C/C++put it in your normal arduino chain compile it and program the pico.
install 107-Arduino-Servo-RP2040 it can be found in the libary installer.
install SimpelTimer from https://github.com/jfturcot/SimpleTimer
#include <queue>
#include <string>
#include <SimpleTimer.h>
#include <107-Arduino-Servo-RP2040.h>
#define maxposx 2000
#define maxposy 2000
#define minposx 1000
#define minposy 1700
#define timertimeout 30
#define maxresetframecount 30
static _107_::Servo servo_0, servo_1;
SimpleTimer simpeltimer;
int autoreset = 0; //counter for autoreset
class hailotxt{
private:
int width = 0 , height = 0 , track_posx = 0 , track_posy = 0, newposx = 0 , newposy = 0;
float cx = 0.0 , cy = 0.0;
bool newpos = false ;
int do_hailotrack(std::string *txt){
std::string mysubstring = "Width:";
int found = txt->find(mysubstring);
if(found != std::string::npos){
int from = found + mysubstring.size();
std::string mysubstring = "Heigth:";
found = txt->find(mysubstring ,from);
std::string number = txt->substr(from , found - 1 );
this->width = std::stoi(number);
from = found + mysubstring.size();
mysubstring = "cx:";
found = txt->find(mysubstring ,from);
number = txt->substr(from , found - 1 );
this->height = std::stoi(number);
from = found + mysubstring.size() + 1;
mysubstring = "cy:";
found = txt->find(mysubstring ,from);
number = txt->substr(from , found - 1 );
this->cx = std::stof(number);
from = found + mysubstring.size() + 1;
mysubstring = "bx:";
found = txt->find(mysubstring ,from);
number = txt->substr(from , found - 1 );
this->cy = std::stof(number);
track_posx = cx * width;
track_posy = cy * height;
int hwidth = width / 2 , hheight = height / 2;
newposx = track_posx - hwidth;
newposy = track_posy - hheight;
newpos = true;
//Serial.println("Ok");
return 0;
}//end if
return -1;
}//end do_ha..
public:
hailotxt(void){}
//return -1 if nothing done
bool lost_track = false;
int dohailotxt(std::string *txt){
if(txt->find("Track:") != std::string::npos){
this->do_hailotrack(txt);
return 0;
}//end if
if(txt->find("light on") != std::string::npos){
digitalWrite(LED_BUILTIN , 1);
Serial.println("Ok");
return 0;
}//end if
if(txt->find("light off") != std::string::npos){
digitalWrite(LED_BUILTIN , 0);
Serial.println("Ok");
lost_track = true;
return 0;
}//end if
if (txt->find("reset") != std::string::npos){
lost_track = true;
Serial.println("Ok");
Serial.println("Reset");
return 0;
}//end if
return -1;
}//end dohailotxt
bool newposready(void){
return(newpos);
}//end newposready
void getnewpos(int *x , int *y){
*x = newposx;
*y = newposy;
newpos = false;
}// end getnewpos
}; //end hailotxt
void timerint (void){
++autoreset;
}//end timer int
hailotxt *hailo = new hailotxt();
int servox = 1500 , servoy = 1900;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(LED_BUILTIN , OUTPUT);
digitalWrite(LED_BUILTIN , LOW);
servo_0.attach(2);
servo_1.attach(3);
simpeltimer.setInterval(timertimeout, timerint);
servo_0.writeMicroseconds(servox);
servo_1.writeMicroseconds(servoy);
}
int testnr = 0;
std::string buffer = "";
std::queue<std::string> *resiverstring = new std::queue<std::string>;
void readchar(void){
char karakter;
while(Serial.available() > 0){
karakter = Serial.read();
buffer += karakter;
if(karakter == '\n'){
resiverstring->push(buffer);
buffer = "";
}//end if
}//end while
}//end readchar
void loop() {
simpeltimer.run();
// put your main code here, to run repeatedly:
if(Serial.available())
readchar();
while(not resiverstring->empty()){
std::string str = resiverstring->front();
resiverstring->pop();
hailo->dohailotxt(&str);
}//end while
if(hailo->newposready()){
int x , y;
autoreset = 0; //autoreset
hailo->getnewpos(&x , &y);
servox += x /15;
servoy += y /15;
if(servox < minposx )
servox = minposx;
if(servox > maxposx)
servox = maxposx;
if(servoy < minposy )
servoy = minposy;
if(servoy > maxposy)
servoy = maxposy;
std::string serialout = "servox = ";
serialout += std::to_string(servox);
serialout += " servoy = ";
serialout += std::to_string(servoy);
serialout += "\n";
//Serial.print(serialout.c_str());
servo_0.writeMicroseconds(servox);
servo_1.writeMicroseconds(servoy);
}//end if
if(hailo->lost_track or autoreset > maxresetframecount){
autoreset = 0;//autoreset
servox = 1500;
servoy = 1900;
hailo->lost_track = false;
servo_0.writeMicroseconds(servox);
servo_1.writeMicroseconds(servoy);
//Serial.println("lost track or autoreset");
}//end if
delay(1); // waits 15ms for the servo to reach the position
}
script file to start the chain
ActionScriptput it in the hailo-rpi5-examples directory
#!/bin/bash
. setup_env.sh
hailopipe/hailopipe &
python3 basic_pipelines/madsen.py --hef-path resources/yolov11s.hef --input rpi --show-fps >> /tmp/hailo
#python3 basic_pipelines/madsen.py --hef-path resources/madsenstx.hef --input rpi --labels-json resources/madsen.json >>/tmp/hailo
rm /tmp/hailo
Comments