目标: 创建一个GUI,用来控制飞机起飞、降落、左右、前后、上下、旋转,后四者的控制量各自由一个文本框输入。
用GTK实现,顶层窗口只能包含一个组合框,所以顶层一个组合框,向下一个vbox;vbox里包含5个hbox,分别用来放置控制起飞降落、左右、前后、上下、旋转的控件。对于起飞降落,需要两个互斥按钮;其余四种动作,各自需要标签、文本框和按钮各一个。
首先创建gui.c,
#
include <stdlib.h>
# include <stdio.h>
# include "gui.h"
# include <ardrone_tool/UI/ardrone_input.h>
# include <VP_Os/vp_os_delay.h>
# include <ardrone_api.h>
static GtkWidget *window ; //top widget--widow
//----------- buttons----------
static GtkWidget *btnStop ;
static GtkWidget *btnStart ;
static GtkWidget *btnLeftRight ;
static GtkWidget *btnFrontBack ;
static GtkWidget *btnUpDown ;
static GtkWidget *btnAngular ;
//------------ text entries--------
static GtkWidget *textLeftright ;
static GtkWidget *textFrontBack ;
static GtkWidget *textUpDown ;
static GtkWidget *textAngular ;
//-------------get and set Start/Stop buttons state-----
static void toggleButtonsState(void)
{
gboolean start_state = gtk_widget_get_sensitive(btnStart) ;
gtk_widget_set_sensitive(btnStart, !start_state) ;
gtk_widget_set_sensitive(btnStop, start_state) ;
}
//-----------Start/Stop buttons callback function------
static void btnlandCallback(GtkWidget *widget,gpointer data)
{
static int landFlag = 1 ; //1-taking off, else land
ardrone_tool_set_ui_pad_start(landFlag) ;
if (landFlag)
g_print( "Taking off") ;
else
g_print( "Landing") ;
landFlag = (landFlag + 1) % 2 ;
toggleButtonsState() ; //Only one button to be clicked
}
static int mode_flag = 1 ;
//-----------LeftRight button callback function
static void btnLRCallback(GtkWidget *widget, gpointer data)
{
float LRVaule ;
const gchar* LRChar = gtk_entry_get_text(GTK_ENTRY(textLeftright)) ;
LRVaule = ( float)strtod(LRChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, LRVaule, 0. 0, 0. 0, 0. 0, 0. 0, 0. 0) ;
}
//--------------FrontBack button callback function
static void btnFBCallback(GtkWidget *widget, gpointer data)
{
float FBVaule ;
const gchar* FBChar = gtk_entry_get_text(GTK_ENTRY(textFrontBack)) ;
FBVaule = ( float)strtod(FBChar, NULL) ;
//int i ;
//ardrone_at_reset_com_watchdog() ;
//for(i= 0 ; i<10; i++)
//{
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, FBVaule, 0. 0, 0. 0, 0. 0, 0. 0) ;
// vp_os_delay( 150) ;
//}
//ardrone_at_set_progress_cmd(mode_flag, 0. 0, FBVaule, 0. 0, 0. 0) ;
}
//------------------ UpDown button callback function
static void btnUDCallback(GtkWidget *widget, gpointer data)
{
float UDVaule ;
const gchar* UDChar = gtk_entry_get_text(GTK_ENTRY(textUpDown)) ;
UDVaule = ( float)strtod(UDChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, 0. 0, UDVaule, 0. 0, 0. 0, 0. 0) ;
}
//--------------Angular button callback function
static void btnACallback(GtkWidget *widget, gpointer data)
{
float AVaule ;
const gchar* AChar = gtk_entry_get_text(GTK_ENTRY(textAngular)) ;
AVaule = ( float)strtod(AChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, 0. 0, 0. 0, AVaule, 0. 0, 0. 0) ;
}
//-----------init window--------------
void init_control_gui(int argc, char **argv)
{
GtkWidget *vboxMain ; //top box
//-----box for every control widget
GtkWidget *hboxStartStop ;
GtkWidget *hboxLeftRight ;
GtkWidget *hboxFrontBack ;
GtkWidget *hboxUpDown ;
GtkWidget *hboxAngular ;
//----- label for control text entries
GtkWidget *labelLeftRight ;
GtkWidget *labelFrontBack ;
GtkWidget *labelUpDown ;
GtkWidget *labelAngular ;
g_thread_init(NULL) ;
gtk_init(&argc, &argv) ;
//-----Create window and register its destroy function
window = gtk_window_new(GTK_WINDOW_TOPLEVEL) ;
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER) ;
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit),NULL) ;
//-----Create all boxes
vboxMain = gtk_vbox_new( FALSE, 1) ;
hboxStartStop = gtk_hbox_new( FALSE, 10) ;
hboxLeftRight = gtk_hbox_new( FALSE, 10) ;
hboxFrontBack = gtk_hbox_new( FALSE, 10) ;
hboxUpDown = gtk_hbox_new( FALSE, 10) ;
hboxAngular = gtk_hbox_new( FALSE, 10) ;
//-----Create Start/Stop buttons and put them into a hbox
btnStart = gtk_button_new_with_label( "Taking Off") ;
btnStop = gtk_button_new_with_label( "Landing") ;
gtk_box_pack_start(GTK_BOX(hboxStartStop), btnStart, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxStartStop), btnStop, FALSE, FALSE, 0) ;
//-----Create LeftRight button/ text/ label and put them into a hbox
btnLeftRight = gtk_button_new_with_label( "Left/Right") ;
labelLeftRight = gtk_label_new( "Left/Right Var:") ;
textLeftright = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), labelLeftRight, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), textLeftright, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), btnLeftRight, FALSE, FALSE, 0) ;
//-----Create FrontBack button/ text/ label and put them into a hbox
btnFrontBack = gtk_button_new_with_label( "Front/Back") ;
labelFrontBack = gtk_label_new( "Front/Back Var:") ;
textFrontBack = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), labelFrontBack, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), textFrontBack, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), btnFrontBack, FALSE, FALSE, 0) ;
//-----Create UpDown button/ text/ label and put them into a hbox
btnUpDown = gtk_button_new_with_label( "Up/Down") ;
labelUpDown = gtk_label_new( "Up/Down Var:") ;
textUpDown = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), labelUpDown, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), textUpDown, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), btnUpDown, FALSE, FALSE, 0) ;
//-----Create Angular button/ text/ label and put them into a hbox
btnAngular = gtk_button_new_with_label( "Angular") ;
labelAngular = gtk_label_new( "Angular Var:") ;
textAngular = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxAngular), labelAngular, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxAngular), textAngular, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxAngular), btnAngular, FALSE, FALSE, 0) ;
//-----Register all buttons' callback function
g_signal_connect(btnStart, "clicked", G_CALLBACK(btnlandCallback), NULL) ;
g_signal_connect(btnStop, "clicked", G_CALLBACK(btnlandCallback), NULL) ;
g_signal_connect(btnLeftRight, "clicked", G_CALLBACK(btnLRCallback), NULL) ;
g_signal_connect(btnFrontBack, "clicked", G_CALLBACK(btnFBCallback), NULL) ;
g_signal_connect(btnUpDown, "clicked", G_CALLBACK(btnUDCallback), NULL) ;
g_signal_connect(btnAngular, "clicked", G_CALLBACK(btnACallback), NULL) ;
//-----Set Start/Stop buttons' state to be different at one moment
gtk_widget_set_sensitive(btnStart, TRUE) ;
gtk_widget_set_sensitive(btnStop, FALSE) ;
//-----Put all hbox into vbox
gtk_box_pack_start(GTK_BOX(vboxMain), hboxStartStop, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxLeftRight, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxFrontBack, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxUpDown, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxAngular, TRUE, TRUE, 0) ;
//-----Put vbox into window
gtk_container_add(GTK_CONTAINER(window), vboxMain) ; //a window can only contain one widget
gtk_widget_show_all(window) ;
}
# include <stdio.h>
# include "gui.h"
# include <ardrone_tool/UI/ardrone_input.h>
# include <VP_Os/vp_os_delay.h>
# include <ardrone_api.h>
static GtkWidget *window ; //top widget--widow
//----------- buttons----------
static GtkWidget *btnStop ;
static GtkWidget *btnStart ;
static GtkWidget *btnLeftRight ;
static GtkWidget *btnFrontBack ;
static GtkWidget *btnUpDown ;
static GtkWidget *btnAngular ;
//------------ text entries--------
static GtkWidget *textLeftright ;
static GtkWidget *textFrontBack ;
static GtkWidget *textUpDown ;
static GtkWidget *textAngular ;
//-------------get and set Start/Stop buttons state-----
static void toggleButtonsState(void)
{
gboolean start_state = gtk_widget_get_sensitive(btnStart) ;
gtk_widget_set_sensitive(btnStart, !start_state) ;
gtk_widget_set_sensitive(btnStop, start_state) ;
}
//-----------Start/Stop buttons callback function------
static void btnlandCallback(GtkWidget *widget,gpointer data)
{
static int landFlag = 1 ; //1-taking off, else land
ardrone_tool_set_ui_pad_start(landFlag) ;
if (landFlag)
g_print( "Taking off") ;
else
g_print( "Landing") ;
landFlag = (landFlag + 1) % 2 ;
toggleButtonsState() ; //Only one button to be clicked
}
static int mode_flag = 1 ;
//-----------LeftRight button callback function
static void btnLRCallback(GtkWidget *widget, gpointer data)
{
float LRVaule ;
const gchar* LRChar = gtk_entry_get_text(GTK_ENTRY(textLeftright)) ;
LRVaule = ( float)strtod(LRChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, LRVaule, 0. 0, 0. 0, 0. 0, 0. 0, 0. 0) ;
}
//--------------FrontBack button callback function
static void btnFBCallback(GtkWidget *widget, gpointer data)
{
float FBVaule ;
const gchar* FBChar = gtk_entry_get_text(GTK_ENTRY(textFrontBack)) ;
FBVaule = ( float)strtod(FBChar, NULL) ;
//int i ;
//ardrone_at_reset_com_watchdog() ;
//for(i= 0 ; i<10; i++)
//{
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, FBVaule, 0. 0, 0. 0, 0. 0, 0. 0) ;
// vp_os_delay( 150) ;
//}
//ardrone_at_set_progress_cmd(mode_flag, 0. 0, FBVaule, 0. 0, 0. 0) ;
}
//------------------ UpDown button callback function
static void btnUDCallback(GtkWidget *widget, gpointer data)
{
float UDVaule ;
const gchar* UDChar = gtk_entry_get_text(GTK_ENTRY(textUpDown)) ;
UDVaule = ( float)strtod(UDChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, 0. 0, UDVaule, 0. 0, 0. 0, 0. 0) ;
}
//--------------Angular button callback function
static void btnACallback(GtkWidget *widget, gpointer data)
{
float AVaule ;
const gchar* AChar = gtk_entry_get_text(GTK_ENTRY(textAngular)) ;
AVaule = ( float)strtod(AChar, NULL) ;
ardrone_tool_set_progressive_cmd(mode_flag, 0. 0, 0. 0, 0. 0, AVaule, 0. 0, 0. 0) ;
}
//-----------init window--------------
void init_control_gui(int argc, char **argv)
{
GtkWidget *vboxMain ; //top box
//-----box for every control widget
GtkWidget *hboxStartStop ;
GtkWidget *hboxLeftRight ;
GtkWidget *hboxFrontBack ;
GtkWidget *hboxUpDown ;
GtkWidget *hboxAngular ;
//----- label for control text entries
GtkWidget *labelLeftRight ;
GtkWidget *labelFrontBack ;
GtkWidget *labelUpDown ;
GtkWidget *labelAngular ;
g_thread_init(NULL) ;
gtk_init(&argc, &argv) ;
//-----Create window and register its destroy function
window = gtk_window_new(GTK_WINDOW_TOPLEVEL) ;
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER) ;
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit),NULL) ;
//-----Create all boxes
vboxMain = gtk_vbox_new( FALSE, 1) ;
hboxStartStop = gtk_hbox_new( FALSE, 10) ;
hboxLeftRight = gtk_hbox_new( FALSE, 10) ;
hboxFrontBack = gtk_hbox_new( FALSE, 10) ;
hboxUpDown = gtk_hbox_new( FALSE, 10) ;
hboxAngular = gtk_hbox_new( FALSE, 10) ;
//-----Create Start/Stop buttons and put them into a hbox
btnStart = gtk_button_new_with_label( "Taking Off") ;
btnStop = gtk_button_new_with_label( "Landing") ;
gtk_box_pack_start(GTK_BOX(hboxStartStop), btnStart, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxStartStop), btnStop, FALSE, FALSE, 0) ;
//-----Create LeftRight button/ text/ label and put them into a hbox
btnLeftRight = gtk_button_new_with_label( "Left/Right") ;
labelLeftRight = gtk_label_new( "Left/Right Var:") ;
textLeftright = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), labelLeftRight, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), textLeftright, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxLeftRight), btnLeftRight, FALSE, FALSE, 0) ;
//-----Create FrontBack button/ text/ label and put them into a hbox
btnFrontBack = gtk_button_new_with_label( "Front/Back") ;
labelFrontBack = gtk_label_new( "Front/Back Var:") ;
textFrontBack = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), labelFrontBack, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), textFrontBack, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxFrontBack), btnFrontBack, FALSE, FALSE, 0) ;
//-----Create UpDown button/ text/ label and put them into a hbox
btnUpDown = gtk_button_new_with_label( "Up/Down") ;
labelUpDown = gtk_label_new( "Up/Down Var:") ;
textUpDown = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), labelUpDown, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), textUpDown, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxUpDown), btnUpDown, FALSE, FALSE, 0) ;
//-----Create Angular button/ text/ label and put them into a hbox
btnAngular = gtk_button_new_with_label( "Angular") ;
labelAngular = gtk_label_new( "Angular Var:") ;
textAngular = gtk_entry_new() ;
gtk_box_pack_start(GTK_BOX(hboxAngular), labelAngular, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxAngular), textAngular, FALSE, FALSE, 0) ;
gtk_box_pack_start(GTK_BOX(hboxAngular), btnAngular, FALSE, FALSE, 0) ;
//-----Register all buttons' callback function
g_signal_connect(btnStart, "clicked", G_CALLBACK(btnlandCallback), NULL) ;
g_signal_connect(btnStop, "clicked", G_CALLBACK(btnlandCallback), NULL) ;
g_signal_connect(btnLeftRight, "clicked", G_CALLBACK(btnLRCallback), NULL) ;
g_signal_connect(btnFrontBack, "clicked", G_CALLBACK(btnFBCallback), NULL) ;
g_signal_connect(btnUpDown, "clicked", G_CALLBACK(btnUDCallback), NULL) ;
g_signal_connect(btnAngular, "clicked", G_CALLBACK(btnACallback), NULL) ;
//-----Set Start/Stop buttons' state to be different at one moment
gtk_widget_set_sensitive(btnStart, TRUE) ;
gtk_widget_set_sensitive(btnStop, FALSE) ;
//-----Put all hbox into vbox
gtk_box_pack_start(GTK_BOX(vboxMain), hboxStartStop, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxLeftRight, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxFrontBack, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxUpDown, TRUE, TRUE, 0) ;
gtk_box_pack_start(GTK_BOX(vboxMain), hboxAngular, TRUE, TRUE, 0) ;
//-----Put vbox into window
gtk_container_add(GTK_CONTAINER(window), vboxMain) ; //a window can only contain one widget
gtk_widget_show_all(window) ;
}
创建gui.h,
#ifndef GUI_H_
#define GUI_H_
# include <gtk- 2. 0/gtk/gtk.h>
# include <cairo.h>
void init_control_gui(int argc, char **argv) ;
#endif
#define GUI_H_
# include <gtk- 2. 0/gtk/gtk.h>
# include <cairo.h>
void init_control_gui(int argc, char **argv) ;
#endif
将以上两个文件添加到
sdk_demo/Source里面的UI文件夹,在ardrone_testing_tool.c里添加GTK线程,
#include "UI/gui.h"
DEFINE_THREAD_ROUTINE(gui, data)
{
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
}
在main函数里添加,
init_control_gui(argc, argv)
在ardrone_tool_init_custom函数里启动线程,
START_THREAD(gui, NULL);
在ardrone_tool_shutdown_custom函数里关闭线程,
JOIN_THREAD(gui);
修改
ardrone_testing_tool.c结尾的
Thread Table,
最后,修改Makefile即可,
GENERIC_BINARIES_COMMON_SOURCE_FILES+= \
Navdata/navdata.c \
Video/video_stage.c \
UI/gui.c
GENERIC_LIBS=-lpc_ardrone -lgtk-x11-2.0 -lrt `pkg-config --libs gthread-2.0`
注:main函数里建立了gtk线程,如果在其他线程里,比如video_stage或navdata_update,想要对界面上的控件(比如Label)做一些改变,可以通过如下方式进行,
gdk_threads_enter();
/*******Your code here*****************/
gdk_threads_leave();
顺便提一下添加navdata_update线程的方法:将sdk_demo里Navdata文件夹拷贝到你的工程源文件目录下,在Thread Table添加,
THREAD_TABLE_ENTRY(navdata_update, 20)
然后在Makefile里的编译源文件加上
Navdata/navdata.c,
就完成了,该线程由SDK的ardrone_tool_main函数自己启动,不用自己在
ardrone_tool_init_custom和
ardrone_tool_shutdown_custom函数里开启和启动
。