智能机器人(55):数据融合

6. 数据融合 – EKF – robot_pose_ekf

此保融合odom/imu/ov等数据获得更精确的位姿信息。
并不要求各路传感器数据连续提供,某路例如imu可以的数据可以中断,不影响算法进行。
REF:
https://answers.ros.org/question/235228/how-is-the-orientation-of-frame-odom-initialized/

Subs:
* odom (nav_msgs/Odometry)
position and orientation of robot in ground plane
* imu_data (sensor_msgs/Imu)
RPY angles of robot base frame relative to a world reference frame.
R和P为绝对角度因为有重力 而Y为相对角度。
* vo (nav_msgs/Odometry)
the full position and orientation of robot
如果某传感器提供3D数据而只用到2D部分,则对不用部分赋值较大的协方差即可。

Pubs:
* robot_pose_ekf/odom_combined (geometry_msgs/PoseWithCovarianceStamped)
The output of the filter (the estimated 3D robot pose).

TFs:
odom_combined -> base_footprint
发布一个名为odom_combined的新的坐标系,
并发布一个 odom_combined->base_footprint的TF变换。

Launchs:

不确定度方面的几个实践问题

6.1 协方差这个参数的来源问题

ERROR: Covariance specified for measurement on topic xxx is zero
A:
Each measurement that is processed by the robot pose ekf ,needs to have a covariance associated with it.
The diagonal elements of the covariance matrix , can not be zero.
When one of the diagonal elements is zero, this error is shown.
Messages with an invalid covariance, will not be used to update the filter.
So, you should reating the covariance matrices for individual sensors:
*1. For IMU and Odometry, the covariance matrix can be formed from the datasheet.
*2. For Visual Odometry, covariance matrix may be obtained from the measurement equation that relates the measured variables to the pose coordinates.

6.2 IMU的协方差

if (imu_covariance_(1,1) == 0.0){
SymmetricMatrix measNoiseImu_Cov(3); measNoiseImu_Cov = 0;
measNoiseImu_Cov(1,1) = pow(0.00017,2); // = 0.01 degrees / sec
measNoiseImu_Cov(2,2) = pow(0.00017,2); // = 0.01 degrees / sec
measNoiseImu_Cov(3,3) = pow(0.00017,2); // = 0.01 degrees / sec
imu_covariance_ = measNoiseImu_Cov;
}

for example 0.00017 means 0101deg/sec, this is so good imu, increase them if you get poor odometry.
For optimal values, perform an odometry calibration alogirthm such as UMBMark.

IMU is:
self.imu_msg.orientation_covariance = [-1, 0, 0,
0, -1, 0,
0, 0, -1 ] #sensor doesn’t have orientation

源代码是这样检查的
$ vi robot_pose_ekf/src/odom_estimation.cpp
void OdomEstimation::addMeasurement(const StampedTransform& meas, const MatrixWrapper::SymmetricMatrix& covar)
{
// check covariance
for (unsigned int i=0; i<covar.rows(); i++){=”” if=”” (covar(i+1,i+1)=”=” 0){=”” ros_error(“covariance=”” specified=”” for=”” measurement=”” on=”” topic=”” %s=”” is=”” zero”,=”” meas.child_frame_id_.c_str());=”” return;=”” }=”” add=”” measurements=”” addmeasurement(meas);=”” (meas.child_frame_id_=”=” “wheelodom”)=”” odom_covariance_=”covar;” else=”” “imu”)=”” imu_covariance_=”covar;” “vo”)=”” vo_covariance_=”covar;” ros_error(“adding=”” a=”” an=”” unknown=”” sensor=”” %s”,=”” };=”” 6.3=”” odom的协方差=”” the=”” odometry=”” will=”” be=”” updated,=”” but=”” covariance=”” always=”” published=”” as=”” 0.=”” controller=”” don’t=”” include=”” information.=”” you=”” need=”” to=”” have=”” value=”” included=”” in=”” information=”” some=”” reason,=”” can=”” create=”” your=”” own=”” based=”” rosaria=”” and=”” value.=”” odom=”” 6×6=”” matrix,=”” because=”” 6=”” dof,=”” position=”” (x,=”” y,=”” z)=”” orientation=”” so=”” float[36]=”” matrix.=”” diagonal=”” terms=”” are=”” trust=”” each=”” dof.=”” estimate=”” or=”” algorithm=”” accuracy=”” with=”” experiment.=”” see=”” data=”” good=”” 1cm=”” translation=”” 0.1=”” radian=”” rotation=”” use=”” this=”” matrix:=”” [0.01=”” 0.0=”” 0.0,=”” 0.01=”” 0.1]=”” no=”” one=”” dof=”” put=”” huge=”” example=”” segway_rmp:=”” this-=””>odom_msg.pose.covariance[0] = 0.00001;
this->odom_msg.pose.covariance[7] = 0.00001;
this->odom_msg.pose.covariance[14] = 1000000000000.0;
this->odom_msg.pose.covariance[21] = 1000000000000.0;
this->odom_msg.pose.covariance[28] = 1000000000000.0;
this->odom_msg.pose.covariance[35] = 0.001;
above means, position z is not sure, ori of x and y is no tsure.</covar.rows();>

covariance
nav_msgs::Odometry odom;
odom.header.stamp = current_time;
odom.header.frame_id = “odom”;
//set the position
odom.pose.pose.position.x = od->position.positionx;
odom.pose.pose.position.y = od->position.positiony;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = odom_quat;
//set the velocity
odom.child_frame_id = “base_link”;
odom.twist.twist.linear.x = od->speed.speedx;
odom.twist.twist.linear.y = od->speed.speedy;
odom.twist.twist.angular.z = od->speed.speedr;

// set stddev
odom.pose.covariance[0] = pos_x_stddev;
odom.pose.covariance[7] = pos_y_stddev;
odom.pose.covariance[14] = pos_z_stddev;
odom.pose.covariance[21] = rot_x_stddev;
odom.pose.covariance[28] = rot_y_stddev;
odom.pose.covariance[35] = rot_z_stddev;

double pos_x_stddev
double pos_x_stddev
double pos_z_stddev
double rot_x_stddev
double rot_y_stddev
double rot_z_stddev

ros::NodeHandle private_node_handle(“~”);
private_node_handle.param(“pos_x_stddev”, pos_x_stddev, 0.11);
private_node_handle.param(“pos_y_stddev”, pos_y_stddev, 0.12);
private_node_handle.param(“pos_z_stddev”, pos_z_stddev, 1000000000000.0);
private_node_handle.param(“rot_x_stddev”, rot_x_stddev, 1000000000000.0);
private_node_handle.param(“rot_y_stddev”, rot_y_stddev, 1000000000000.0);
private_node_handle.param(“ros_z_stddev”, ros_z_stddev, 0.15);

REF:
Covariance matrices with a practical example

智能机器人(53):定位调试

Q:
性能的平衡
A:
各sensor发布topic, amcl和robot_pose_ekf模块发布tf, 这些frequency需要和cpu性能进行trade-off, 搞折衷做平衡。

top查看系统性能,’1′ 查看多核的具体cpu, 节后’b’ ‘x’ ‘y’等指令, 并要关注average load指标:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14706 ubuntu 20 0 296736 212296 5564 R 71.5 11.0 1:51.56 amcl
14245 ubuntu 20 0 79408 5592 4792 S 47.0 0.3 2:30.72 laser_node
14250 ubuntu 20 0 105876 5348 4616 S 3.0 0.3 0:09.73 lpms_imu_node
23344 ubuntu 20 0 91032 6960 6140 S 4.0 0.4 0:00.77 robot_pose_ekf
这个就好了。

如果配置不切实际, 类似arm板配置20Hz的transform frequency, 则资源受限出错:
$ roswtf
— —
ERROR: receiving transform from [/amcl] that differed from ROS time by 2.96s
这个时间,设置的越快会,大的越夸张。

此外还要关注内存情况:
$ free -m
— —

也要关注磁盘介质:
$ df -h

$ du -h –max-depth=1

Q:
amcl的node会die掉

$ rosnode ping amcl
— —
ERROR: connection refused to [http://192.168.0.40:38282/]

查看 ~/.ros/log/latest/… …/amcl-1.log:
amcl: /tmp/buildd/ros-indigo-amcl-1.12.4-0trusty-20150604-0435/src/amcl/pf/pf_kdtree.c:378: pf_kdtree_cluster: Assertion `node == pf_kdtree_find_node(self, self->root, node->key)’ failed.
Aborted (core dumped)

A:
原因是激光雷达被不恰当遮挡, pf程序没有足够健壮导致的。

Q:
ERROR: receiving transform from [/robot_state_publisher] that differed from ROS time by 12.34s
A:
如果是多机系统:
可能是没有进行时间同步。
$ install chrony
$ sudo ntpdate 192.168.1.1 <--- 如果是单机系统系统, 而且时间相差很大: 可能是/use_sime_time要为false。 如果是单机系统系统, 时间相差细微: 第一感就是降低某些重载模块的频率, 50Hz ---> 20Hz—>5Hz。
或者换个PC。

Q:
WARNING The following node subscriptions are unconnected:
* /amcl:
* /tf_static
* /robot_pose_ekf:
* /tf_static
A:
roswtf发出的警告,说amcl节点订阅了tf_static这个topic,但是却没有其他节点发布内容的topic。
这个警告正是所期望看到的:
因为我们没有使用tf_static来发布模型urdf,所以可以忽略这些警告。

智能机器人(51):建图和定位

3. 建图功能 – gmapping

$ sudo apt-get install ros-indigo-gmapping
$ rosrun gmapping slam_gmapping scan:=scan

gmapping实现基于激光的SLAM, in fact usinf OpenSlam的Gmapping。
make a 名为slam_gmapping的node -> 创建2D的occupancy grid map。

Subs:
* scan (sensor_msgs/LaserScan)

Pubs:
* map (nav_msgs/OccupancyGrid)
Get the map data from this topic, which is latched, and updated periodically
Services:
* dynamic_map (nav_msgs/GetMap)
Call this service to get the map data

TF required:
* odom -> base_link
usually provided by the odometry system, e.g., the driver for the mobile base
* base_link -> laser_link (base_laser)
usually broadcast periodically by robot_state_publisher, or from a tf static_transform_publisher.

TF provided:
* map -> odom
the current estimate of the robot’s pose in the map frame
既然是建图,肯定给出了odom在map中的位置,也就是此处的map->odom的tf变换。

4. 地图服务器 – map_server

$ sudo apt-get install ros-indigo-map-server

map_server包提供一个服务map_server和一个应用map_saver:
* map_server , a ROS Node, which offers map data as a ROS Service.
* map_saver , a command-line utility, which allows dynamically generated maps to be saved to file.
前者map_server提供地图服务,例如导航时。
后者map_saver用于保存地图,例如建图时。

4.1 在导航或者定位场景,加载地图,可以在c或python的node。
$ roslaunch funbot r_mapserver.launch
$ vi r_mapserver.launch
$ rosrun map_server map_server /home/funbot/map/map2017.yaml

Pubs:
* map (nav_msgs/OccupancyGrid)
you can receive the map via this latched topic.

Services:
* static_map (nav_msgs/GetMap)
Retrieve the map via this service.

4.2 在mapping场景,可以随时保存地图。
这个通过command-line或者在code里面system()。
$ rosrun map_server map_saver -f /home/funstep/map/map2017 y
$ rosrun map_server map_saver -f _map_file:=/home/funstep/map/map.yaml x

Subs:
* map (nav_msgs/OccupancyGrid)
Map will be retrieved via this latched topic.

5. 定位功能 – amcl

$ sudo apt-get install ros-indigo-amcl
rosrun amcl amcl scan:=scan

amcl是2D的基于概率的定位的一个包。

Subs:
* map (nav_msgs/OccupancyGrid)
If amcl parameter “use_map_topic=true” ,then AMCL subscribes this topic to retrieve map,
otherwise using service call.
* scan (sensor_msgs/LaserScan)
Laser scans
* initialpose (geometry_msgs/PoseWithCovarianceStamped)
Mean and covariance with which to (re-)initialize the particle filter

Pubs:
* amcl_pose (geometry_msgs/PoseWithCovarianceStamped)
Robot’s estimated pose in the map with covariance.

TF required:
* tf (tf/tfMessage)
提供odom -> base_link

TF supported:
* tf (tf/tfMessage)
发布map -> odom(间接的机器人在地图的位置)
注意:
不能有另外的map->odom在同时发布,例如在跑mapping.
实际上,mapping和amcl同时跑的需求不存在。
如果有,也使用hector_slam.

Paras:
三种类型的参数用来配置AMCL节点:filter整体的,laser模型的,odom模型。例如
Odometry model parameters:
* ~tf_broadcast (bool, default: true)
Set to false to prevent amcl from publishing the transform map -> odom.
可以关闭上述map->odom的tf。

注意:
*1. initialpose这个topic的存在,主要方便于在amcl运行时对姿态进行复位。
*2. initial_pose这个topic上如果发布赋值,实际就是初始化一个高斯分布。这个分布的协方差越大,说明粒子在地图上撒开的面积越大,越难定位。
*3. 不 对initial_pose直接赋值,而通过操作amcl的parameter参数,可以同样效果。
或者通过呼叫global_localization service,也可以达到把颗粒均匀洒在地图的目的。
4. 如果不赋值,则位置是默认地图的(0.0.0,0,0,0),但是默认的协方差很小,也就是说默认为确认给出的位置信息相当的准确。这个需要注意。

智能机器人(49):Qt界面设计

1. qtcreator环境
2. qtcreator开发ros项目
3. qtcreator的ros插件
4. Qt界面设计之C++
5. Qt界面设计之Python
6. Python的界面设计
7. Qt ROS GUI练习

界面库很多: Tk低效,wxWidgets复杂,GTK使用少,Qt is okay。目前Qt的版本有Qt4和Qt5。
开发环境很多:Eclipse is popular but QtCreator benefits good。目前qtcreator的版本有5.6,5.2,4.8。

  • 1. qtcreator环境

更新ubuntu系统资源
$ sudo apt-get update
//配置c++编译环境
//$sudo apt-get install build-essential
安装
软件中心搜索qtcreator,安装
or,
$ sudo apt-get install qtcreator

1.1 qtcreator的多版本
如果有多个版本(in fact it is! ),现确认使用的哪一个:
$ which qtcreator
—/usr/bin/qtcreator
再确认当前使用版本:
$ qmake -version
—QMake version 3.0
—Using Qt version 5.2.1 in /usr/lib/x86_64-linux-gnu
$ qtchooser -list-versions
—4
—5
—default
—qt4-x86_64-linux-gnu
—qt4
—qt5-x86_64-linux-gnu
—qt5

1.3 注意快捷方式启动和终端启动的环境变量
As QtCreator supports opening CMake projects out of the box,it does not require a setup procedure if started from a terminal.
Note: this is absolutely crucial, because otherwise the environment will not be set correctly and functionality related to rosbuild or catkin will fail when running cmake. In order to be able to work with ROS code, QtCreator needs to be able to source the environment (your .bashrc),

SO:
1.3.1 You can either launch it from a terminal,
$ qt-creator
or,
1.3.2. customize your qtcreator.desktop file:
You should not try to generate this file yourself, but rather modify the file that was created when you installed QtCreator.
Normally in Ubuntu this file in /usr/share/applications(in fact it is! ), or, maybe in ~/.local/share/applications if installed it only for your user.

$ cat qtcreator.desktop
[Desktop Entry]
Exec=bash -i -c qtcreator %F
Icon=qtcreator
Type=Application
Terminal=false
Name=Qt Creator
GenericName=Integrated Development Environment
MimeType=text/x-c++src;text/x-c++hdr;text/x-xsrc;application/x-designer;application/vnd.nokia.qt.qmakeprofile;application/vnd.nokia.xml.qt.resource;
Categories=Qt;Development;IDE;
InitialPreference=9

In Ubuntu 13.04 and later, the third line must read:
Icon=QtProject-qtcreator

Use this standard QtCreator desktop file, and in the Exec line, add bash -i -c.
This will run your QtCreator in a shell which should source all required setup.bash files of your ros installation and workspace.

# cp /usr/share/applications/qtcreator.desktop ~

First copy the standard qtcreator.desktop file, Then edit it and change the Exec line into: Exec=bash -i -c qtcreator %F
Note that instead of starting QtCreator from a terminal, you can use the following desktop file and use it in your launcher:

Finally, remove the QtCreator icon from the launcher (if present) by right clicking it and selecting “Unlock from launcher”; drag and drop the qtcreator.desktop file you just created to the launcher.
I chose the first one:  start from terminal.

By not providing “Findcatkin.cmake” inCMAKE_MODULE_PATH this project has asked CMake to find a packageconfiguration file provided by “catkin”, but CMake did not find one.打开terminal,输入下面的命令:
$ vi /home/xxxx/.local/share/applications/Qt-Creator-ros.desktop
修改Exec变量一行,在中间添加bash-i -c即改为Exec=bash-i -c/home/leon/qtc_plugins/qt-creator-build/bin/qtcreator,注意修改路径,保存并退出。添加bash-i -c是为了在通过快捷方式启动QtCreator的同时加载ROS环境变量

DO NOT user sudo qtcreator, for these will generated build folder in custome location and configfile in ~/.config with root owner and privage, this will forbidde other user to manupulate.

  • 2. qtcreator开发ros项目

2.1. rosbuild方式:
$ echo $ROS_PACKAGE_PATH
$ add ROS_PACKAGE_PATH=/YoutPackage:${ROS_PACKAGE_PATH}
$ cd ~/ros/boter
$ rosmake boter
NO USED NOW.

2.2. catkin_make方式:
all packages managed by ~/catkin_ws/src/CMakeListst.txt

2.2.1 Use “Open File or Project” and select the top level CMakeLists.txt of the catkin workspace (~/catkin_ws/src/CMakeListst.txt) to Open a catkin code as a project
如果QT错:
— Cannot create file /opt/ros/indigo/share/catkin/cmake/toplevel.cmake.user: Permission denied
This has started to fail because the main CMakeLists is a symlink to a non writtable location. The solution is to make a copy to toplevel.cmake instead of using a symlink. And if you want the project to be named something else than “Project” then add a line at the top with “project(MyProjectName)”
解决的办法是:
$ cd到要打开的工程目录下,
$ ls -l 查看哪个文件与你的CMakeList是符号链接,
我的:
CMakeLists.txt -> /opt/ros/indigo/share/catkin/cmake/toplevel.cmake
然后,要做的是把链接文件替代你的CMakeList文件:
$ mv CMakeLists.txt CMakeLists.txt.bak
$ cp /opt/ros/indigo/share/catkin/cmake/toplevel.cmake CMakeLists.txt

To be able to modify all files in workspace, add those lines in src/CMakeLists.txt” :
#Add custom (non compiling) targets so launch scripts and python files show up in QT Creator’s project view.
file(GLOB_RECURSE EXTRA_FILES */*)
add_custom_target(${PROJECT_NAME}_OTHER_FILES ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} SOURCES ${EXTRA_FILES})
You may specify the correct catkin devel and install spaces at Projects->Build Settings by providing the following CMake arguments: -DCATKIN_DEVEL_PREFIX=../devel -DCMAKE_INSTALL_PREFIX=../install

2.2.2 Select the catkin build folder as the build directory and ‘Run CMake’
Set the build location to the build space of the catking workspace ( maybe ~/catkin_ws/build).
(in order to enable debugging, add following line into arguments edit box: -DCMAKE_BUILD_TYPE=Debug).

2.2.3 Run cmake with no arguments
It should start parsing the packages in the project (as with catkin_make) ,
and the list of packages should appear in the project view.
Use Ctrl+B to build.
goes okay!

2.3. catkin_make方式:
single packahe at top level .

With the new catkin_tools, there is no longer a top level make file for the whole workspace.
Instead, open each package as an individual project in QtCreator now is available.

2.3.1 first click project, Make sure the build directory folder is set to: ws/build/your_package instead of ws/build,
for example mine is : /home/dehaou1404/catkin_ws/build/zPack01

2.3.2 执行CMake”,如果需要Debug填入参数-DCMAKE_BUILD_TYPE=Debug,如果不需要Debug直接运行,填入参数-DCMAKE_BUILD_TYPE=Release

2.3.3 How to properly add include directories with CMake? for example, project have 2 files:
include/my_package/my_code.h
src/my_code.cpp
these lines to CMakeLists.txt:
add_executable(my_node_executable
include/your_package/your_code.h
src/your_code.cpp
)

If u want to create a library to be used by other node, add like this:
add_library(my_node_executable
include/my_package/my_code.h
src/my_code.cpp
)

2.3.4 if necessory, 在“项目”的“运行”页可以修改一些环境变量, or change CMakeLists.txt:
set(A1_PATH /usr/local) #设置一个变量A1_PATH
SET(CMAKE_MODULE_PATH ${A1_PATH}/lib/cmake )#设置CMAKE_MODULE_PATH的path
SET(ARUCO_INCLUDE_DIRS ${A1_PATH}/include/a1 )#设置aruco的库的头文件
set(ROS_BUILD_TYPE Debug) #调试作用
include_directories(${B1_INCLUDE_DIRS} ${B2_INCLUDE_DIRS} ${B3_DIRS}) #包含三个库的文件
for examples:
**Add the directory to be included:
include_directories(${YOUR_DIRECTORY})
**Add the header files to the list of your source files for the current target, for instance:
set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_executable(node_executable ${SOURCES})
**How to use those header files for several targets
set(HEADER_FILES ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h)
add_library(mylib libsrc.cpp ${HEADER_FILES})
add_executable(myexec execfile.cpp ${HEADER_FILES})
–As an example, if your project’s sources are in src, and you need headers from include, you could do it like this:
include_directories(include_dir)
add_executable(MyExec
src/main.c
src/other_source.c
include/header1.h
include/header2.h
)

2.3.5 如果想重新导入这个项目需要删除catkin_ws/src/zPack01的CMakeLists.txt.user文件,然后按照上述操作重新导入
NOTE:
Before opening a package with QtCreator, make sure to build the package once with catkin build.

If your build artifacts (binaries, libraries, …) end up in the wrong directory, maybe because you built the package first with QtCreator.
You can check whether you have this problem by simple doing a rosrun of your package’s node, change code, recompile with QtCreator and do a rosrun again if you don’t see your changes in the executable’s behavior, it is probably installed into the wrong directory.

To resolve this issue, just clean the package (catkin clean for linked layout, for newer catkins, remove the build/ folder) and rebuild it with catkin build.

With QtCreator of version 4 and higher, you can (and actually have to) configure your compiler etc. in a Kit.
Go to Tools — Options — Build & Run — Kits. In the Default kit (or create a new kit for ros)
1) select the compiler you want to use in catkin
2) select CodeBlocks — Unix Makfiles
3) change the CMake Configuration to only contain QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} (i.e. remove the define for CMAKE_CXX_COMPILER)

In your workspace, execute
$ catkin config –cmake-args -DCMAKE_CXX_COMPILER:STRING=/usr/bin/g++ —
where you substitute /usr/bin/g++ with the compiler you actually want to use (and which is the same that you selected in the kit above).
See this discussion about this issue.

You can configure some default paths in QtCreator:
1) The default build path (what you normally have to set manually once you open a new project):
In Tools — Options — Build & Run — General,  the Default build directory is:
../build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}
change to:
~/catkin_ws/build/%{CurrentProject:Name}
2) The path in which to look for projects (i.e. where to start the search when you want to open a new project):
Tools — Options — Build & Run — General — Projects directory
set Directory to /home//workspace/src (or wherever your workspace is).

2.4 –Troubleshooting–
When running cmake in QtCreator (when you open the package), check the output for error messages — they provide a clue on what is going wrong.
To remove cached/stored information for a project, remove the CMakeLists.txt.user (possibly with some trailing numbers) in your project and re-open the project.
If that does not solve your problem, repeat remove CMakeLists.txt.user and additionally remove (or rather rename) the QtCreator configuration in ~/.config/QtProject and ~/.local/share/data/QtProject/qtcreator and try again.

  • 3. qtcreator的ros插件

qdude是ROS为qtcreator提供的插件。
Which can speed app development with quickstart templates via roscreate-qt-pkg.

To use the plugin which can generate a qt-ros application package with ‘catkin_create_qt_pkg’, install package:
$ sudo apt-get install ros-indigo-qt-ros

This package can generate a sample template: Currently the creational script generates only one template app, though this may be expanded in future. Features include:
*a ros master chooser
*separate ui and ros node classes
*ros node class has connections for gui logging and a spinner

to generate:
$ cd ~/catkin_ws/src
$ catkin_create_qt_pkg qdude
$ cd ~/catkin_ws
$ catkin_make –force-cmake
$ rosrun qdude qdude
Simply catkin_make in place (native compile) to compile.

We’ve temporarily dropped cross compiling support with the mingw cross compiler on groovy (lack of time and we’re not using so much anymore) but is possible.

Once compiled and running, you can:
*Affect gui changes in main_window.ui with qt designer
*Modify qt code in main_window.hpp/main_window.cpp
*Do ros topics and services in qnode.hpp/qnode.cpp.
For more advanced qt options (e.g. specifying qt components), see the notes in qt_build for a more detailed explanation now how to use the cmake api to configure your package.

  • 4. Qt的C++界面设计

这个是最标准的:
File–New File or project…
select QT Widget Application
click Choose.
Ctrl-B to build,
Ctrl-r ro run.
ok -> close.

QTwidgets-based-project一共4个文件,入口文件main.cpp +mainwindow.ui文件 + mainwindow.h和mainwindow.cpp后台源文件
在main.cpp -> main函数中 直接调用MainWindow类的show()方法显示主界面
MainWindow类中有一个成员变量是ui,其类型是Ui::MainWindow,通过这个ui成员去访问操作界面控件

  • 5. Qt的Python界面设计

这个需要先用qtcreator设计出界面,然后用pyc转化为python代码。在Ubuntu 14.04 Python默认安装了Python2.7和Python3.4,Qt默认安装了4.8和5.2,sip默认安装时是4.15,PyQt默认安装的是pyqt4。
$ python -V
—Python 2.7.6
$ python3 -V
—Python 3.4.3
$ sip -V
—4.15.5
—python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
>>>import sip
>>>import PyQt4
导入都是OK.

5.1、 做一个Hello项目
5.1.1、 绘制界面,$ qtcreater创建一个project,选择kit为Qt4。
5.1.2、添加按钮,在ui的designer添加一个pushButton,
5.1.3、为clicked这个single添加一个slot例如CbOnClicked(),保存,ok。
5.1.4、界面转换成Python代码
$ pyuic4 -x ./main.ui -o ./main.py
5.1.5、 添加回调函数
添加:
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8(“clicked()”)), self.CbOnClicked)
添加:
def CbOnClicked(self):
print “Hello…dehao…”
5.1.6、测试
$ python main.py
这样,窗口弹出,button响应。

  • 6. Python的界面设计

当然,Python界面设计最好使用wxGlade。
wxGlade 使用的GUI框架是 wxPython

  • 7. Qt ROS GUI练习

首先基于插件方式产生一个ros的qt项目,然后在此基础上修改:
1) 在Qt Designer里面修改xxx.ui界面
2) 在main_window.hpp/main_window.cpp修改代码
3) 在qnode.hpp/qnode.cpp修改ROS功能

7.1 添加Widget按钮,自动链接slot槽函数
Drag a “Push Button” into the ui and replace its text name and object name as “Test” and “button_test”
Open “main_window.hpp” and “main_window.cpp” and create two new functions associated with this button test by imitating from the “button_connect” working.
void on_button_test_clicked(bool check); <— in hpp void MainWindow::on_button_test_clicked(bool check ) { <— in cpp showTestButtonMessage(); } 7.2 添加Widget按钮,人工链接slot槽函数 We notice the “Quit” button is explicitly connected with a callback function “close()” in Signals & Slots Editor in ui mode. Also, in “main_window.cpp”, there exists some lines seeming to link the widgets and callback functions together, like: QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp a global variable for the application QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close())); QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView())); SO: 1) Create two new buttons, “Left” and “Right”, to output something different with each other in the logging window 2) Create two callback functions to be called by the two buttons in cpp file: QObject::connect(ui.left, SIGNAL(clicked()), this, SLOT(moveLeft())); QObject::connect(ui.right, SIGNAL(clicked()), this, SLOT(moveRight())); void MainWindow::moveLeft() { … } void MainWindow::moveRight() { … } So basically Qt is using a signal-slot mechanism, which is a central feature of Qt and probably the part that differs most from the features provided by other frameworks. You can goto http://doc.qt.io/qt-4.8/signalsandslots.html 7.3 添加topic的发布和订阅 Populate the qnode.cpp with ROS topics and we can easily build a number of Qt GUI applications in ROS. Here is an example. By filling in QNode::rosrun() with publisher and subscriber, we can use two nodes to communicate with each other and show everything in logging windows. Create two separated packagas named “my_gui_publisher” and “my_gui_subsriber”. In my_gui_publisher/src/qnode.cpp chatter_publisher = n.advertise(“chatter”, 1000);
In my_gui_subscriber/src/qnode.cpp
chatter_subscriber = n.subscribe(“chatter”, 1000, &QNode::myCallback, this);

Conclusion : we start C++ GUI with Qt in ROS. REF: http://qkxue.net/info/205412/How-build-GUI-ROS-with

7.4 完整示例
here simple controller built with ROS and Qt5 libraries, REF: https://github.com/allenh1/ros-qt-controller