فهرست منبع

Merge branch 'master' of http://118.24.47.114/madesheng/self-driving-robot

madesheng 4 سال پیش
والد
کامیت
ce6b427cc5

+ 53 - 0
src/hmi/CMakeLists.txt

@@ -0,0 +1,53 @@
+##############################################################################
+# CMake
+##############################################################################
+
+cmake_minimum_required(VERSION 2.8.0)
+project(hmi)
+
+##############################################################################
+# Catkin
+##############################################################################
+
+# qt_build provides the qt cmake glue, roscpp the comms for a default talker
+find_package(catkin REQUIRED COMPONENTS qt_build roscpp)
+include_directories(${catkin_INCLUDE_DIRS})
+# Use this to define what the package will export (e.g. libs, headers).
+# Since the default here is to produce only a binary, we don't worry about
+# exporting anything. 
+catkin_package()
+
+##############################################################################
+# Qt Environment
+##############################################################################
+
+# this comes from qt_build's qt-ros.cmake which is automatically 
+# included via the dependency call in package.xml
+rosbuild_prepare_qt4(QtCore QtGui) # Add the appropriate components to the component list here
+
+##############################################################################
+# Sections
+##############################################################################
+
+file(GLOB QT_FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ui/*.ui)
+file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*.qrc)
+file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/hmi/*.hpp)
+
+QT4_ADD_RESOURCES(QT_RESOURCES_CPP ${QT_RESOURCES})
+QT4_WRAP_UI(QT_FORMS_HPP ${QT_FORMS})
+QT4_WRAP_CPP(QT_MOC_HPP ${QT_MOC})
+
+##############################################################################
+# Sources
+##############################################################################
+
+file(GLOB_RECURSE QT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)
+
+##############################################################################
+# Binaries
+##############################################################################
+
+add_executable(hmi ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_FORMS_HPP} ${QT_MOC_HPP})
+target_link_libraries(hmi ${QT_LIBRARIES} ${catkin_LIBRARIES})
+install(TARGETS hmi RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
+

+ 67 - 0
src/hmi/include/hmi/main_window.hpp

@@ -0,0 +1,67 @@
+/**
+ * @file /include/hmi/main_window.hpp
+ *
+ * @brief Qt based gui for hmi.
+ *
+ * @date November 2010
+ **/
+#ifndef hmi_MAIN_WINDOW_H
+#define hmi_MAIN_WINDOW_H
+
+/*****************************************************************************
+** Includes
+*****************************************************************************/
+
+#include <QtGui/QMainWindow>
+#include "ui_main_window.h"
+#include "qnode.hpp"
+
+/*****************************************************************************
+** Namespace
+*****************************************************************************/
+
+namespace hmi {
+
+/*****************************************************************************
+** Interface [MainWindow]
+*****************************************************************************/
+/**
+ * @brief Qt central, all operations relating to the view part here.
+ */
+class MainWindow : public QMainWindow {
+Q_OBJECT
+
+public:
+	MainWindow(int argc, char** argv, QWidget *parent = 0);
+	~MainWindow();
+
+	void ReadSettings(); // Load up qt program settings at startup
+	void WriteSettings(); // Save qt program settings when closing
+
+	void closeEvent(QCloseEvent *event); // Overloaded function
+	void showNoMasterMessage();
+
+public Q_SLOTS:
+	/******************************************
+	** Auto-connections (connectSlotsByName())
+	*******************************************/
+	void on_actionAbout_triggered();
+	void on_button_connect_clicked(bool check );
+	void on_checkbox_use_environment_stateChanged(int state);
+
+    /******************************************
+    ** Manual connections
+    *******************************************/
+    void updateLoggingView(); // no idea why this can't connect automatically
+
+  void updateLoggingView_sub(); //add
+  void pub_cmd(); //add
+
+private:
+	Ui::MainWindowDesign ui;
+	QNode qnode;
+};
+
+}  // namespace hmi
+
+#endif // hmi_MAIN_WINDOW_H

+ 83 - 0
src/hmi/include/hmi/qnode.hpp

@@ -0,0 +1,83 @@
+/**
+ * @file /include/hmi/qnode.hpp
+ *
+ * @brief Communications central!
+ *
+ * @date February 2011
+ **/
+/*****************************************************************************
+** Ifdefs
+*****************************************************************************/
+
+#ifndef hmi_QNODE_HPP_
+#define hmi_QNODE_HPP_
+
+/*****************************************************************************
+** Includes
+*****************************************************************************/
+
+// To workaround boost/qt4 problems that won't be bugfixed. Refer to
+//    https://bugreports.qt.io/browse/QTBUG-22829
+#ifndef Q_MOC_RUN
+#include <ros/ros.h>
+#endif
+#include <string>
+#include <QThread>
+#include <QStringListModel>
+#include <std_msgs/String.h> //add
+
+
+/*****************************************************************************
+** Namespaces
+*****************************************************************************/
+
+namespace hmi {
+
+/*****************************************************************************
+** Class
+*****************************************************************************/
+
+class QNode : public QThread {
+    Q_OBJECT
+public:
+	QNode(int argc, char** argv );
+	virtual ~QNode();
+	bool init();
+	bool init(const std::string &master_url, const std::string &host_url);
+	void run();
+
+	/*********************
+	** Logging
+	**********************/
+	enum LogLevel {
+	         Debug,
+	         Info,
+	         Warn,
+	         Error,
+	         Fatal
+	 };
+
+	QStringListModel* loggingModel() { return &logging_model; }
+	void log( const LogLevel &level, const std::string &msg);
+  QStringListModel* loggingModel_sub() { return &logging_model_sub; } //add
+  void log_sub( const LogLevel &level, const std::string &msg); //add
+  void Callback(const std_msgs::StringConstPtr &submsg); //add
+  void sent_cmd(); //add
+
+Q_SIGNALS:
+	void loggingUpdated();
+  void rosShutdown();
+  void loggingUpdated_sub(); //add
+
+private:
+	int init_argc;
+	char** init_argv;
+	ros::Publisher chatter_publisher;
+  QStringListModel logging_model;
+  ros::Subscriber chatter_subscriber; //add
+  QStringListModel logging_model_sub; //add
+};
+
+}  // namespace hmi
+
+#endif /* hmi_QNODE_HPP_ */

+ 26 - 0
src/hmi/mainpage.dox

@@ -0,0 +1,26 @@
+/**
+\mainpage
+\htmlinclude manifest.html
+
+\b hmi is ... 
+
+<!-- 
+Provide an overview of your package.
+-->
+
+
+\section codeapi Code API
+
+<!--
+Provide links to specific auto-generated API documentation within your
+package that is of particular interest to a reader. Doxygen will
+document pretty much every part of your code, so do your best here to
+point the reader to the actual API.
+
+If your codebase is fairly large or has different sets of APIs, you
+should use the doxygen 'group' tag to keep these APIs together. For
+example, the roscpp documentation has 'libros' group.
+-->
+
+
+*/

+ 25 - 0
src/hmi/package.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<package>
+  <name>hmi</name>
+  <version>0.1.0</version>
+  <description>
+
+     hmi
+
+  </description>
+  <maintainer email="madesheng@gmail.com">madesheng</maintainer>
+  <author>madesheng</author>
+  <license>BSD</license>
+  <!-- <url type="bugtracker">https://github.com/stonier/qt_ros/issues</url> -->
+  <!-- <url type="repository">https://github.com/stonier/qt_ros</url> -->
+
+  <buildtool_depend>catkin</buildtool_depend>
+  <build_depend>qt_build</build_depend>
+  <build_depend>roscpp</build_depend>
+  <build_depend>libqt4-dev</build_depend>
+  <run_depend>qt_build</run_depend>
+  <run_depend>roscpp</run_depend>
+  <run_depend>libqt4-dev</run_depend>
+
+ 
+</package>

+ 5 - 0
src/hmi/resources/images.qrc

@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/" >
+        <file>images/icon.png</file>
+    </qresource>
+</RCC>

BIN
src/hmi/resources/images/icon.png


+ 32 - 0
src/hmi/src/main.cpp

@@ -0,0 +1,32 @@
+/**
+ * @file /src/main.cpp
+ *
+ * @brief Qt based gui.
+ *
+ * @date November 2010
+ **/
+/*****************************************************************************
+** Includes
+*****************************************************************************/
+
+#include <QtGui>
+#include <QApplication>
+#include "../include/hmi/main_window.hpp"
+
+/*****************************************************************************
+** Main
+*****************************************************************************/
+
+int main(int argc, char **argv) {
+
+    /*********************
+    ** Qt
+    **********************/
+    QApplication app(argc, argv);
+    hmi::MainWindow w(argc,argv);
+    w.show();
+    app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+    int result = app.exec();
+
+	return result;
+}

+ 183 - 0
src/hmi/src/main_window.cpp

@@ -0,0 +1,183 @@
+/**
+ * @file /src/main_window.cpp
+ *
+ * @brief Implementation for the qt gui.
+ *
+ * @date February 2011
+ **/
+/*****************************************************************************
+** Includes
+*****************************************************************************/
+
+#include <QtGui>
+#include <QMessageBox>
+#include <iostream>
+#include "../include/hmi/main_window.hpp"
+
+/*****************************************************************************
+** Namespaces
+*****************************************************************************/
+
+namespace hmi {
+
+using namespace Qt;
+
+/*****************************************************************************
+** Implementation [MainWindow]
+*****************************************************************************/
+
+MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
+	: QMainWindow(parent)
+	, qnode(argc,argv)
+{
+    ui.setupUi(this); // Calling this incidentally connects all ui's triggers to on_...() callbacks in this class.
+    QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp is a global variable for the application
+
+    ReadSettings();
+    setWindowIcon(QIcon(":/images/icon.png"));
+    ui.tab_manager->setCurrentIndex(0); // ensure the first tab is showing - qt-designer should have this already hardwired, but often loses it (settings?).
+    QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close()));
+
+	/*********************
+	** Logging
+	**********************/
+    ui.view_logging->setModel(qnode.loggingModel());
+    QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView()));
+
+    /*********************
+    ** Auto Start
+    **********************/
+    if ( ui.checkbox_remember_settings->isChecked() ) {
+        on_button_connect_clicked(true);
+    }
+
+    ui.view_logging_sub->setModel(qnode.loggingModel_sub());//add
+    QObject::connect(&qnode,SIGNAL(loggingUpdated_sub()), this, SLOT(updateLoggingView_sub()));//add
+    QObject::connect(ui.sent_cmd,SIGNAL(clicked()),this,SLOT(pub_cmd())); //add
+}
+
+MainWindow::~MainWindow() {}
+
+/*****************************************************************************
+** Implementation [Slots]
+*****************************************************************************/
+
+void MainWindow::showNoMasterMessage() {
+	QMessageBox msgBox;
+	msgBox.setText("Couldn't find the ros master.");
+	msgBox.exec();
+    close();
+}
+
+/*
+ * These triggers whenever the button is clicked, regardless of whether it
+ * is already checked or not.
+ */
+
+void MainWindow::on_button_connect_clicked(bool check ) {
+	if ( ui.checkbox_use_environment->isChecked() ) {
+		if ( !qnode.init() ) {
+			showNoMasterMessage();
+		} else {
+			ui.button_connect->setEnabled(false);
+		}
+	} else {
+		if ( ! qnode.init(ui.line_edit_master->text().toStdString(),
+				   ui.line_edit_host->text().toStdString()) ) {
+			showNoMasterMessage();
+		} else {
+			ui.button_connect->setEnabled(false);
+			ui.line_edit_master->setReadOnly(true);
+			ui.line_edit_host->setReadOnly(true);
+			ui.line_edit_topic->setReadOnly(true);
+		}
+	}
+}
+
+
+void MainWindow::on_checkbox_use_environment_stateChanged(int state) {
+	bool enabled;
+	if ( state == 0 ) {
+		enabled = true;
+	} else {
+		enabled = false;
+	}
+	ui.line_edit_master->setEnabled(enabled);
+	ui.line_edit_host->setEnabled(enabled);
+	//ui.line_edit_topic->setEnabled(enabled);
+}
+
+/*****************************************************************************
+** Implemenation [Slots][manually connected]
+*****************************************************************************/
+
+/**
+ * This function is signalled by the underlying model. When the model changes,
+ * this will drop the cursor down to the last line in the QListview to ensure
+ * the user can always see the latest log message.
+ */
+void MainWindow::updateLoggingView() {
+        ui.view_logging->scrollToBottom();
+}
+
+/*****************************************************************************
+** Implementation [Menu]
+*****************************************************************************/
+
+void MainWindow::on_actionAbout_triggered() {
+    QMessageBox::about(this, tr("About ..."),tr("<h2>PACKAGE_NAME Test Program 0.10</h2><p>Copyright Yujin Robot</p><p>This package needs an about description.</p>"));
+}
+
+/*****************************************************************************
+** Implementation [Configuration]
+*****************************************************************************/
+
+void MainWindow::ReadSettings() {
+    QSettings settings("Qt-Ros Package", "hmi");
+    restoreGeometry(settings.value("geometry").toByteArray());
+    restoreState(settings.value("windowState").toByteArray());
+    QString master_url = settings.value("master_url",QString("http://localhost:11311/")).toString();
+    QString host_url = settings.value("host_url", QString("192.168.126.128")).toString();
+    //QString topic_name = settings.value("topic_name", QString("/chatter")).toString();
+    ui.line_edit_master->setText(master_url);
+    ui.line_edit_host->setText(host_url);
+    //ui.line_edit_topic->setText(topic_name);
+    bool remember = settings.value("remember_settings", false).toBool();
+    ui.checkbox_remember_settings->setChecked(remember);
+    bool checked = settings.value("use_environment_variables", false).toBool();
+    ui.checkbox_use_environment->setChecked(checked);
+    if ( checked ) {
+    	ui.line_edit_master->setEnabled(false);
+    	ui.line_edit_host->setEnabled(false);
+    	//ui.line_edit_topic->setEnabled(false);
+    }
+}
+
+void MainWindow::WriteSettings() {
+    QSettings settings("Qt-Ros Package", "hmi");
+    settings.setValue("master_url",ui.line_edit_master->text());
+    settings.setValue("host_url",ui.line_edit_host->text());
+    //settings.setValue("topic_name",ui.line_edit_topic->text());
+    settings.setValue("use_environment_variables",QVariant(ui.checkbox_use_environment->isChecked()));
+    settings.setValue("geometry", saveGeometry());
+    settings.setValue("windowState", saveState());
+    settings.setValue("remember_settings",QVariant(ui.checkbox_remember_settings->isChecked()));
+
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+	WriteSettings();
+	QMainWindow::closeEvent(event);
+}
+
+void MainWindow::updateLoggingView_sub(){// add
+  ui.view_logging_sub->scrollToBottom();
+}
+
+void MainWindow::pub_cmd(){// add
+  qnode.sent_cmd();
+}
+
+}  // namespace hmi
+

+ 186 - 0
src/hmi/src/qnode.cpp

@@ -0,0 +1,186 @@
+/**
+ * @file /src/qnode.cpp
+ *
+ * @brief Ros communication central!
+ *
+ * @date February 2011
+ **/
+
+/*****************************************************************************
+** Includes
+*****************************************************************************/
+
+#include <ros/ros.h>
+#include <ros/network.h>
+#include <string>
+#include <std_msgs/String.h>
+#include <sstream>
+#include "../include/hmi/qnode.hpp"
+
+/*****************************************************************************
+** Namespaces
+*****************************************************************************/
+
+namespace hmi {
+
+/*****************************************************************************
+** Implementation
+*****************************************************************************/
+
+QNode::QNode(int argc, char** argv ) :
+	init_argc(argc),
+	init_argv(argv)
+	{}
+
+QNode::~QNode() {
+    if(ros::isStarted()) {
+      ros::shutdown(); // explicitly needed since we use ros::start();
+      ros::waitForShutdown();
+    }
+	wait();
+}
+
+bool QNode::init() {
+	ros::init(init_argc,init_argv,"hmi");
+	if ( ! ros::master::check() ) {
+		return false;
+	}
+	ros::start(); // explicitly needed since our nodehandle is going out of scope.
+	ros::NodeHandle n;
+	// Add your ros communications here.
+	chatter_publisher = n.advertise<std_msgs::String>("chatter", 1000);
+  chatter_subscriber = n.subscribe("chatter",1000,&QNode::Callback,this);//加
+	start();
+	return true;
+}
+
+bool QNode::init(const std::string &master_url, const std::string &host_url) {
+	std::map<std::string,std::string> remappings;
+	remappings["__master"] = master_url;
+	remappings["__hostname"] = host_url;
+	ros::init(remappings,"hmi");
+	if ( ! ros::master::check() ) {
+		return false;
+	}
+	ros::start(); // explicitly needed since our nodehandle is going out of scope.
+	ros::NodeHandle n;
+	// Add your ros communications here.
+	chatter_publisher = n.advertise<std_msgs::String>("chatter", 1000);
+  chatter_subscriber = n.subscribe("chatter",1000,&QNode::Callback,this);//add
+
+	start();
+	return true;
+}
+
+void QNode::run() {
+	ros::Rate loop_rate(1);
+	int count = 0;
+	while ( ros::ok() ) {
+
+		std_msgs::String msg;
+		std::stringstream ss;
+		ss << "hello world " << count;
+		msg.data = ss.str();
+		chatter_publisher.publish(msg);
+		log(Info,std::string("I sent: ")+msg.data);
+		ros::spinOnce();
+		loop_rate.sleep();
+		++count;
+	}
+	std::cout << "Ros shutdown, proceeding to close the gui." << std::endl;
+	Q_EMIT rosShutdown(); // used to signal the gui for a shutdown (useful to roslaunch)
+}
+
+
+void QNode::log( const LogLevel &level, const std::string &msg) {
+	logging_model.insertRows(logging_model.rowCount(),1);
+	std::stringstream logging_model_msg;
+	switch ( level ) {
+		case(Debug) : {
+				ROS_DEBUG_STREAM(msg);
+				logging_model_msg << "[DEBUG] [" << ros::Time::now() << "]: " << msg;
+				break;
+		}
+		case(Info) : {
+				ROS_INFO_STREAM(msg);
+				logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
+				break;
+		}
+		case(Warn) : {
+				ROS_WARN_STREAM(msg);
+				logging_model_msg << "[INFO] [" << ros::Time::now() << "]: " << msg;
+				break;
+		}
+		case(Error) : {
+				ROS_ERROR_STREAM(msg);
+				logging_model_msg << "[ERROR] [" << ros::Time::now() << "]: " << msg;
+				break;
+		}
+		case(Fatal) : {
+				ROS_FATAL_STREAM(msg);
+				logging_model_msg << "[FATAL] [" << ros::Time::now() << "]: " << msg;
+				break;
+		}
+	}
+	QVariant new_row(QString(logging_model_msg.str().c_str()));
+	logging_model.setData(logging_model.index(logging_model.rowCount()-1),new_row);
+	Q_EMIT loggingUpdated(); // used to readjust the scrollbar
+}
+
+void QNode::log_sub( const LogLevel &level, const std::string &msg)
+{// add
+  logging_model_sub.insertRows(logging_model_sub.rowCount(),1);
+  std::stringstream logging_model_msg; //开关(级别)
+  {
+    switch ( level ) {
+    case(Debug):{
+      ROS_DEBUG_STREAM(msg);
+      logging_model_msg <<"[DEBUG] ["<< ros::Time::now()<<"]:"<< msg;
+      break;
+    }
+    case(Info):{
+      ROS_INFO_STREAM(msg);
+      logging_model_msg <<"[INFO] ["<< ros::Time::now()<<"]:"<< msg;
+      break;
+    }
+    case(Warn):{
+      ROS_WARN_STREAM(msg);
+      logging_model_msg <<"[INFO] ["<< ros::Time::now()<<"]:"<< msg;
+      break;
+    }
+    case(Error):{
+      ROS_ERROR_STREAM(msg);
+      logging_model_msg <<"[ERROR] ["<< ros::Time::now()<<"]:"<< msg;
+      break;
+    }
+    case(Fatal):{
+      ROS_FATAL_STREAM(msg);
+      logging_model_msg <<"[FATAL] ["<< ros::Time::now()<<"]:"<< msg;
+      break;
+    }
+    }
+  }
+
+  QVariant new_row(QString(logging_model_msg.str().c_str()));
+  logging_model_sub.setData(logging_model_sub.index(logging_model_sub.rowCount() - 1),new_row);
+  Q_EMIT loggingUpdated_sub(); //用于重新调整滚动条
+}
+  void QNode::Callback(const std_msgs::StringConstPtr&submsg)// add
+  {
+      log_sub(Info,std::string("Success sub:")+ submsg->data.c_str());
+  }
+
+  void QNode::sent_cmd()// add
+  {
+    if(ros::ok()){
+          std_msgs :: String msg;
+          std :: stringstream ss;
+          ss <<"clicked the button";
+          msg.data = ss.str();
+           chatter_publisher.publish(msg);
+           log(Info,std::string("I sent:")+ msg.data);
+           ros::spinOnce();
+    }
+  }
+
+}  // namespace hmi

+ 383 - 0
src/hmi/ui/main_window.ui

@@ -0,0 +1,383 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindowDesign</class>
+ <widget class="QMainWindow" name="MainWindowDesign">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>944</width>
+    <height>704</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>QRosApp</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../resources/images.qrc">
+    <normaloff>:/images/icon.png</normaloff>:/images/icon.png</iconset>
+  </property>
+  <property name="locale">
+   <locale language="English" country="Australia"/>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QHBoxLayout">
+    <item>
+     <widget class="QTabWidget" name="tab_manager">
+      <property name="minimumSize">
+       <size>
+        <width>100</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="locale">
+       <locale language="English" country="Australia"/>
+      </property>
+      <property name="currentIndex">
+       <number>0</number>
+      </property>
+      <widget class="QWidget" name="tab_status">
+       <attribute name="title">
+        <string>Ros Communications</string>
+       </attribute>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <widget class="QGroupBox" name="groupBox_12">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="title">
+           <string>Logging</string>
+          </property>
+          <layout class="QGridLayout" name="gridLayout_3">
+           <item row="1" column="0">
+            <widget class="QListView" name="view_logging"/>
+           </item>
+           <item row="0" column="0">
+            <widget class="QLabel" name="pub">
+             <property name="text">
+              <string>pub</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignCenter</set>
+             </property>
+            </widget>
+           </item>
+           <item row="3" column="0">
+            <widget class="QListView" name="view_logging_sub"/>
+           </item>
+           <item row="2" column="0">
+            <widget class="QLabel" name="sub">
+             <property name="text">
+              <string>sub</string>
+             </property>
+             <property name="alignment">
+              <set>Qt::AlignCenter</set>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>944</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menu_File">
+    <property name="title">
+     <string>&amp;App</string>
+    </property>
+    <addaction name="action_Preferences"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout"/>
+    <addaction name="actionAbout_Qt"/>
+    <addaction name="separator"/>
+    <addaction name="action_Quit"/>
+   </widget>
+   <addaction name="menu_File"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QDockWidget" name="dock_status">
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <property name="minimumSize">
+    <size>
+     <width>325</width>
+     <height>392</height>
+    </size>
+   </property>
+   <property name="allowedAreas">
+    <set>Qt::RightDockWidgetArea</set>
+   </property>
+   <property name="windowTitle">
+    <string>Command Panel</string>
+   </property>
+   <attribute name="dockWidgetArea">
+    <number>2</number>
+   </attribute>
+   <widget class="QWidget" name="dockWidgetContents_2">
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="QFrame" name="frame">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Raised</enum>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_3">
+        <item>
+         <widget class="QGroupBox" name="groupBox">
+          <property name="title">
+           <string>Ros Master</string>
+          </property>
+          <layout class="QGridLayout" name="gridLayout">
+           <item row="0" column="0">
+            <widget class="QLabel" name="label">
+             <property name="frameShape">
+              <enum>QFrame::StyledPanel</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string>Ros Master Url</string>
+             </property>
+            </widget>
+           </item>
+           <item row="1" column="0" colspan="2">
+            <widget class="QLineEdit" name="line_edit_master">
+             <property name="text">
+              <string>http://192.168.81.128:11311/</string>
+             </property>
+            </widget>
+           </item>
+           <item row="2" column="0">
+            <widget class="QLabel" name="label_2">
+             <property name="frameShape">
+              <enum>QFrame::StyledPanel</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string>Ros IP</string>
+             </property>
+            </widget>
+           </item>
+           <item row="3" column="0" colspan="2">
+            <widget class="QLineEdit" name="line_edit_host">
+             <property name="text">
+              <string>192.168.81.128</string>
+             </property>
+            </widget>
+           </item>
+           <item row="4" column="0">
+            <widget class="QLabel" name="label_3">
+             <property name="frameShape">
+              <enum>QFrame::StyledPanel</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string>Ros Hostname</string>
+             </property>
+            </widget>
+           </item>
+           <item row="5" column="0" colspan="2">
+            <widget class="QLineEdit" name="line_edit_topic">
+             <property name="enabled">
+              <bool>false</bool>
+             </property>
+             <property name="text">
+              <string>unused</string>
+             </property>
+            </widget>
+           </item>
+           <item row="6" column="0" colspan="2">
+            <widget class="QCheckBox" name="checkbox_use_environment">
+             <property name="layoutDirection">
+              <enum>Qt::RightToLeft</enum>
+             </property>
+             <property name="text">
+              <string>Use environment variables</string>
+             </property>
+            </widget>
+           </item>
+           <item row="7" column="0" colspan="2">
+            <widget class="QCheckBox" name="checkbox_remember_settings">
+             <property name="layoutDirection">
+              <enum>Qt::RightToLeft</enum>
+             </property>
+             <property name="text">
+              <string>Remember settings on startup</string>
+             </property>
+            </widget>
+           </item>
+           <item row="8" column="0">
+            <spacer name="horizontalSpacer">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>170</width>
+               <height>21</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item row="8" column="1">
+            <widget class="QPushButton" name="button_connect">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="toolTip">
+              <string>Set the target to the current joint trajectory state.</string>
+             </property>
+             <property name="statusTip">
+              <string>Clear all waypoints and set the target to the current joint trajectory state.</string>
+             </property>
+             <property name="text">
+              <string>Connect</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="sent_cmd">
+          <property name="text">
+           <string>sent_cmd</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer_3">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>233</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="quit_button">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Quit</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </widget>
+  </widget>
+  <action name="action_Quit">
+   <property name="text">
+    <string>&amp;Quit</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Q</string>
+   </property>
+   <property name="shortcutContext">
+    <enum>Qt::ApplicationShortcut</enum>
+   </property>
+  </action>
+  <action name="action_Preferences">
+   <property name="text">
+    <string>&amp;Preferences</string>
+   </property>
+  </action>
+  <action name="actionAbout">
+   <property name="text">
+    <string>&amp;About</string>
+   </property>
+  </action>
+  <action name="actionAbout_Qt">
+   <property name="text">
+    <string>About &amp;Qt</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="../resources/images.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>action_Quit</sender>
+   <signal>triggered()</signal>
+   <receiver>MainWindowDesign</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>399</x>
+     <y>299</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>quit_button</sender>
+   <signal>clicked()</signal>
+   <receiver>MainWindowDesign</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>859</x>
+     <y>552</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>469</x>
+     <y>299</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>