mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-29 19:17:28 +08:00
convert to thread-communication
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user