目标: 创建一个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)
;
}
创建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
将以上两个文件添加到
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函数里开启和启动
。