基于GTK创建ARDrone 2.0控制线程

来源:互联网 发布:破解版360企业云盘mac 编辑:程序博客网 时间:2024/06/07 10:26
        目标: 创建一个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.00.00.00.00.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.00.00.00.0)
        //     vp_os_delay(150)
        //}              
        //ardrone_at_set_progress_cmd(mode_flag, 0.0, FBVaule, 0.00.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.00.0, UDVaule, 0.00.00.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.00.00.0, AVaule, 0.00.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(FALSE1);
        hboxStartStop = gtk_hbox_new(FALSE10);
        hboxLeftRight = gtk_hbox_new(FALSE10);
        hboxFrontBack = gtk_hbox_new(FALSE10);
        hboxUpDown = gtk_hbox_new(FALSE10);
        hboxAngular = gtk_hbox_new(FALSE10);

        //-----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, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxStartStop), btnStop, FALSEFALSE0);

        //-----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, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxLeftRight), textLeftright, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxLeftRight), btnLeftRight, FALSEFALSE,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, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxFrontBack), textFrontBack, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxFrontBack), btnFrontBack, FALSEFALSE,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, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxUpDown), textUpDown, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxUpDown), btnUpDown, FALSEFALSE,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, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxAngular), textAngular, FALSEFALSE0);
        gtk_box_pack_start(GTK_BOX(hboxAngular), btnAngular, FALSEFALSE,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, TRUETRUE0);
        gtk_box_pack_start(GTK_BOX(vboxMain), hboxLeftRight, TRUETRUE0);
        gtk_box_pack_start(GTK_BOX(vboxMain), hboxFrontBack, TRUETRUE0);
        gtk_box_pack_start(GTK_BOX(vboxMain), hboxUpDown, TRUETRUE0);
        gtk_box_pack_start(GTK_BOX(vboxMain), hboxAngular, TRUETRUE0);

        //-----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函数里开启和启动





0 0