最近开始学习ROS,但是官方给的教程都是在终端命令行下实现的,如果想要编写代码我使用的是vscode进行编写。
首先vscode它不是一个IDE,vscode只提供编辑的环境而不提供编译的环境,如果想要用vscode来集成开发环境,就必须安装必须的编译器(比如mingw,python,texlive等)、配置相应编译环境(添加环境变量等)、 安装匹配的vscode的拓展插件、通过拓展插件提供的“属性”将外部编译器链接到vscode。
所以vscode仅仅起到了一个编写代码的作用,想要编译ros相关代码,还得转到终端输入命令执行,这就显得有些繁琐,好在vscode可以自定义task完成一些代码或者项目生成,编译,测试,打包等的工作,通过这种方式完成代码生产自动化,可以在做这些事情时不用临时再敲命令,或者写代码。
我在网上看了许多vscode + ros的配置教程,都五花八门,所以在此想把看过的相关博客总结成一套固定好用、清晰的配置流程,因此写了此篇博客,不仅是我个人的学习笔记,也希望能给看到的各位提供帮助。
2022年4月22日更新排雷:
总流程简单总结,详情看博客:
1、创建工作空间: 创建新工作空间(父文件夹),在工作空间中创建子文件夹 src(子文件夹,必须叫src),在父文件夹打开终端执行catkin_make,执行完后执行code .用vscode打开此文件夹(前提安装好插件)。
2、创建功能包: 在左侧资源管理器找到我们创建的工作区中的src文件夹,右键src选择create catkin package,第一个填写自定义功能包名称:xxx,第二个填写使用到的功能包:一般为roscpp rospy std_msgs。
3、配置json文件: 修改task.json以及c_cpp_properties.json,看博客内具体内容。
4、编写cpp: 不多说了。
5、编写CMakeList.txt: 看博客具体内容。
6、vscode编译: ctrl + shfit + b进行编译。
6、vscode运行: ctrl + shfit + p分别执行 ROS:Start、ROS:Run a Ros executable,详情看博客。
安装ROS、catkin_tool两个插件。

接下来我将以创建一个输出hellworld的程序为案例。
新建一个文件夹,在终端执行以下命令:
mkdir -p /工作区名称/src
cd ./你的工作区
catkin_make
如下图所示,我是创建了一个叫helloworld的工作区,并且创建了src的子文件夹(注意,这是必须),然后切换到helloworld文件夹中,执行catkik_make。

用vscode打开你新建的工作区文件夹,在这里我是打开了helloworld文件夹。
在这里教给大家一个通过命令行用vscode打开文件夹的方法:
在想要打开的文件夹目录下打开终端输入code .即可(我不是最后一个知道的吧):
code .
如下图所示,因为安装了ros插件,所以会自动识别catkin环境,自动生成.vscode文件夹,包含c_cpp_properties.json、settings.json,如果没有,清重新打开,一般就会识别到了,这两个文件后面会用到,先放在这。
c_cpp_properties.json主要是includePath参数,当有自定义头文件时,需要在其内添加。setting.json主要是ROS使用python编程,python相关配置,以及其它配置。我这里没有做出改动。
在c_cpp_properties.json当中,includePath自动包含了ros的头文件路径,这样就可以拥有代码提示与自动补全了,如果想添加其他头文件,在这添加即可。
咱先看官方使用终端执行的,但我们不用这个方法。
按正常的创建功能包流程的话,你需要打开终端切换到src目录下(这里就是开始工作空间创建的src),在我这里应该是./helloworld/src输入以下命令执行:
cd src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
我们用以下方法:
在左侧资源管理器找到我们创建的工作区中的src文件夹,右键src选择create catkin package:
- 弹出的第一个框(package name)填写你的功能包名称,这个是自定义,我命名为
helloworld;- 弹出的第二个框(dependencies)填写你用到的功能包名称,这里填
roscpprospystd_msgs;
总之,依次输入helloworld以及roscpp rospy std_msgs。
我觉得最恶心的就是配置json文件,把我搞得晕头转向的。。。以下仅供参考,有需要需要自己更改,比如说路径。
c_cpp_properties.json这个一般不需要更改,自动包含ros的头文件目录,除非你想添加其他头文件目录。
我的如下:
{
"configurations": [
{
"browse": {
"databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db",
"limitSymbolsToIncludedHeaders": false
},
# 头文件路径
"includePath": [
"/opt/ros/melodic/include/**",
"/usr/include/**"
],
"name": "ROS",
"intelliSenseMode": "gcc-x64",
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu11",
"cppStandard": "c++14"
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
}
在
configurations中添加了"compileCommands": "${workspaceFolder}/build/compile_commands.json",具体原因看配置task.json。
settings.json主要是ROS使用python编程,python相关配置,以及其它配置,我这里没有改动。
{
"python.autoComplete.extraPaths": [
"/opt/ros/melodic/lib/python2.7/dist-packages"
],
"python.analysis.extraPaths": [
"/opt/ros/melodic/lib/python2.7/dist-packages"
]
}
在这里还缺少两个json文件:task.json,launch.json,我们进行配置。
task.json按下ctrl + shfit + p输入指令tasks: configure task,然后会下拉出许多,在这里看了好多博客都没有说选择哪一个,随便选一个,比如catkin_make: build,下面我们会直接对其作修改,复制以下代码修改:
{
"version": "2.0.0",
"tasks": [
{
"label": "catkin_make", //代表提示的描述性信息
"type": "shell", //可以选择shell或者process,如果是shell代码是在shell里面运行一个命令,如果是process代表作为一个进程来运行
"command": "catkin_make",//这个是我们需要运行的命令
"args": [
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
],//如果需要在命令后面加一些后缀,可以写在这里,比如-DCATKIN_WHITELIST_PACKAGES=“pac1;pac2”
"group": {"kind":"build","isDefault":true},
"presentation": {
"reveal": "always"//可选always或者silence,代表是否输出信息
},
"problemMatcher": "$msCompile"
},
]
}
"args"中添加了-DCMAKE_EXPORT_COMPILE_COMMANDS=ONc_cpp_properties.json的configurations中添加 "compileCommands": "${workspaceFolder}/build/compile_commands.json"在
task.json的"args"中添加了-DCMAKE_EXPORT_COMPILE_COMMANDS=ON,这里是因为后面编译cpp可能会报错找不到头文件,具体原因我还没有搞懂,懂了后续更新。
接下来就可以执行快捷键ctrl + shfit + b自动执行task.json中的catkin_make指令进行编译了,并在build文件夹下生成compile_commands.json,这个文件是在c_cpp_properties.json中调用的,这样就能找到头文件了。
TODO: 具体
task.json文件起到什么作用,后续等学习到再进行详解。
2022年4月12日更新:
launch.json文件不需要创建,这部分可以略过了。
我们运行会直接通过在vscode执行快捷键ctrl + shfit + p,使用rosrun指令运行对应节点与功能包,或者使用roslaunch指令运行xxx.launch文件(后缀是launch,不是launch.json)。
具体操作看这篇博客第5部分:【ROS入门21讲】订阅者Subscriber的编程使用
launch.json执行快捷键ctrl + shfit + d切换到运行和调试,并选择创建一个launch.json,随便选一个,手动创建也可以,复制以下代码修改:
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
# 这里要修改,找到编译生成的二进制可执行文件
"program": "${workspaceFolder}/devel/lib/myros/myros",
"args": [],
"stopAtEntry": false,
//"preLaunchTask": "build",
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"targetArchitecture": "x64",
"avoidWindowsConsoleRedirection": true,
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
在你创建的工作区的src中创建一个helloworld.cpp,输入以下代码:
#include "ros/ros.h"
int main(int argc, char *argv[])
{
//执行 ros 节点初始化
ros::init(argc,argv,"hello");
//创建 ros 节点句柄(非必须)
ros::NodeHandle n;
//控制台输出 hello world
ROS_INFO("hello world!");
return 0;
}
这个没什么可说的。
在这里可能有人会跟我遇到同样的疑惑,catkin_make 与cmake到底是什么关系,简单一句话来讲,catkin_make是cmake的高级封装,具体的区别我会在文章结尾附上几篇参考博客。
在这里编写CMakeLists.txt 是编写的编写位于你工作区中src下helloworld中的CMakeLists.txt文件,这个文件是事先通过catkin_make指令生成的,在其中添加:
aux_source_directory(./src SRCS)
add_executable(helloworld ${SRCS})
target_link_libraries(helloworld ${catkin_LIBRARIES})
修改后:
cmake_minimum_required(VERSION 3.0.2)
project(helloworld)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES helloworld
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
)
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
aux_source_directory(./src SRCS)
add_executable(helloworld ${SRCS})
target_link_libraries(helloworld ${catkin_LIBRARIES})
这个其实是前面初始化ros环境空间就生成的,直接修改即可。
在对程序进行编译的时候,我遇到了诡异的事情,对于编译之后生成的二进制可执行文件有时候会出现在build文件夹,有时候会出现在devel文件夹,困惑了我好久,网上也没有找到解释的,花了好久好久时间才发现,原来是编译的方式不同。我都是使用的catkin_make指令,造成这种原因是因为我使用指令的方式不一样:
在工作区目录下用终端执行catkin_make会将可执行文件生成在build里面;

在vscode中使用快捷键ctrl + shfit + b进行编译是执行的task.json中你所创建的指令,这种方法会将可执行文件生成在devel;

TODO: 具体为什么会产生这种区别目前也不太了解,等懂了之后再来更新,或者有大佬可以在评论区指出,谢谢。
以上两种编译方式选择一种就可以了,在对应文件夹下寻找可执行文件,在这里为了方便,我选择第二种方案。
运行程序我们需要打开一个ROS MASTER。
打开一个新终端输入roscore即可,如下:
roscore
vscode里面可以执行直接执行指令,代替了第一种方法,不需要来会反复切换终端,减少了麻烦。
执行快捷键ctrl + shfit + p输入ROS:Start,即可打开ROS MASTER。
网上有些博客写的是
ROS: Start Core,但实际上我并没有,可能是进行了更改变成了ROS:Start,如果想要关闭,执行ROS:Stop即可。
打开一个新终端输入rosrun 包名 节点名称即可,如下:
在这里我的包名helloworld,节点名称helloworld
rosrun helloworld helloworld
执行快捷键ctrl + shfit + p输入ROS:Run a Ros executable,代替了在终端调用rosrun helloworld helloworld指令的操作,依次输入你创建的功能包的名称以及节点名称(即编译成功后二进制文件的名称)
运行在终端查看结果,输出以下结果说明成功:

TODO :其实在这里我是想调用
launch.json文件进行程序调试的,但是不知道为什么一添加launch.json就会导致cpp文件的头文件找不到。
2022年4月12日更新:不需要launch.json文件运行,直接通过在vscode执行快捷键ctrl + shfit + p,使用
rosrun指令运行对应节点与功能包,或者使用roslaunch指令运行xxx.launch文件(后缀是launch,不是launch.json)。
具体操作看这篇博客第5部分:【ROS入门21讲】订阅者Subscriber的编程使用
目前这一套流程能够跑通这一个demo案例,但是感觉仍有许多bug和不懂之处,之后了解之后再来更新。
参考博客:
ros项目调试:vscode下配置开发ROS项目
VS Code创建、调试ROS项目
VS Code 配置 ROS catkin
使用Visual Studio Code 开发ROS方法
vscode开发ROS(5)-ROS工程目录结构
VScode debug ROS cpp程序设置 断点调试
使用VScode搭建ROS开发环境的教程详解
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2