在已有项目的基础上修改,在Qt中构建ros workspace需要插件,或者下载Qtreator Ros,参考博客:ROS Qt5 librviz人机交互界面开发一(配置QT环境)-CSDN博客
qtcreator ros可以直接在ubuntu software下载
按参考博客打开项目,在design中添加按键
这里我添加了“启动仿真”和“关闭仿真”按键,分别实现启动.launch文件和关闭;另外修改了connect按键,改为发送目标位姿到move_base_simple/goal,用于导航
槽函数如下:
/*****************************************************************************
** 添加仿真
*****************************************************************************/
void startROSNodes() {
system("./temp_ws/launch_script.sh");
}
void MainWindow::on_pushButton_clicked()
{
std::thread rosThread(startROSNodes);
rosThread.detach(); // 启动节点并分离线程,使其在后台运行
}
void MainWindow::on_pushButton_2_clicked()
{
system("killall -SIGINT roslaunch");
}
当你启动了 ROS 节点(比如 rviz 和 Gazebo),它们可能会占用一定的系统资源。如果这些节点占用了大量 CPU 或内存,可能会导致 UI 界面的响应变慢或失去响应。
这可能是因为你的 ROS 节点正在运行,而主线程(UI 界面)被这些节点占用导致无法及时响应用户操作。一种方法是在一个单独的线程中启动 ROS 节点,以避免阻塞主线程。
你可以尝试在启动 ROS 节点的时候使用异步或多线程的方式,确保它们不会阻塞 UI 界面。这可以使用 C++ 中的线程库来实现,比如 std::thread
。
其中
system("./temp_ws/launch_script.sh");
是启动launch文件的主要代码,temp_ws为该项目的文件名
通过 system()
函数来执行一系列命令,包括改变目录、加载环境变量、并启动 ROS launch 文件。然而,使用 system()
函数连续执行这些命令时,可能会遇到一些问题。
首先,system()
函数在一个单独的 shell 进程中执行每个命令,每次调用 system()
都会启动一个新的 shell。这意味着在一个命令执行完毕后,它所做的更改(如改变目录、加载环境变量)通常不会影响到下一个命令,因为每个命令都在自己的临时 shell 中执行。
解决这个问题的一个方法是将所有命令放入一个脚本文件中,然后在 C++ 中执行该脚本文件。例如,将你的命令序列放入一个名为 launch_script.sh
的脚本文件中:
#!/bin/bash
cd hit_navigation/
source ./devel/setup.bash
roslaunch trajectory_plan sim_qt.launch
我将该脚本文件放在temp_ws下,/ temp_ws 可以替换为你存放 launch_script.sh
脚本文件的实际路径。里面的命令可根据自己的情况来修改。
添加访问权限:
xxx@xxx:~/temp_ws$ chmod +x launch_script.sh
system("killall -SIGINT roslaunch");
上面的代码用来杀死roslaunch,通过 system()
函数来发送中断信号给名为 roslaunch
的进程,以终止正在运行的 ROS 节点。在终端中使用 killall -SIGINT roslaunch
命令通常可以有效地关闭这些节点。
但需要注意的是,在 C++ 中使用 system()
函数执行这个命令时,可能会遇到一些问题。首先,使用 system()
函数调用这个命令会在一个单独的 shell 进程中执行该命令,而不是直接在你的程序进程中运行。因此,可能会遇到权限问题或者无法成功发送信号的情况。
另外,发送信号也不一定能够确保节点完全安全地关闭。有些节点可能需要更复杂的关闭逻辑,因为它们可能在接收到信号后需要一些时间来清理资源或保存数据。
在编写 C++ 代码关闭 ROS 节点时,最好使用 ROS 提供的 API 或者 ROS 的程序接口,这样可以更可靠地控制节点的关闭过程。如果有可能,尝试编写一个 ROS 节点,让它监听某个特定的消息或者服务请求,当收到关闭请求时执行关闭逻辑。
如果仍然希望使用 system()
函数发送信号,确保你的程序有足够的权限执行 killall -SIGINT roslaunch
命令,并且可以通过终端手动执行这个命令来验证它是否能够正常工作。
编译运行,成功启动