linux程序运行时突然出现Killed
,可以使用dmesg | egrep -i -B100 'killed process
查看原因,输出最近killed的信息。
linux程序运行时突然出现Killed
,可以使用dmesg | egrep -i -B100 'killed process
查看原因,输出最近killed的信息。
1 | int main() |
opencv函数: double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)
当measureDist
设置为true时,返回实际距离值。若返回值为正,表示点在多边形内部,返回值为负,表示在多边形外部,返回值为0,表示在多边形上。
当measureDist设置为false时,返回 -1、0、1三个固定值。若返回值为+1,表示点在多边形内部,返回值为-1,表示在多边形外部,返回值为0,表示在多边形上。
1 | /* |
cmp 函数的特点:
1 | // 从小到大排列 |
用来计算特定范围内(包括连续的部分和初始值)所有元素的和,除此之外,还可以用指定的二进制操作来计算特定范围内的元素结果,需要 #include <numeric>
。 三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。
1 | vector<int> v; |
当不正确关闭Gazebo时,再次启动Gazebo会遇到sever无法启动的问题。1
Exception [Master.cc:50] Unable to start server[bind: Address already in use]. There is probably another Gazebo process running.
解决方法:用ps命令查找gzserver
进程,将其kill。或是干脆重启系统
报错: Unable to convert from SDF version 1.7 to 1.6
把world文件的第一行改成 <sdf version = '1.6'>
文件使用了OBJ meshes
,这是从Gazebo 7.4.0才可支持,使用gazebo -v
发现我的gazebo版本是 7.0
报错 [joint_state_publisher-3] process has died 或者 UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position xxx ordinal
去掉urdf、xacro、launch文件中的中文注释,或者改为英文,而且第一行不能有中文。
1 | <plugin name='front_right_middle_sonar_sensor' filename='libgazebo_ros_range.so'> |
.urdf.xacro
文件中的颜色不识别。需要在文件开头定义颜色值,否则默认不识别1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<material name="blue">
<color rgba="0.0 0.0 0.8 1.0"/>
</material>
<material name="red">
<color rgba="0.8 0.0 0.0 1.0"/>
</material>
<material name="white">
<color rgba="1.0 1.0 1.0 1.0"/>
</material>
<material name="yellow">
<color rgba="0.8 0.8 0.0 1.0"/>
</material>
运行Gazebo竟然出现错误,Gazebo页面卡住黑屏,在终端出现 Gazebo [Err] [REST.cc:205] Error in REST request
解决方案sudo gedit ~/.ignition/fuel/config.yaml
,然后将 url : https://api.ignitionfuel.org
注释掉,添加 url: https://api.ignitionrobotics.org
在Gazebo中进行小车仿真的过程中会出现如下警告 The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia. As a workaround, you can add an extra dummy link to your URDF 该警告的意思是根关节的base_link
在urdf中具有惯性参数,但是KDL不支持,建议的解决办法是,增加一个额外的dummy link
。
这个问题看似很麻烦,实际解决起来是非常简单的,只需添加一个link和一个joint即可:1
2
3
4
5
6<link name="dummy">
</link>
<joint name="dummy_joint" type="fixed">
<parent link="dummy"/>
<child link="base_link"/>
</joint>
当然link的名称是可以自己改的
ubuntu18.04 装的Gazebo版本是9,升级方式,但是能不升级就不升级。
使用Gazebo时出现下面报错:1
2[spawn_entity.py-5] [ERROR] [1715655287.539237215] [spawn_entity]: Service %s/spawn_entity unavailable. Was Gazebo started with GazeboRosFactory?
[spawn_entity.py-5] [ERROR] [1715655287.540067060] [spawn_entity]: Spawn service failed. Exiting.
1 | [ERROR] [gzserver-1]: process has died [pid 239512, exit code 255, cmd 'gzserver -slibgazebo_ros_init.so -slibgazebo_ros_factory.so -slibgazebo_ros_force_system.so']. |
这是因为关闭的过程中有些Gazebo的程序没有完全关闭,导致再次启动时,无法正常开启。所以,只要把gazebo的相关程序关闭即可: killall gzserver
。 此时,再次启动gazebo,就能正常打开了。
如果担心是自己程序的问题,使用ros2 launch gazebo_ros spawn_entity_demo.launch.py
验证是不是Gazebo自身的问题
joint_state_publisher
报错 UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 30-36: ordinal not in range(128)
/opt/ros/melodic/lib/joint_state_publisher_gui/joint_state_publisher
和 /opt/ros/melodic/lib/joint_state_publisher
,在开头import sys
之后增加1 | reload(sys) |
或者修改文件/opt/ros/melodic/lib/python2.7/dist-packages/joint_state_publisher/__init__.py
,也是添加1
2reload(sys)
sys.setdefaultencoding("utf-8")
运行spawn_model
也可能会同样的报错,到/opt/ros/melodic/lib/python2.7/dist-packages
文件夹,然后新建一个sitecustomize.py
文件,内容为1
2
3
4#coding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
保存后给文件权限。
origin并不特别,就像分支名 master 在git中没有任何特殊意义一样.当执行git init时,master会作为初始分支的默认名字,因此使得master分支名被广泛使用。而origin是执行git clone时的默认服务器名称,当然可以通过指令git clone -o cat
,使得默认服务器名称为cat,而默认远程分支为cat/master
从远程分支check out一个本地分支,该本地分支被称为追踪分支(tracking branch),被追踪的分支被称为上游分支(upstream branch),追踪分支可以理解为是和远程分支有直接关联的本地分支. 如果我们在追踪分支时执行git pull,git会自动知道需要获取和merge的分支的服务器.
1 | git remote add origin https://github.com/user/user.github.com.git |
在本地创建分支develop并切换到该分支1
git checkout -b develop(本地分支名称) origin/develop (远程分支名称)
远程分支上的内容都拉取到本地1
2# develop 为远程分支名称
git pull origin develop (远程分支名称)
回到本地文件夹查看,已完成拉取远程某个分支到本地。拉去更新也是这个命令,如果是git pull
,可能会把所有分支的内容都拉下来,用时较长,没有必要。
git branch -a
list both remote-tracking and local branches
git branch -vv
会列出所有的分支信息,包含追踪分支的关联关系
常见的情况是,我自己有一个分支me
,还要拉取另一个人的分支,两人共用部分文件,合并到分支master。在自己分支修改文件结束后,提交到自己的分支。然后切换到master分支,git checkout master
。由于不知道另一个人是否更新了代码,所以先执行git pull
更新一下,然后git merge me
,这就合并了我的分支,再git push origin master
。
有时会出现冲突 ,这是由于两人修改了同一个文件,冲突的提示1
2
3Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.git status
也可以告诉我们冲突的文件. 在冲突的文件里,Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,只能自己手动修改,然后再提交。解决冲突的过程一直是在master
分支。 用带参数的git log
也可以看到分支的合并情况
1 | # 当前是user分支 |
git branch -d user
1 | user@user:~/dev_ws/$ git branch -d user |
1 | git push origin --delete remoteBranchName |
1 | # 执行 git status 的结果 |
这发生在多人可能操作 master 分支的时候,我自己的分支提交完了,切换到master分支,要执行合并时,出现这个问题,并不是文件冲突的问题。按如下方法解决:
如果不需要保留本地的修改,只要执行下面两步:1
2git fetch origin
git reset --hard origin/master
当我们在本地提交到远程仓库的时候,如果遇到上述问题,我们可以首先使用如下命令:1
2
3
4git rebase origin/master
git pull --rebase
# 提交到远程仓库
git push origin master
执行git pull
出现下面提示1
2Please commit your changes or stash them before you merge.
Aborting
这是因为本地修改了一些文件,但远程仓库已经有别人提交更新了,所以有冲突。一般不会直接commit本地的修改。
1 | git reset --hard |
1 | # 当前在个人分支 |
我在自己的分支me
开发,主分支比我领先很多。有一次,我从git上下载了主分支的压缩包,然后手动覆盖了一部分文件以更新,这其实是不正确的操作。
第二天我先切换到主分支,更新到最新,然后切换到me
分支,提交到远程后,合并主分支,结果出现的冲突比我自己修改的多很多,因为把我昨天手动覆盖的那些也包括了。这种情况下,只能手动解决冲突,但是大部分文件一定是用主分支,如果一个个打开会很麻烦。
用VSCode打开工程,分支管理里会显示文件冲突,对使用主分支版本的文件,右键选择就可以,而且能同时选多个文件。解决完之后,选择暂存文件,之后可以push了。
Navigation2中引入了行为树来组织机器人的工作流程和动作执行。
行为树本身并不具体实现机器人的执行内容,它只负责将执行内容进行编排。以Navigation2为例,具体的执行内容实现是放在各个server中的。行为树上的节点与server进行通信,请求具体的执行内容,然后获得反馈。根据反馈结果又可以请求另外的执行内容。这些不同执行内容间的跳转就是由行为树控制的。
另一种比较常见的组织机器人行为的方式是状态机。ROS1中的move_base就是基于状态机的。它与行为树最显著的区别是状态与执行内容是绑定在一起的。当执行内容需要在多个状态中执行时,各个状态下都需要放置执行内容的逻辑。当业务逻辑代码分散在各处时就不太好维护了
ROS2行为树动态库默认安装在/opt/ros/galactic/lib/libbehaviortree_cpp_v3.so
,头文件在/opt/ros/foxy/include/behaviortree_cpp_v3
行为树并不执行特定的功能代码,它只是把各个业务逻辑代码组织起来。通过不同的组织方式和少量代码的修改可以实现截然不同的功能
Sequence树节点的特点是它的children必须全部返回SUCCESS才认为执行成功,有一个child返回FAILURE就导致这个树节点执行失败。
If a child returns SUCCESS, it ticks the next child.
action
动作节点通常实现服务客户端和动作客户端,也可以是一些简单的执行程序。他们通过向Planner server,Controller server,Recovery server发送请求来启动相应的功能程序。action通常作为行为树中的叶子节点,负责具体行为和功能的实现。但这些具体的功能代码并没有在叶子节点中而是在对应的服务端。
这是条件控制节点。比如判断电池电量,某一开关信号等等。
这是行为树中的控制流。类似c++语言中的if else,switch等等。它负责构建行为树的逻辑结构。sequeence,fallback等等就属于这个范畴。
decorator是节点装饰器。它只能有一个子节点。负责将子节点的结果进行修饰。比如将子节点的结果进行反向,约束子节点的执行次数等等。
ControlNode
至少有1个子节点,DecoratorNode
只有1个子节点,Subtree
没有子节点
行为树中的共有数据是存放在Blackboard中的。Blackboard是以键值对
的形式存储数据的。各个行为树的叶子节点均可以通过key访问到需要的数据。节点的输入端口可以从黑板读取数据,节点的输出端口可以写入黑板。
Ports是用于在节点间交换数据而存在的。一个行为树叶子节点可以定义输入的Ports和输出的Ports。当不同叶子节点的Port有相同的key名称时,可以认为它们是相通的。当在行为树叶子节点中声明了这些Ports时,也需要同时在xml文件中描述这些Ports。
注意设置子树的__shared_blackboard
属性为true,否则C++程序可能报错
xml格式有以下几个要点
main_tree_to_execute
的属性,表示执行哪颗树BehaviorTree
的ID的属性值必须是不同的,此时必须指定main_tree_to_execute
标签main_tree_to_execute
属性可有可无TreeNodesModel
标签,主要用于Groot可视化。对于C++程序来说,可以没有。createTreeFromFile
的文件路径错误时,会报错 what(): Internal error in realpath(): No such file or directory
Groot1的日志工具很不好用,在fbl
文件比较大的时候,很容易卡死。如果总的行为树很大,需要放大才能观看流程,十分不方便。Groot2的日志工具据说很好用,但是收费。
拆分行为树后,在Groot里不方便直接打开子树,只能再开一个Groot打开子树的xml文件. 后来Groot2解决了这个问题,在设置的Editor标签里还可设置是否每次都加载<include>
标签对应的文件。
${CMAKE_CURRENT_LIST_DIR}
和 ${CMAKE_CURRENT_SOURCE_DIR}
一般都是当前CMakeLists.txt
所在的目录。
file (GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
把路径下的所有cpp文件名都加入变量SOURCE_FILES
C++中的优先队列(priority queue)是一种特殊的队列,它允许在队列中添加元素时自动根据元素的优先级进行排序,
以便能够快速访问具有最高优先级的元素。优先队列可以用来解决很多算法问题,例如Dijkstra算法、Prim算法等。
1 |
|
优先队列不支持随机访问,只允许访问队头元素,不允许访问其余的数据
package.xml
中包含该功能包的依赖信息,它可以帮助编译工具colcon
确定多个功能包编译的顺序。
CMakeList.txt
当中,必须有1
2find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
用于生命周期管理,平时可以不添加
例如package
名称为project(first_node)
,必须修改的部分如下1
2
3
4
5add_executable(test_node src/test.cpp)
ament_target_dependencies(test_node rclcpp std_msgs)
install(TARGETS test_node DESTINATION lib/install_node)
target_link_libraries(test_node behaviortree_cpp_v3)
add_executable
不必解释
ament_target_dependencies
是官方推荐的方式去添加依赖项。它将使依赖项的库、头文件和自身的依赖项被正常找到。
install
是安装库的语句。它将在工作空间生成文件 install/first_node/lib/install_node/test_node
ament_package()
最后一句,不要修改。项目安装是通过ament_package()
完成的,并且每个软件包必须恰好执行一次这个调用。ament_package()
会安装package.xml文件,用ament索引注册该软件包,并安装CMake的配置(和可能的目标)文件,以便其他软件包可以用find_package
找到该软件包。由于ament_package()
会从CMakeLists.txt
中收集大量信息,因此它应该是CMakeLists.txt
中的最后一个调用。ament_export_dependencies(${dependencies})
这句会将依赖项导出到下游软件包。这样该库使用者也就不必为那些依赖项调用find_package了。