convert to thread-communication

This commit is contained in:
dewagter
2015-02-05 17:28:50 +01:00
parent dfa33e4824
commit ec745f0264
11 changed files with 345 additions and 237 deletions
+3 -1
View File
@@ -43,16 +43,18 @@
<init fun="opticflow_module_init()"/> <init fun="opticflow_module_init()"/>
<periodic fun="opticflow_module_run()" freq="60" start="opticflow_module_start()" stop="opticflow_module_stop()" autorun="TRUE"/> <periodic fun="opticflow_module_run()" start="opticflow_module_start()" stop="opticflow_module_stop()" autorun="TRUE"/>
<makefile target="ap"> <makefile target="ap">
<define name="ARDRONE_VIDEO_PORT" value="2002" /> <define name="ARDRONE_VIDEO_PORT" value="2002" />
<file name="opticflow_module.c"/> <file name="opticflow_module.c"/>
<file name="opticflow_thread.c" dir="modules/computer_vision/opticflow"/>
<file name="visual_estimator.c" dir="modules/computer_vision/opticflow"/> <file name="visual_estimator.c" dir="modules/computer_vision/opticflow"/>
<file name="hover_stabilization.c" dir="modules/computer_vision/opticflow"/> <file name="hover_stabilization.c" dir="modules/computer_vision/opticflow"/>
<file name="optic_flow_int.c" dir="modules/computer_vision/cv/opticflow"/> <file name="optic_flow_int.c" dir="modules/computer_vision/cv/opticflow"/>
<file name="fastRosten.c" dir="modules/computer_vision/cv/opticflow/fast9"/> <file name="fastRosten.c" dir="modules/computer_vision/cv/opticflow/fast9"/>
<file name="trig.c" dir="modules/computer_vision/cv"/> <file name="trig.c" dir="modules/computer_vision/cv"/>
<file name="framerate.c" dir="modules/computer_vision/cv"/>
<file name="jpeg.c" dir="modules/computer_vision/cv/encoding"/> <file name="jpeg.c" dir="modules/computer_vision/cv/encoding"/>
<file name="rtp.c" dir="modules/computer_vision/cv/encoding"/> <file name="rtp.c" dir="modules/computer_vision/cv/encoding"/>
<file name="socket.c" dir="modules/computer_vision/lib/udp"/> <file name="socket.c" dir="modules/computer_vision/lib/udp"/>
@@ -0,0 +1,54 @@
#include "std.h"
#include "framerate.h"
// Frame Rate (FPS)
#include <sys/time.h>
// local variables
volatile long timestamp;
struct timeval start_time;
struct timeval end_time;
#define USEC_PER_SEC 1000000L
float FPS;
static long time_elapsed(struct timeval *t1, struct timeval *t2)
{
long sec, usec;
sec = t2->tv_sec - t1->tv_sec;
usec = t2->tv_usec - t1->tv_usec;
if (usec < 0) {
--sec;
usec = usec + USEC_PER_SEC;
}
return sec * USEC_PER_SEC + usec;
}
static void start_timer(void)
{
gettimeofday(&start_time, NULL);
}
static long end_timer(void)
{
gettimeofday(&end_time, NULL);
return time_elapsed(&start_time, &end_time);
}
void framerate_init(void) {
// Frame Rate Initialization
FPS = 0.0;
timestamp = 0;
start_timer();
}
void framerate_run(void) {
// FPS
timestamp = end_timer();
FPS = (float) 1000000 / (float)timestamp;
// printf("dt = %d, FPS = %f\n",timestamp, FPS);
start_timer();
}
@@ -0,0 +1,5 @@
extern float FPS;
void framerate_init(void);
void framerate_run(void);
@@ -29,11 +29,7 @@
// Own Header // Own Header
#include "hover_stabilization.h" #include "hover_stabilization.h"
// Vision Data
#include "visual_estimator.h"
// Stabilization // Stabilization
//#include "stabilization.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude.h" #include "firmwares/rotorcraft/stabilization/stabilization_attitude.h"
#include "firmwares/rotorcraft/guidance/guidance_v.h" #include "firmwares/rotorcraft/guidance/guidance_v.h"
#include "autopilot.h" #include "autopilot.h"
@@ -144,15 +140,12 @@ void init_hover_stabilization_onvision()
Vely_Int = 0; Vely_Int = 0;
} }
void run_hover_stabilization_onvision(void) void run_hover_stabilization_onvision(struct CVresults* vision )
{ {
if (autopilot_mode == AP_MODE_MODULE) { if (autopilot_mode != AP_MODE_MODULE) {
run_opticflow_hover(); return;
} }
}
void run_opticflow_hover(void)
{
struct FloatVect3 V_body; struct FloatVect3 V_body;
if (activate_opticflow_hover == TRUE) { if (activate_opticflow_hover == TRUE) {
// Compute body velocities from ENU // Compute body velocities from ENU
@@ -161,9 +154,9 @@ void run_opticflow_hover(void)
float_quat_vmult(&V_body, q_n2b, vel_ned); float_quat_vmult(&V_body, q_n2b, vel_ned);
} }
if (flow_count) { if (vision->flow_count) {
Error_Velx = Velx - vision_desired_vx; Error_Velx = vision->Velx - vision_desired_vx;
Error_Vely = Vely - vision_desired_vy; Error_Vely = vision->Vely - vision_desired_vy;
} else { } else {
Error_Velx = 0; Error_Velx = 0;
Error_Vely = 0; Error_Vely = 0;
@@ -204,6 +197,6 @@ void run_opticflow_hover(void)
else if (cmd_euler.theta > CMD_OF_SAT) {cmd_euler.theta = CMD_OF_SAT; saturateY = 1;} else if (cmd_euler.theta > CMD_OF_SAT) {cmd_euler.theta = CMD_OF_SAT; saturateY = 1;}
stabilization_attitude_set_rpy_setpoint_i(&cmd_euler); stabilization_attitude_set_rpy_setpoint_i(&cmd_euler);
DOWNLINK_SEND_VISION_STABILIZATION(DefaultChannel, DefaultDevice, &Velx, &Vely, &Velx_Int, DOWNLINK_SEND_VISION_STABILIZATION(DefaultChannel, DefaultDevice, &vision->Velx, &vision->Vely, &Velx_Int,
&Vely_Int, &cmd_euler.phi, &cmd_euler.theta); &Vely_Int, &cmd_euler.phi, &cmd_euler.theta);
} }
@@ -30,6 +30,7 @@
#define HOVER_STABILIZATION_H_ #define HOVER_STABILIZATION_H_
#include <std.h> #include <std.h>
#include "inter_thread_data.h"
// Controller module // Controller module
@@ -46,7 +47,7 @@ extern void guidance_h_module_run(bool_t in_flight);
void init_hover_stabilization_onvision(void); void init_hover_stabilization_onvision(void);
void run_hover_stabilization_onvision(void); void run_hover_stabilization_onvision(struct CVresults *vision);
extern bool activate_opticflow_hover; extern bool activate_opticflow_hover;
extern float vision_desired_vx; extern float vision_desired_vx;
@@ -0,0 +1,28 @@
#ifndef _INTER_THREAD_DATA_H
#define _INTER_THREAD_DATA_H
// Inter-thread communication: Unix Socket
// Data from thread to module
struct CVresults {
int x;
int status;
float Velx;
float Vely;
int flow_count;
};
// Data from module to thread
struct PPRZinfo {
int cnt;
float theta;
float phi;
float agl;
};
#endif
@@ -0,0 +1,121 @@
// Sockets
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "opticflow_thread.h"
/////////////////////////////////////////////////////////////////////////
// COMPUTER VISION THREAD
// Video
#include "v4l/video.h"
#include "resize.h"
// Payload Code
#include "visual_estimator.h"
// Downlink Video
//#define DOWNLINK_VIDEO 1
#ifdef DOWNLINK_VIDEO
#include "encoding/jpeg.h"
#include "encoding/rtp.h"
#endif
#include <stdio.h>
static volatile enum{RUN,EXIT} computer_vision_thread_command = RUN; /** request to close: set to 1 */
void computervision_thread_request_exit(void) {
computer_vision_thread_command = 0;
}
void *computervision_thread_main(void *args)
{
int thread_socket = *(int *) args;
int cnt = 0;
computer_vision_thread_command = RUN;
struct CVresults vision_results;
struct PPRZinfo autopilot_data;
// Video Input
struct vid_struct vid;
vid.device = (char *)"/dev/video2"; // video1 = front camera; video2 = bottom camera
vid.w = 320;
vid.h = 240;
vid.n_buffers = 4;
vision_results.status = 1;
if (video_init(&vid) < 0) {
printf("Error initialising video\n");
vision_results.status = -1;
return 0;
}
// Video Grabbing
struct img_struct *img_new = video_create_image(&vid);
#ifdef DOWNLINK_VIDEO
// Video Compression
uint8_t *jpegbuf = (uint8_t *)malloc(vid.h * vid.w * 2);
// Network Transmit
struct UdpSocket *vsock;
//#define FMS_UNICAST 0
//#define FMS_BROADCAST 1
vsock = udp_socket("192.168.1.255", 5000, 5001, FMS_BROADCAST);
#endif
// First Apply Settings before init
opticflow_plugin_init(vid.w, vid.h, &vision_results);
while (computer_vision_thread_command > 0) {
vision_results.status = 2;
video_grab_image(&vid, img_new);
// Get most recent State
int bytes_read = read(thread_socket, &autopilot_data, sizeof(autopilot_data));
if (bytes_read <= sizeof(autopilot_data)) {
if (bytes_read != 0) {
printf("Failed to read PPRZ info from socket.\n");
}
}
// Run Image Processing
opticflow_plugin_run(img_new->buf, &autopilot_data, &vision_results);
/* send results to main */
vision_results.x = cnt++;
int bytes_written = write(thread_socket, &vision_results, sizeof(vision_results));
if (bytes_written != sizeof(vision_results)){
perror("failed to write to socket.\n");
}
#ifdef DOWNLINK_VIDEO
// JPEG encode the image:
uint32_t quality_factor = 10; //20 if no resize,
uint8_t dri_header = 0;
uint32_t image_format = FOUR_TWO_TWO; // format (in jpeg.h)
uint8_t *end = encode_image(small.buf, jpegbuf, quality_factor, image_format, small.w, small.h, dri_header);
uint32_t size = end - (jpegbuf);
printf("Sending an image ...%u\n", size);
uint32_t delta_t_per_frame = 0; // 0 = use drone clock
send_rtp_frame(vsock, jpegbuf, size, small.w, small.h, 0, quality_factor, dri_header, delta_t_per_frame);
#endif
}
printf("Thread Closed\n");
video_close(&vid);
vision_results.status = -100;
return 0;
}
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2015 The Paparazzi Community
*
* This file is part of Paparazzi.
*
* Paparazzi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* Paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Paparazzi; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
/**
* @file modules/computer_vision/opticflow/opticflow_thread.c
* @brief computer vision thread
*
* Sensors from vertical camera and IMU of Parrot AR.Drone 2.0
*/
#include "std.h"
void *computervision_thread_main(void *args); /* computer vision thread: should be given a pointer to a socketpair as argument */
void computervision_thread_request_exit(void);
@@ -25,7 +25,10 @@
* Sensors from vertical camera and IMU of Parrot AR.Drone 2.0 * Sensors from vertical camera and IMU of Parrot AR.Drone 2.0
*/ */
// Warning: all this code is called form the Vision-Thread: do not access any autopilot data in here.
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
// Own Header // Own Header
@@ -36,17 +39,7 @@
#include "opticflow/fast9/fastRosten.h" #include "opticflow/fast9/fastRosten.h"
// for FPS // for FPS
#include "modules/computer_vision/opticflow_module.h" #include "modules/computer_vision/cv/framerate.h"
// Paparazzi Data
#include "state.h"
#include "subsystems/abi.h"
// Downlink
#include "subsystems/datalink/downlink.h"
// Timer
#include <sys/time.h>
// Image size set at init // Image size set at init
unsigned int imgWidth, imgHeight; unsigned int imgWidth, imgHeight;
@@ -71,7 +64,6 @@ int max_count = 25;
// Corner Tracking // Corner Tracking
int *new_x, *new_y, *status, *dx, *dy; int *new_x, *new_y, *status, *dx, *dy;
int error_opticflow; int error_opticflow;
int flow_count = 0;
int remove_point; int remove_point;
int c; int c;
int borderx = 24, bordery = 24; int borderx = 24, bordery = 24;
@@ -84,30 +76,10 @@ float distance2, min_distance, min_distance2;
float curr_pitch, curr_roll, prev_pitch, prev_roll; float curr_pitch, curr_roll, prev_pitch, prev_roll;
float cam_h, diff_roll, diff_pitch, OFx_trans, OFy_trans; float cam_h, diff_roll, diff_pitch, OFx_trans, OFy_trans;
// Lateral Velocity Computation
float Velx, Vely;
/** height above ground level, from ABI
* Used for scale computation, negative value means invalid.
*/
volatile float estimator_agl;
/** default sonar/agl to use in opticflow visual_estimator */
#ifndef OPTICFLOW_AGL_ID
#define OPTICFLOW_AGL_ID ABI_BROADCAST
#endif
abi_event agl_ev;
static void agl_cb(uint8_t sender_id, const float *distance);
static void agl_cb(uint8_t sender_id __attribute__((unused)), const float *distance)
{
if (*distance > 0) {
estimator_agl = *distance;
}
}
// Called by plugin // Called by plugin
void opticflow_plugin_init(unsigned int w, unsigned int h) void opticflow_plugin_init(unsigned int w, unsigned int h, struct CVresults *results)
{ {
// Initialize variables // Initialize variables
imgWidth = w; imgWidth = w;
@@ -136,16 +108,17 @@ void opticflow_plugin_init(unsigned int w, unsigned int h)
curr_roll = 0.0; curr_roll = 0.0;
OFx_trans = 0.0; OFx_trans = 0.0;
OFy_trans = 0.0; OFy_trans = 0.0;
Velx = 0.0; results->Velx = 0.0;
Vely = 0.0; results->Vely = 0.0;
results->flow_count = 0;
// get AGL from sonar via ABI framerate_init();
estimator_agl = -1.0;
AbiBindMsgAGL(OPTICFLOW_AGL_ID, &agl_ev, agl_cb);
} }
void opticflow_plugin_run(unsigned char *frame) void opticflow_plugin_run(unsigned char *frame, struct PPRZinfo* info, struct CVresults *results)
{ {
framerate_run();
if (old_img_init == 1) { if (old_img_init == 1) {
memcpy(prev_frame, frame, imgHeight * imgWidth * 2); memcpy(prev_frame, frame, imgHeight * imgWidth * 2);
CvtYUYV2Gray(prev_gray_frame, prev_frame, imgWidth, imgHeight); CvtYUYV2Gray(prev_gray_frame, prev_frame, imgWidth, imgHeight);
@@ -213,7 +186,7 @@ void opticflow_plugin_run(unsigned char *frame)
error_opticflow = opticFlowLK(gray_frame, prev_gray_frame, x, y, count_fil, imgWidth, error_opticflow = opticFlowLK(gray_frame, prev_gray_frame, x, y, count_fil, imgWidth,
imgHeight, new_x, new_y, status, 5, 100); imgHeight, new_x, new_y, status, 5, 100);
flow_count = count_fil; results->flow_count = count_fil;
for (int i = count_fil - 1; i >= 0; i--) { for (int i = count_fil - 1; i >= 0; i--) {
remove_point = 1; remove_point = 1;
@@ -223,13 +196,13 @@ void opticflow_plugin_run(unsigned char *frame)
} }
if (remove_point) { if (remove_point) {
for (c = i; c < flow_count - 1; c++) { for (c = i; c < results->flow_count - 1; c++) {
x[c] = x[c + 1]; x[c] = x[c + 1];
y[c] = y[c + 1]; y[c] = y[c + 1];
new_x[c] = new_x[c + 1]; new_x[c] = new_x[c + 1];
new_y[c] = new_y[c + 1]; new_y[c] = new_y[c + 1];
} }
flow_count--; results->flow_count--;
} }
} }
@@ -237,27 +210,26 @@ void opticflow_plugin_run(unsigned char *frame)
dy_sum = 0.0; dy_sum = 0.0;
// Optical Flow Computation // Optical Flow Computation
for (int i = 0; i < flow_count; i++) { for (int i = 0; i < results->flow_count; i++) {
dx[i] = new_x[i] - x[i]; dx[i] = new_x[i] - x[i];
dy[i] = new_y[i] - y[i]; dy[i] = new_y[i] - y[i];
} }
// Median Filter // Median Filter
if (flow_count) { if (results->flow_count) {
quick_sort_int(dx, flow_count); // 11 quick_sort_int(dx, results->flow_count); // 11
quick_sort_int(dy, flow_count); // 11 quick_sort_int(dy, results->flow_count); // 11
dx_sum = (float) dx[flow_count / 2]; dx_sum = (float) dx[results->flow_count / 2];
dy_sum = (float) dy[flow_count / 2]; dy_sum = (float) dy[results->flow_count / 2];
} else { } else {
dx_sum = 0.0; dx_sum = 0.0;
dy_sum = 0.0; dy_sum = 0.0;
} }
// Flow Derotation // Flow Derotation
// !!WARNING!! Accessing of the state interface is NOT tread safe!!! curr_pitch = info->theta;
curr_pitch = stateGetNedToBodyEulers_f()->theta; curr_roll = info->phi;
curr_roll = stateGetNedToBodyEulers_f()->phi;
diff_pitch = (curr_pitch - prev_pitch) * imgHeight / FOV_H; diff_pitch = (curr_pitch - prev_pitch) * imgHeight / FOV_H;
diff_roll = (curr_roll - prev_roll) * imgWidth / FOV_W; diff_roll = (curr_roll - prev_roll) * imgWidth / FOV_W;
@@ -266,7 +238,7 @@ void opticflow_plugin_run(unsigned char *frame)
prev_roll = curr_roll; prev_roll = curr_roll;
#ifdef FLOW_DEROTATION #ifdef FLOW_DEROTATION
if (flow_count) { if (results->flow_count) {
OFx_trans = dx_sum - diff_roll; OFx_trans = dx_sum - diff_roll;
OFy_trans = dy_sum - diff_pitch; OFy_trans = dy_sum - diff_pitch;
@@ -284,22 +256,22 @@ void opticflow_plugin_run(unsigned char *frame)
#endif #endif
// Average Filter // Average Filter
OFfilter(&OFx, &OFy, OFx_trans, OFy_trans, flow_count, 1); OFfilter(&OFx, &OFy, OFx_trans, OFy_trans, results->flow_count, 1);
// Velocity Computation // Velocity Computation
if (estimator_agl < 0) { if (info->agl < 0) {
cam_h = 1; cam_h = 1;
} }
else { else {
cam_h = estimator_agl; cam_h = info->agl;
} }
if (flow_count) { if (results->flow_count) {
Velx = OFy * cam_h * FPS / Fy_ARdrone + 0.05; results->Velx = OFy * cam_h * FPS / Fy_ARdrone + 0.05;
Vely = -OFx * cam_h * FPS / Fx_ARdrone - 0.1; results->Vely = -OFx * cam_h * FPS / Fx_ARdrone - 0.1;
} else { } else {
Velx = 0.0; results->Velx = 0.0;
Vely = 0.0; results->Vely = 0.0;
} }
// ************************************************************************************* // *************************************************************************************
@@ -28,16 +28,15 @@
#ifndef VISUAL_ESTIMATOR_H #ifndef VISUAL_ESTIMATOR_H
#define VISUAL_ESTIMATOR_H #define VISUAL_ESTIMATOR_H
// Variables used by the controller
extern float Velx, Vely; #include "inter_thread_data.h"
extern int flow_count;
/** /**
* Initialize visual estimator. * Initialize visual estimator.
* @param w image width * @param w image width
* @param h image height * @param h image height
*/ */
void opticflow_plugin_init(unsigned int w, unsigned int h); void opticflow_plugin_init(unsigned int w, unsigned int h, struct CVresults *results);
void opticflow_plugin_run(unsigned char *frame); void opticflow_plugin_run(unsigned char *frame, struct PPRZinfo* info, struct CVresults* results);
#endif /* VISUAL_ESTIMATOR_H */ #endif /* VISUAL_ESTIMATOR_H */
@@ -28,200 +28,101 @@
#include "opticflow_module.h" #include "opticflow_module.h"
// Computervision Runs in a thread
#include "opticflow/opticflow_thread.h"
#include "opticflow/inter_thread_data.h"
// Navigate Based On Vision, needed to call init/run_hover_stabilization_onvision // Navigate Based On Vision, needed to call init/run_hover_stabilization_onvision
#include "opticflow/hover_stabilization.h" #include "opticflow/hover_stabilization.h"
// Threaded computer vision // Threaded computer vision
#include <pthread.h> #include <pthread.h>
// Frame Rate (FPS)
#include <sys/time.h>
// Sockets // Sockets
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#define USEC_PER_SEC 1000000L
float FPS;
struct CVresults {
int x;
};
int cv_sockets[2]; int cv_sockets[2];
// Paparazzi Data
#include "state.h"
#include "subsystems/abi.h"
// local variables // Downlink
volatile long timestamp; #include "subsystems/datalink/downlink.h"
struct timeval start_time;
struct timeval end_time;
static long time_elapsed(struct timeval *t1, struct timeval *t2)
struct PPRZinfo opticflow_module_data;
/** height above ground level, from ABI
* Used for scale computation, negative value means invalid.
*/
/** default sonar/agl to use in opticflow visual_estimator */
#ifndef OPTICFLOW_AGL_ID
#define OPTICFLOW_AGL_ID ABI_BROADCAST
#endif
abi_event agl_ev;
static void agl_cb(uint8_t sender_id, const float *distance);
static void agl_cb(uint8_t sender_id __attribute__((unused)), const float *distance)
{ {
long sec, usec; if (*distance > 0) {
sec = t2->tv_sec - t1->tv_sec; opticflow_module_data.agl = *distance;
usec = t2->tv_usec - t1->tv_usec;
if (usec < 0) {
--sec;
usec = usec + USEC_PER_SEC;
} }
return sec * USEC_PER_SEC + usec;
}
static void start_timer(void)
{
gettimeofday(&start_time, NULL);
}
static long end_timer(void)
{
gettimeofday(&end_time, NULL);
return time_elapsed(&start_time, &end_time);
} }
void opticflow_module_init(void) void opticflow_module_init(void)
{ {
// Immediately start the vision thread when the module initialized // get AGL from sonar via ABI
opticflow_module_start(); AbiBindMsgAGL(OPTICFLOW_AGL_ID, &agl_ev, agl_cb);
// Initialize local data
opticflow_module_data.cnt = 0;
opticflow_module_data.phi = 0;
opticflow_module_data.theta = 0;
opticflow_module_data.agl = 0;
// Stabilization Code Initialization // Stabilization Code Initialization
init_hover_stabilization_onvision(); init_hover_stabilization_onvision();
// Frame Rate Initialization
FPS = 0.0;
timestamp = 0;
start_timer();
} }
volatile uint8_t computervision_thread_has_results = 0;
void opticflow_module_run(void) void opticflow_module_run(void)
{ {
// Send Updated data to thread
opticflow_module_data.cnt++;
opticflow_module_data.phi = stateGetNedToBodyEulers_f()->phi;
opticflow_module_data.theta = stateGetNedToBodyEulers_f()->theta;
int bytes_written = write(cv_sockets[0], &opticflow_module_data, sizeof(opticflow_module_data));
if (bytes_written != sizeof(opticflow_module_data)){
perror("module failed to write to socket.\n");
}
// Read Latest Vision Module Results // Read Latest Vision Module Results
if (computervision_thread_has_results) { struct CVresults vision_results;
struct CVresults res; int bytes_read = read(cv_sockets[0], &vision_results, sizeof(vision_results));
if (read(cv_sockets[0], &res, sizeof(res))) { if (bytes_read <= sizeof(vision_results)) {
perror("Failed to read CV results from socket.\n"); if (bytes_read != 0) {
printf("Failed to read CV results from socket.\n");
} }
/* TODO: use results */ } else {
printf("result x=%i", res.x); ////////////////////////////////////////////
// Module-Side Code
computervision_thread_has_results = 0; ////////////////////////////////////////////
run_hover_stabilization_onvision(); run_hover_stabilization_onvision(&vision_results);
} }
} }
/////////////////////////////////////////////////////////////////////////
// COMPUTER VISION THREAD
// Video
#include "v4l/video.h"
#include "resize.h"
// Payload Code
#include "opticflow/visual_estimator.h"
// Downlink Video
//#define DOWNLINK_VIDEO 1
#ifdef DOWNLINK_VIDEO
#include "encoding/jpeg.h"
#include "encoding/rtp.h"
#endif
#include <stdio.h>
pthread_t computervision_thread;
volatile uint8_t computervision_thread_status = 0;
volatile uint8_t computer_vision_thread_command = 0;
void *computervision_thread_main(void *args);
void *computervision_thread_main(void *args)
{
int socket = *(int *) args;
// Video Input
struct vid_struct vid;
vid.device = (char *)"/dev/video2"; // video1 = front camera; video2 = bottom camera
vid.w = 320;
vid.h = 240;
vid.n_buffers = 4;
if (video_init(&vid) < 0) {
printf("Error initialising video\n");
computervision_thread_status = -1;
return 0;
}
// Video Grabbing
struct img_struct *img_new = video_create_image(&vid);
#ifdef DOWNLINK_VIDEO
// Video Compression
uint8_t *jpegbuf = (uint8_t *)malloc(vid.h * vid.w * 2);
// Network Transmit
struct UdpSocket *vsock;
//#define FMS_UNICAST 0
//#define FMS_BROADCAST 1
vsock = udp_socket("192.168.1.255", 5000, 5001, FMS_BROADCAST);
#endif
// First Apply Settings before init
opticflow_plugin_init(vid.w, vid.h);
while (computer_vision_thread_command > 0) {
video_grab_image(&vid, img_new);
// FPS
timestamp = end_timer();
FPS = (float) 1000000 / (float)timestamp;
// printf("dt = %d, FPS = %f\n",timestamp, FPS);
start_timer();
// Run Image Processing
opticflow_plugin_run(img_new->buf);
/* send results to main */
struct CVresults data;
/* TODO: fill in results here */
data.x = 42;
if (write(socket, &data, sizeof(data))) {
printf("failed to write to socket.\n");
}
#ifdef DOWNLINK_VIDEO
// JPEG encode the image:
uint32_t quality_factor = 10; //20 if no resize,
uint8_t dri_header = 0;
uint32_t image_format = FOUR_TWO_TWO; // format (in jpeg.h)
uint8_t *end = encode_image(small.buf, jpegbuf, quality_factor, image_format, small.w, small.h, dri_header);
uint32_t size = end - (jpegbuf);
printf("Sending an image ...%u\n", size);
uint32_t delta_t_per_frame = 0; // 0 = use drone clock
send_rtp_frame(vsock, jpegbuf, size, small.w, small.h, 0, quality_factor, dri_header, delta_t_per_frame);
#endif
computervision_thread_has_results++;
}
printf("Thread Closed\n");
video_close(&vid);
computervision_thread_status = -100;
return 0;
}
void opticflow_module_start(void) void opticflow_module_start(void)
{ {
/* create socket pair for communication */ pthread_t computervision_thread;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, cv_sockets) == 0) { if (socketpair(AF_UNIX, SOCK_DGRAM, 0, cv_sockets) == 0) {
computer_vision_thread_command = 1; ////////////////////////////////////////////
// Thread-Side Code
////////////////////////////////////////////
int rc = pthread_create(&computervision_thread, NULL, computervision_thread_main, int rc = pthread_create(&computervision_thread, NULL, computervision_thread_main,
&cv_sockets[1]); &cv_sockets[1]);
if (rc) { if (rc) {
@@ -235,5 +136,5 @@ void opticflow_module_start(void)
void opticflow_module_stop(void) void opticflow_module_stop(void)
{ {
computer_vision_thread_command = 0; computervision_thread_request_exit();
} }