ROS2基础入门

1. ROS2文件系统

1.1 概述

架构分层:分为操作系统层中间层应用层三层结构

在这里插入图片描述

  • 操作系统层

    ROS2实质是构建机器人应用程序的SDK,必须依赖传统操作系统

    • 支持平台:可运行在Linux、Windows、Mac或RTOS(实时操作系统)上
    • 发展历史:ROS1时代主要支持Ubuntu,ROS2实现真正跨平台
  • 中间层

    中间层主要由数据分发服务DDSROS2封装的机器人开发中间件组成

    • DDS特性
      • 去中心化的数据通信方式
      • 起源于军事领域应用,通信质量有保障
      • 引入QoS(服务质量)机制,保证恶劣网络环境下的通信效果
    • 中间件构成
      • 客户端库(如rclcpprclpy
      • DDS抽象层实现DDS模块可插拔设计
      • 进程内通信API(提高通信效率)
  • 应用层

    核心单元为以功能包为基本构建单元

    • 组成内容:包含源码数据定义接口配置文件
    • 开发者重点:一般开发者工作主要集中在应用层,通过实现特定功能的功能包构建机器人应用

1.2 工作空间目录结构

WorkSpace --- 自定义的工作空间。
|-- build: 存储中间文件的目录,该目录下会为每一个功能包创建一个单独子目录。
|-- install: 安装目录,该目录下会为每一个功能包创建一个单独子目录。
|-- log: 日志目录,用于存储日志文件。
|-- src: 用于存储功能包源码的目录。
    |-- C++功能包
        |-- package.xml: 包信息,比如:包名、版本、作者、依赖项。
        |-- CMakeLists.txt: 配置编译规则,比如源文件、依赖项、目标文件。
        |-- src: C++源文件目录,包含该功能包下的多个节点程序源代码。
        |-- include: 头文件目录。
        |-- msg: 消息接口文件目录。
        |-- srv: 服务接口文件目录。
        |-- action: 动作接口文件目录。
    |-- Python功能包
        |-- package.xml: 包信息,比如:包名、版本、作者、依赖项。
        |-- setup.py: 与C++功能包的CMakeLists.txt类似。
        |-- setup.cfg: 功能包基本配置文件。
        |-- resource: 资源目录。
        |-- test: 存储测试相关文件。
        |-- 功能包同名目录: Python源文件目录,包含该功能包下的多个节点程序源代码。

另外,无论是Python功能包还是C++功能包,都可以自定义一些配置文件相关的目录

  • 基本结构
    • workspace:自定义工作空间根目录
    • build:存储编译中间文件,每个功能包有单独子目录
    • install:安装目录,每个功能包有单独子目录存放生成的可执行节点程序及依赖的头文件
    • log:日志存储目录
    • src:功能包源码目录,包含多个创建的功能包目录
  • C++功能包结构
    • package.xml:包信息(名称、版本、作者、依赖等)
    • CMakeLists.txt:编译规则配置
    • src:C++源文件目录
    • include:头文件目录
    • msg/srv/action:消息/服务/动作接口文件目录
  • Python功能包结构
    • package.xml:包信息
    • setup.py:类似C++的CMakeLists.txt
    • setup.cfg:基本配置文件
    • resource:资源目录
    • test:测试文件目录
    • 同名目录:Python源文件目录
  • 自定义目录
    • launch:存储launch文件
    • rviz:rviz2配置文件
    • urdf:机器人建模文件
    • params:参数文件
    • world:仿真环境文件
    • map:导航地图文件

2. ROS2核心模块

2.1 通信模块及功能包实现

​ 通信模块是RO2核心模块,负责数据交互,是学习和工作重点。应用场景包括:控制机器人底盘运动、传感器数据传输、人机交互指令下发与反馈、导航与机械臂系统数据交互。所有数据交互都依赖通信模块,开发者构建应用程序时通信部分占较大比重。通常通过相关的功能包实现通信模块

2.1.1 ROS2项目构建及功能包开发流程

​ 需要先创建工作空间的文件夹即ros2项目,并在创建src目录,在src目录下创建该ros2项目的功能包,然后修改生成可执行节点文件的源代码和相关配置文件即可。

1.工作空间(ROS2项目)的创建与编译

​ 所有ROS2项目都必须建立在工作空间(workspace)中,这是项目存储源代码、中间文件、日志和配置的根目录。可以通过以下命令创建工作空间文件夹及该工作空间下的src功能包源代码目录,然后进行编译初始化。

// 假设创建的ros2项目名是ws00_helloworld
mkdir ws00_helloworld
// 需要在工作空间下进行操作
cd ws00_helloworld
// 创建src源目录文件用于存放功能包源文件
mkdir src
// 初始化编译以自动生成所需文件
colcon build

​ 编译后将自动在该工作空间中生成build(编译中间文件)、install(安装文件)、log(日志)三个子目录,与手动创建的src(源代码)目录共同构成标准工作空间结构,即一个完整ROS2项目的文件结构。

2.ROS2项目的功能包创建、节点程序的源代码编写

​ 一个ROS2项目的主要工作流程是功能包的可执行节点程序的编写与执行。一个ROS2项目可以为不同模块创建不同的功能包,同时每个功能包下可以生成多个可执行的节点程序文件。

  1. 创建功能包

    必须在工作空间即项目下的src功能包源代码文件目录下,执行以下ros2命令创建功能包。

    // 假设创建的功能包名为pkg01_test_cpp,功能包下一个可执行的节点程序名为ros2test,这种是创建C++功能包
    ros2 pkg create pkg01_test_cpp --build-type ament_cmake --dependencies rclcpp --node-name ros2test
    // 这种是创建Python功能包
    ros2 pkg create pkg02_test_py --build-type ament_py --dependencies rclpy --node-name ros2test
    

    执行该命令创建功能包后,会自动在src目录下创建一个功能包同名的存放功能包源代码的目录,在其中的src目录下会存放可执行节点程序的同名节点名称的源代码文件。

  2. 添加及编写节点程序源文件、修改配置文件

    ​ 一般需要使用到ROS2的客户端依赖包的库文件,在C++功能包中为rclcpp依赖包,在Python功能包中为rclpy依赖包,标准的节点程序的编写流程是继承rclcpp或rclpy的Node类,然后在该类中实现特定的节点程序功能。注意创建功能包时只允许在--node-name参数中指定该功能包的一个节点程序,在需要功能包下实现多个节点程序时,可以通过添加源文件方式,并在CMakeLists.txt的配置文件中或setup.py的配置文件中修改实现。在创建功能包的参数--dependencies指定依赖的功能包外,需要添加新的依赖包时,同样需要在该配置文件中进行修改

    推荐的节点程序源文件编写方式

    ​ 这种继承Node类实现在子类结点中编写业务逻辑的方式,可以在一个进程中组织多个节点,以实现在进程内各个高效方式通信。相比于直接使用Node类的每个结点实例一个进程方式,各个节点需要跨进程通信方式更加高效。

    // pkg01_test_cpp::ros2test.cpp:C++功能包的可执行节点源程序编写方式
    #include "rclcpp/rclcpp.hpp"
    
    // 继承rclcpp::Node方式创建特定子类结点,在其中编写业务功能
    class MyNode: public rclcpp::Node{
    public:
    	MyNode():Node("node_name_cpp"){
    		RCLCPP_INFO(this->get_logger(),"hello world!(C++)");
    	}
    }
    
    int main(int argc, char *argv[]){
    	rclcpp::init(argc,argv);
    	std::shared_ptr<MyNode> node = std::make_shared<MyNode>();
    	rclcpp::shutdown();
    	return 0;
    }
    
    
    # pkg02_test_py.ros2test.py:Python功能包的可执行节点源程序编写方式
    import rclpy
    from rclpy.node import Node
    
    # 继承rclpy包的Node方式创建特定子类结点,在其中编写业务逻辑
    class MyNode(Node):
    	def __init__(self):
    		super().__init__("node_name_py")
    		self.get_logger().info("hello world!(Python)")
    
    # 功能包的节点入口程序
    def main():
    	rclpy.init()
    	node = MyNode()
    	rclpy.shutdown()
    	return 0
    
    if __FILE__ == "main":
    	main()
    
3.ROS2项目的功能包编译

​ ROS2项目在完成功能包的节点程序的源代码编写及相应配置文件的修改后,通过以下colcon指令进行编译功能包,包括编译所有功能包和编译指定功能包方式。注意在编译所在位置和初始化创建工作区间时的编译位置相同,都必须在工作空间下进行编译

// 默认编译该工作空间即项目下的所有ros2功能包
colcon build
// 编译指定ros2功能包列表
colcon build --packages-selection pkg01_test_cpp pkg02_test_py
4.ROS2项目的功能包的节点程序执行

​ 直接执行以下命令运行该ros2项目的功能包的指定节点程序时,会默认优先在apt二进制安装的系统路径下/opt/ros/humble/lib查找指定功能包名的可执行的同节点名的可执行文件本地编译生成的功能包在本地工作空间下的install文件下的相应功能包名的lib文件下而无法找到,因此需要先执行该工作空间下的install文件的setup.bash文件修改下列环境变量,以方便可以找到本地编译生成的功能包及其可执行的节点程序。

// 先修改查找前缀
source install/setup.bash
// 执行本地编译指定功能包pkg01_test_cpp的指定节点程序ros2test
ros2 run pkg01_test_cpp ros2test

source install/setup.bash主要会修改以下ROS2关键的环境变量:

  • AMENT_PREFIX_PATH最重要

    这是 ROS 2 用来查找包的核心路径。

    export AMENT_PREFIX_PATH=/home/user/ros2_ws/install:/opt/ros/humble
    
    • 作用find_package()会依据这个变量列出的路径,去搜索 *Config.cmake文件。
    • 顺序越靠前的路径优先级越高
  • PATH

    export PATH=/home/user/ros2_ws/install/bin:$PATH
    
    • 作用:让系统能在终端直接找到 ros2colcon以及你自己包里安装的可执行文件。
  • LD_LIBRARY_PATH

    export LD_LIBRARY_PATH=/home/user/ros2_ws/install/lib:$LD_LIBRARY_PATH
    
    • 作用:告诉操作系统(动态链接器)去哪里找 .so库文件。
  • PYTHONPATH

    export PYTHONPATH=/home/user/ros2_ws/install/lib/python3.10/site-packages:$PYTHONPATH
    
    • 作用:让 Python 能找到你工作空间中安装的 Python 模块。

在以非登录交互方式打开一个bash窗口时,无法直接运行本地工作空间下的某个功能包的某个节点程序**,可以将source install/setup.bash命令添加到用户配置文件~/.bahrc中,其会在打开一个bash窗口时自动执行**。可以通过以下指令直接写入该文件,也可以直接打开该文件,在最后添加这行source /{工作空间路径}/install/setup.bash

echo "source /{工作空间路径}/install/setup.bash" >> ~/.bahrc
2.1.2 功能包的获取方式
1.apt二进制安装

ROS社区或官方提供的功能包,可以通过apt指令的二进制方式进行安装。在不完全记得功能包时,可以通过以下指令由关键词来搜素所需的功能包。

# 按照指定ros版本的功能包
apt install ros-ROS2版本代号−功能包名称
# 根据关键词查找指定ros版本的功能包
apt search ros-ROS2版本代号-* | grep -i 功能包关键词

通过apt二进制方式只能安装ROS社区或官方提供的功能包,并且安装后在指定系统路径/opt/ros/humble下,由于该路径在包查找时自动包括系统路径,因此可以在安装后直接使用

2.GitHub等平台将功能包源码下载后编译安装

从GitHub等平台将功能包的源代码进行下载到本地工作空间即ROS项目中,然后进行自行编译的软件安装方式。从获取官方或第三方提供的源代码必须选择与当前ROS项目匹配的分支版本(如humble对应ROS2)。采用下述命令可以将GitHub上的源代码进行下载到当前文件夹。

git clone GitHub仓库地址 -b 指定分支

通过下载功能包源代码然后进行编译安装的方式,可以自行修改源码以适应自身需求

3.自己编写功能包源码进行编译安装

​ 开发者根据业务需求编写功能包所需实现的需求。

2.1.3.ROS2功能包的常用操作命令
1. 创建功能包
ros2 pkg create 包名 --build-type 构建类型 --dependencies 依赖列表 --node-name 节点名称
  • 构建类型
    • 有cmake、ament_cmakeament_python三种可选,默认类型为ament_cmake
    • C++功能包常用ament_cmakePython功能包用ament_python
  • 节点名称
    • 会自动生成对应相同名称的源文件并生成配置文件
    • 若不设置则需要手动添加源文件和修改配置文件
  • 依赖列表
    • 多个依赖的功能包用空格分隔
    • 建议创建时一并添加完整依赖项,避免后续手动修改配置文件
2. 编译功能包
  • 完整编译:

    未选择特定的功能包时,默认会构建工作空间下所有功能包

    colcon build 
    
  • 选择性编译

    只构建工作空间下的功能包列表中的指定功能包,多个功能包用空格分隔

    colcon build --packages-select 功能包列表
    
3. 执行功能包
 ros2 run 功能包 可执行节点文件 [参数]
4. 查找功能包
  • 查询指定功能包下的可执行节点程序

    • 列出所有功能包及其可执行程序

      ros2 pkg executables
      
    • 列出指定功能包的可执行程序

      ros2 pkg executables 包名
      
  • 列出所有可用功能包

    ros2 pkg list 
    
  • 输出指定的功能包安装路径

     ros2 pkg prefix 包名
    
  • 查看指定功能包的xml配置文件,包括包名、版本、描述、维护者、许可证、依赖项等信息

    ros2 pkg xml 包名
    

技巧:任何命令后加-h或–help可获取帮助文档,查看其所有可添加的参数及作用


2.1.4 ROS2功能包的配置文件
1.xml文件

无论是C++功能包文件或Python功能包文件,在被创建时都会生成xml文件,用于描述该功能包信息,在使用ros2 pkg xml 命令时会打印该xml文件内容

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>pkg02_test_py</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="lzw@todo.todo">lzw</maintainer>
  <license>TODO: License declaration</license>
	
  // 在需要增加依赖功能包以类似rclpy方式增加一行
  <depend>rclpy</depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>
  • 根标签

    声明文件格式版本

  • 元信息

    • 包名,必须和功能包名相同对应
    • 版本号
    • 描述信息
    • 维护者信息
    • 软件协议
    • 介绍网址
  • 依赖项

    • <buildtool_depend> 构建工具依赖
    • 通用依赖的功能包,通常在创建功能包时的--dependencies参数指定的依赖功能包,在需要添加新依赖的功能包时,在这里添加一行。C++功能包必须声明rclcpp依赖包,Python功能包必须声明rclpy依赖包。
    • <exec_depend> 执行依赖
    • <test_depend> 测试依赖
    • <build_type>构建类型:对于C++文件来说创建功能包时指定的构建类型为ament_cmake,对于Python文件的功能包说为ament_python
2.CMakeLists.txt文件

C++功能包创建时的配置文件,规定ros2功能包的编译流程,一个功能包通常有多个可执行的节点程序,对应于CMakeLists.txt中生成的多个可执行文件

cmake_minimum_required(VERSION 3.8)
# 项目名必须和功能包名相同
project(pkg01_test_cpp)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# 查找所有依赖的功能包,可以以类似于方式添加其他所需要的依赖功能包
find_package(ament_cmake REQUIRED) # 构建工具ament_cmake所需要的依赖包
find_package(rclcpp REQUIRED)	# rclcpp库文件的依赖包

# 生成可执行的功能包节点程序,通常有多个可以实现一个功能包内有多个可执行的节点程序,生成的可执行程序名称必须和功能包节点名称相同
add_executable(ros2test src/ros2test.cpp)

# 指定指定所需生成的节点程序ros2test指定的编译头文件所在路径及安装后头文件所在路径
target_include_directories(ros2test PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>	# 编译时头文件所在路径
  $<INSTALL_INTERFACE:include>								# 安装后头文件所在路径
)

# 规定C语言和C++语言标准,ROS2一般使用C99和C++17标准
target_compile_features(ros2test PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17

# 为生成的节点程序目标添加find_package所需要依赖包的运行时库,其他依赖包的库以类似方式添加
ament_target_dependencies(
  ros2test
  "rclcpp"		# 对应find_package中添加的rclcpp依赖包的库,ament_cmake构建时使用,非运行时库
)

# 编译完成后的安装指令,将生成的节点程序拷贝在项目的install目录下指定功能包名的lib文件下,以方便ros2 run命令可以找到并执行
install(TARGETS ros2test
  DESTINATION lib/${PROJECT_NAME})
# 一般想要被外界使用该功能包库,通过find_package找到时,还需将该库依赖的头文件include拷贝到install的include目录下
install(DIRECTORY include 
  DESTINATION include)

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()

# 对于ament_cmake构建工具来说,在最后必须使用表示这是一个完整的ament包进行构造
ament_package()
3. setup.py文件

Python功能包创建时的配置文件,规定该功能包的多个节点程序对应的py文件

from setuptools import find_packages, setup

# 必须和功能包名相同
package_name = 'pkg02_test_py'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='lzw',
    maintainer_email='lzw@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    extras_require={
        'test': [
            'pytest',
        ],
    },
    # 重点关注功能包的所有节点程序所对应的源文件的入口函数,可以以其他类似的方式为功能包的节点设置入口程序
    entry_points={
        'console_scripts': [
            'rostest = pkg02_test_py.rostest:main' # rostest节点程序对应src/pkg02_test_py/rostest.py中的main函数
        ],
    },
)

  • 基本结构
    • package_name变量必须与package.xml的一致,即和功能包名相同
    • setup()函数配置各种构建参数
  • 关键参数
    • name/version:包名和版本
    • packages:功能包列表
    • data_files:需要安装的文件及路径
    • install_requires:安装依赖(如setuptools)
    • entry_points映射源文件与可执行的节点程序,可以在这里为功能包的节点设置入口程序
  • 维护信息:包含maintainer、description、license等元信息

2.2 工具模块

2.2.1 终端命令与RQT

​ 在对编译生成后的可执行文件进行调试时,可以在终端命令界面使用命令方式进行启动,这种方式适合快速运行调试和远程连接时的使用场景。RQT工具提供一种图形化窗口方式设置启动命令的参数(如坐标、角度),然后执行命令

2.2.2 launch文件

​ 在需要进行测试同时启动大量命令时,采用命令行方式一个个进行启动过于繁琐,可以通过Python脚本批量启动节点的launch文件进行设置,支持内部以循环方式创建多个相同类型节点,并且支持节点参数可编程化配置

# 某个功能包下的launch.py文件
from launch import LaunchDescription	# ROS2启动文件的“容器”,所有要启动的东西都要放进去
from launch_ros.actions import Node		# 用来描述一个准备启动的ROS2节点

# launch文件的入口函数的固定写法:colcon build和 ros2 launch会编译和运行这个函数
def generate_launch_description():
    nodes = list()
    # 指定节点启动的参数列表
    colors = [
        {"background_r": 255, "background_g": 0, "background_b": 0},    # 红 turtle0
        {"background_r": 0, "background_g": 255, "background_b": 0},    # 绿 turtle1
        {"background_r": 0, "background_g": 0, "background_b": 255},    # 蓝 turtle2
        {"background_r": 255, "background_g": 255, "background_b": 0}   # 黄 turtle3
    ]
    
    # 循环创建4个可执行节点程序
    for i in range(4):
        node = Node(
           		# package指定功能包名
            	package="turtlesim",
            	# executable指定可执行节点程序名
            	executable="turtlesim_node",
           		# name指定ROS2中的节点名称,节点名称必须唯一
            	name=f'turtle{i}',
                # parameters指定该Node结点启动时的参数,需要以字典列表方式提供即[{},...]方式
            	parameters=[colors[i]]
            	# parameters同时也允许通过yaml文件方式提供各节点启动参数,需要以yaml文件路径列表方式提供即[filepath,...]
                parameters=[config/turtlesim_params.yaml]
        )
        nodes.append(node)
    # 将创建的节点列表放入到启动文件容器中
    return LaunchDescription(nodes)

# 某个功能包下的config/turtlesim_params.yaml文件
turtle0:
  ros__parameters:
    background_r: 255
    background_g: 0
    background_b: 0

turtle1:
  ros__parameters:
    background_r: 0
    background_g: 255
    background_b: 0
    
turtle2:
  ros__parameters:
    background_r: 0
    background_g: 0
    background_b: 255

turtle3:
  ros__parameters:
    background_r: 255
    background_g: 255
    background_b: 0

将上述launch文件放入在ROS2项目的src源码文件夹下的指定功能包后,采用colcon build进行编译该功能包,然后采用**ros2 launch packages_name launch.py命令启动该launch文件进行批量启动多个节点**。ros2 run packages_name node_name命令是启动单个节点。

2.2.3 TF坐标变换

​ 将某个部件获取的坐标距离转化为其他部件的坐标距离位置,可以用于管理机器人部件间相对位置(如雷达→车体→摄像头),支持多机器人编队的位置关系维护,可以通过RViz可视化坐标系树状结构。

2.2.4 rviz2三维可视化工具

​ ROS2内置了三维可视化工具rviz2,它可以图形化的方式显示机器人模型或显示机器人系统中的一些抽象数据。

3. ROS2应用方向

  • NAV2

    Nav2项目继承自ROS Navigation Stack。该项目旨在可以让移动机器人从A点安全的移动到B点。它也可以应用于涉及机器人导航的其他应用,例如跟随动态点。Nav2将用于实现路径规划、运动控制、动态避障和恢复行为等一系列功能。

  • OpenCV

    OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。OpenCV旨在为计算机视觉应用程序提供通用基础架构,并加速机器感知在商业产品中的使用。OpenCV允许企业轻松地使用和修改代码。

  • MoveIt

    MoveIt是一组ROS软件包,主要包含运动规划、碰撞检测、运动学、3D感知、操作控制等功能。它可以用于构建机械臂的高级行为。MoveIt现在可以用于市面上的大多数机械臂,并被许多大公司使用。

  • The Autoware Foundation

    Autoware Foundation是ROS下属的非营利组织,支持实现自动驾驶的开源项目。Autoware基金会在企业发展和学术研究之间创造协同效应,为每个人提供自动驾驶技术

  • F1 Tenth

    F1 Tenth是将模型车改为无人车的竞速赛事,是一个由研究人员、工程师和自主系统爱好者组成的国际社区。它最初于 2016 年在宾夕法尼亚大学成立,但后来扩展到全球许多其他机构。

  • microROS

    在基于ROS的机器人应用中,micro-ROS正在弥合性能有限的微控制器和一般处理器之间的差距。micro-ROS在各种嵌入式硬件上运行,使ROS能直接应用于机器人硬件。

  • Open Robotics

    Open Robotics与全球ROS社区合作,为机器人创建开放的软件和硬件平台,包括 ROS1、ROS2、Gazebo模拟器和Ignition模拟器。Open Robotics使用这些平台解决一些重要问题,并通过为各种客户组织提供软件和硬件开发服务来帮助其他人做同样的事情。

  • PX4

    PX4是一款用于无人机和其他无人驾驶车辆的开源飞行控制软件。该项目为无人机开发人员提供了一套灵活的工具,用于共享技术并为无人机应用程序创建量身定制解决方案。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐