-
Notifications
You must be signed in to change notification settings - Fork 5
Ground Station Algorithm Test
├─ diva2
│ ├─ build
│ │ └─ GroundStation
│ │ ├─ AlgorithmTesting
│ │ └─ AlgorithmTesting_GUI
│ │ └─ diva_algorithm
│ ├─ GroundStation
│ │ ├─ AlgorithmTesting
│ │ │ ├─ lane_detection_algorithm
│ │ │ └─ obj_detection
│ │ │ └─ darknet
│ │ └─ AlgorithmTesting_GUI
...
darknet파일은 github에 업로드되지않아 별도로 다운로드받아 디렉토리에 추가해야한다. 여기에서 다운로드받을 수 있다.
build하기 전에 diva2/GroundStation/AlgorithmTesting_GUI/ModelRunThread.cpp에서 다음의 절대경로를 본인의 경로로 수정해주어야 한다.
if(sensorIdx == Sensor::cam){
if(algorithmIdx==0) // lane detection
{
command += "cd /home/diva2/diva2/GroundStation/AlgorithmTesting/lane_detection_algorithm/ ";
...
}else if(algorithmIdx==1) // object detection
{
command += "cd /home/diva2/diva2/GroundStation/obj_detection/darknet/ ";
...
Qt를 이용하여 프로그래밍한 AlgorithmTesting의 GUI에 관한 파일이 들어있다.
build에서 make
를 통해 build/GroundStation/AlgorithmTesting_GUI/diva_algorithm
실행파일을 생성할 수 있다.
./diva_algorithm
명령어를 통해 GUI를 실행할 수 있으며 실행 결과는 아래와 같다.
CAM sensor data에 대해 lane detection과 object detection 알고리즘만을 지원한다.
lane detection 및 object detection 알고리즘 테스트를 위한 data, config, weights파일과 images 파일은 algorithm_resources에서 다운로드받을 수 있다.
lane detection는 다음과 같은 세팅을 통해 테스트를 실행할 수 있다.
- data file :
diva2/storage/lane_detection/fcn_big_01.json
- config file : -
- weight file :
diva2/storage/lane_detection/fcn_big_01.h5
- input file :
diva2/storage/lane_detection/images
알고리즘의 제약으로 인해 input file이 존재하는 디렉토리의 상위 디렉토리 내에
result
directory가 존재해야core dumped
error를 방지할 수 있다. 또한 상위디렉토리의 상위 디렉토리 내에 역시result
directory가 존재하고, 그 안에result.txt
파일이 존재해야 한다. 가령 아래와 같이 directory를 구성할 수 있다.├─ user │ ├─ algorithm_resources │ │ ├─ lane_detection │ │ ├─ object_detection │ │ │ ├─ obj.data │ │ │ ├─ cp.cfg │ │ │ ├─ cp_best.weights │ │ │ └─ result ◂─────────── ★very important★ │ │ └─ result ◂───────────────── ★very important★ │ │ └─ result.txt ◂─────── ★very important★
이러한 디렉토리구조를 무시하는 경우 core dumped가 발생할 수 있다.
object detection을 수행하기 위한 파일은 [diva2/storage/object_detection]에 들어있다. 다음과 같은 세팅을 통해 테스트를 실행할 수 있다.
- data file :
diva2/storage/object_detection/obj.data
- config file :
diva2/storage/object_detection/cp.cfg
- weight file :
cp_best.weights
- input file : 입력 이미지가 들어있는 디렉토리
object detection은 darknet 파일을 통해 실행된다. darknet파일은 diva2/GroundStation/AlgorithmTesting/obj_detection/darknet
에서 다음의 명령어를 통해 얻어진다.
cmake .
make
CUDA가 없다면
cmake . -DENABLE_CUDA=OFF
으로 대체하면 된다.
어떤 PC에서는 build 안에서
cmake ..
가 안되므로darknet
디렉토리에서cmake .
를 해주어야 한다. 하지만 또 어떤 PC에서는mkdir build && cd build && cmake .. && make
가 가능하다.
make를 수행하면 분명 error가 날 것이다. error때문에 완전히 make가 되지 않더라도
[ 98%] Linking CXX executable darknet
만 되면 사용가능하다. 이 error로인해 root의CMakeLists.txt
와 darknet의CMakeLists.txt
를 연결하지 않았다.
1. mainwindow의 play button (link)
void MainWindow::on_pb_Play_clicked()
{
printf("[MainWindow::on_pb_Play_clicked] start\n");
// [ Set the Environments ]
// < Set Algorithm Thread to Run >
sensorIdx = 1;
algorithmIdx = 1;
algorithmThread = new AlgorithmThread(this);
algorithmThread->set_sensorIdx(sensorIdx);
algorithmThread->set_algorithmIdx(algorithmIdx);
algorithmThread->set_input_path(this->input_path.path().toStdString());
algorithmThread->start();
modelRunThread = new ModelRunThread(this);
modelRunThread->set_sensorIdx(sensorIdx);
modelRunThread->set_algorithmIdx(algorithmIdx);
modelRunThread->set_datafile(this->data_path.path().toStdString());
modelRunThread->set_configfile(this->config_path.path().toStdString());
modelRunThread->set_weightfile(this->weight_path.path().toStdString());
modelRunThread->start();
connect(algorithmThread, SIGNAL(send_qimage(QImage, QImage, QString)), this, SLOT(display_original(QImage, QImage, QString)));
...
}
mainwindow의 play button이 눌리면 algorithmThread와 modelRunThread의 멤버변수값이 세팅이 되며 thread가 실행된다.
2. AlgorithmThread의 동작 (link)
AlgorithmThread는 modelRunThread의 결과를 수신하여 Qt GUI에 출력한다.
void AlgorithmThread::run(){
...
if((sensorIdx==Sensor::cam) && (algorithmIdx==0)){
lane_detection();
}else if((sensorIdx==Sensor::cam) && (algorithmIdx==1)){
obj_detection();
}
...
}
멤버변수 세팅값(센서, 알고리즘 번호)에 따라 각 알고리즘이 동작한다.
2.1. lane_detection
① zmq 연결
zmq::context_t ctx(1);
zmq::socket_t algorithmTesting_sub(ctx, ZMQ_SUB);
algorithmTesting_sub.connect("tcp://localhost:9899");
algorithmTesting_sub.setsockopt(ZMQ_SUBSCRIBE, "", 0);
printf("[AlgorithmThread::lane_detection] connect\n");
② sub socket으로부터 데이터 읽기
algorithmTesting_sub.recv(&msg);
frame_cnt++;
③ protobuf image로 parsing하기
std::string _buff = std::string(static_cast<char *>(msg.data()), msg.size());
algo_img.ParseFromString(_buff);
④ fps 계산하기
float millis = algo_img.millis_term();
millis_sum += millis;
float fps = (float)(1000*frame_cnt)/(float)(millis_sum);
printf("fps=%f\n", fps);
⑤ Qt GUI에 출력하기
// [ Preprocessing for Visualization ]
// < Setting for original image >
memcpy((void*)frame_original.data, (void*)(&algo_img.image_original()[0]), frame_original.step[0]*(size_t)frame_original.rows);
// < Setting for result image >
memcpy((void*)frame_result.data, (void*)(&algo_img.image_result()[0]), frame_result.step[0]*(size_t)frame_result.rows);
// [ Visualization at Qt GUI ]
QImage image_original(frame_original.size().width, frame_original.size().height, QImage::Format_RGB888);
memcpy(image_original.scanLine(0), frame_original.data, static_cast<size_t>(image_original.width() * image_original.height() * frame_original.channels()));
QImage image_result(frame_result.size().width, frame_result.size().height, QImage::Format_RGB888);
memcpy(image_result.scanLine(0), frame_result.data, static_cast<size_t>(image_result.width() * image_result.height() * frame_result.channels()));
emit send_qimage(image_original, image_result, QString::number(fps));
2.2. object_detection
object_detection에 사용되는 darknet은 C기반으로 작성되었으므로 zmq.hpp
가 아닌 zmq.h
라이브러리를 이용하여 코드를 작성해야 한다.
① zmq 연결하기
// [ Setting ]
// < Zeromq >
void *ctx = zmq_ctx_new();
void *socketSub = zmq_socket(ctx, ZMQ_REP);
int rc = -1;
rc = zmq_connect(socketSub, "tcp://localhost:9899");
printf("[AlgorithmThread::obj_detection] connect:%d\n", rc);
이유는 모르겠으나 PUB-SUB 소켓은 사용이 불가능했다. 따라서 REP-REQ 소켓을 이용하여 프로토콜 규칙을 만들어 통신을 수행하였다.
② directory로부터 input image file path 읽기
// < Input File >
printf("[AlgorithmThread::obj_detection] get input files\n");
vector<string> fileName;
DIR *d = opendir(get_input_path().c_str());
struct dirent *dir;
vector<string> fileList;
int i=0;
if (d){
while ((dir = readdir(d)) != NULL){
string d_name = dir->d_name;
if((d_name.compare("..")==0) || (d_name.compare(".")==0))
continue;
i++;
fileList.push_back(d_name);
}
closedir(d);
}
이를 통해 fileList에 input image file의 path 정보가 저장된다.
③ REP 소켓으로부터 start signal을 수신한 뒤, REP소켓으로 fileList 내용을 차례로 송신
// [PROTOCOL0: START SIGNAL]
char buf [512];
int nbytes = zmq_recv (socketSub, buf, 512, 0);
assert (nbytes != -1);
...
// [ Communicate ]
// < Send a file name of original image >
len = sprintf(buf, "%s/%s",get_input_path().c_str(), fileList[count].c_str());
buf[len] = '\0';
rc = zmq_send(socketSub, buf, len+1, 0);
assert (rc > 0);
fn = buf; // file name = buf
④ REP소켓으로부터 결과 이미지의 경로명을 수신
// < Receive a file name of result image >
nbytes = zmq_recv (socketSub, buf, 512, 0);
assert (nbytes != -1);
frame_cnt++;
⑤ Qt GUI에 출력하기
mat = cv::imread(fn);
mat = cv::imread(result_filename);
...
emit send_qimage(image_original, image_result, QString::number(fps));
...
input file path인 fn
와 result file path인 result_filename
을 이용하여 이미지를 불러온 뒤, Qt GUI에 출력한다.
3. modelRunThread의 동작 (link)
modelRunThread는 알고리즘을 실행하여 algorithmThread에 그 결과를 전송한다.
void ModelRunThread::run(){
string command;
if(sensorIdx == Sensor::cam){
if(algorithmIdx==0) // lane detection
{
command += "cd /home/diva2/diva2/GroundStation/AlgorithmTesting/Algorithm/ ";
command += "&& python3 model.py ";
}else if(algorithmIdx==1) // object detection
{
command += "cd /home/diva2/diva2/GroundStation/obj_detection/darknet/ ";
command += "&& ./darknet detector test ";
command += this->str_datafile;
command +=" ";
command += this->str_configfile;
command +=" ";
command += this->str_weightfile;
}
}
int ret = system(command.c_str());
}
system command를 이용하여 파라미터 세팅 및 알고리즘을 실행한다.
2.1. lane_detection lane detection 알고리즘은 BuiKhoi/DigitalRace2019을 참고하여 작성했다.
2.2. object_detection lane detection 알고리즘은 BuiKhoi/DigitalRace2019을 참고하여 작성했다.
If you have any questions, please email below.
- dazory: 12181851@inha.edu
- yuntreee: lewis45626@gmail.com
- airpod2: 12181774@inha.edu
- ka-yeon: 12181736@inha.edu
-
🚘 Mobile Platform
-
📊 Ground Station