1、“demo_cpp_pkg” not found
hou@hou-virtual-machine:~/chap2$ ros2 run demo_cpp_pkg cpp_node
Package 'demo_cpp_pkg' not found
解决方案:在功能包上级目录添加环境变量
source install/setup.bash
2、No executable found
hou@hou-virtual-machine:~/chap2$ ros2 run demo_cpp_pkg cpp_node
No executable found
解决方案:C++功能包需要在功能包中的cmakelist文件中添加下列标红语句:
cmake_minimum_required(VERSION 3.8)
project(demo_cpp_pkg)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
add_executable(cpp_node src/cpp_node.cpp)
target_include_directories(cpp_node PUBLIC ${rclcpp_INCLUDE_DIRS}) #头文件包含
target_link_libraries(cpp_node ${rclcpp_LIBRARIES}) #库文件链接
# ament_target_dependencies(cpp_node rclcpp)
install(TARGETS
cpp_node
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
3 工作空间/功能包架构
每个工作空间下,有build(编译产生的过渡文件) install(最终的文件) src log(日志)文件夹,src文件夹下又可以有若干功能包,每次编译colcon build都会产生新的build install log。
4 递归创建功能包:如果没有此包,则递归创建
mkdir -p chap2_ws/src
5 、删除文件夹以及子文件夹
rm -rf build/ log/ install/
6、移动文件夹
mv 目标文件 目标文件夹
7、只构建工作空间中的某一个功能包
colcon build --package-select demo_cpp_package
8、只能在工作空间下colcon build!!!!否则文件夹会很乱
9、如何添加pkg的依赖
在package.xml文件中,添加这一行代码:demo_cpp_pkg是你希望你的功能包 依赖的 其他功能包的名字。
<depend>demo_cpp_pkg</depend>
10、clear清除终端所有的消息
11、如何在功能包中添加新的文件(node),在功能包(比如demo_python_pkg)中的同名文件夹demo_python_pkg中添加你想要添加的python文件(比如person_node),在里面一定要写main函数,接着在setup.bash文件中添加入口。
比如下图中的'person_node = demo_python_pkg.person_node:main',
需要注意的是,句尾一定要加 “,”,作为两个节点的分割,否则编译成功但不能运行。
12、colcon build 的实际逻辑:前面说到了colcon build会产生install文件夹,其中会有一个python 3.10文件夹,这个里面就放着我们在src文件夹中写的python源文件,也就是说我们每次ros2 run的时候,ros2 就会到这个python3.10文件夹下去寻找需要的文件。 因此,可以修改src中的源文件再重新编译,也可以直接在python3.10中修改编译后的文件,都可以达到重新编译的效果。
13、如何将一个Python文件变成一个node节点
import rclpy
from rclpy.node import Node
class PersonNode(Node):
def __init__(self, node_name: str,name_value: str, age_value: int) -> None:
print("PersonNode被调用了,添加了两个属性")
super().__init__(node_name)
self.name = name_value
self.age = age_value
def eat(self, food_name: str):
"""
方法:吃东西
food_name:食物名字
"""
self.get_logger().info(f"{self.name}, {self.age}岁, 爱吃{food_name}")
def main():
rclpy.init()
node = PersonNode("zhangsan","张三", 23)
node.eat('鱼香肉丝')
rclpy.spin(node)
rclpy.shutdown()
14、在c++的class中,"->"指的是从类的属性中选择属性,不加的话就是从类的方法中传入的参数
15、如何创建c++节点类
#include "rclcpp/rclcpp.hpp"
class PersonNode : public rclcpp::Node
{
private: // 私有属性
std::string name_;
int age_;
public:
PersonNode(const std::string &node_name, const std::string &name, const int &age)
:Node(node_name) /*调用父类的构造函数,等效于python的super().__init__()*/
{
this->name_ = name;
this->age_ = age;
}
void eat(const std::string &food_name) // 加const使得变量不能在函数内做修改
{
RCLCPP_INFO(this->get_logger(), "我是%s, %d岁, 爱吃%s", this->name_.c_str(),
this->age_, food_name.c_str());
}
};
int main(int argc, char** argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<PersonNode>("person_node", "张三", 21); // make_shared创建指针
RCLCPP_INFO(node->get_logger(), "你好, C++节点!");
node->eat("鱼香肉丝");
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
16、echo将输出重定向到文件,也可以进行简单的文件输出
17、一个节点通常是单线程,复杂的时候会用到多线程。