ROS2高效学习第四章 -- ros2 topic 编程之自定义 msg

ros2 topic 编程之自定义 msg

  • 1 前言和资料
  • 2 正文
    • 2.1 两种自定义 msg 方式的讨论
    • 2.2 自定义 msg 独立存在
      • 2.2.1 自定义 msg 包(diy_interface)
      • 2.2.2 pubsub_cpp 收发自定义 msg
      • 2.2.3 pubsub_py 收发自定义 msg
    • 2.3 自定义 msg 放在模块包里(pubsub_mix )
  • 总结

1 前言和资料

本文是 ros2 topic 编程第二篇,讲解自定义消息,也是第一篇ROS2高效学习第四章 – ros2 topic 编程之收发 string 并使用 ros2 launch的延续。我们将复用第一篇创建的两个软件包,即 pubsub_cpp 和 pubsub_py,在此基础上开发自定义消息样例。
本文参考资料如下:
(1)Custom-ROS2-Interfaces
(2)Single-Package-Define-And-Use-Interface

2 正文

2.1 两种自定义 msg 方式的讨论

(1)自定义 msg:所谓自定义msg,就是用户根据需求自己定义的消息结构体,用于 topic 收发,比如用户定义了描述 student 信息的 msg。自定义的 msg 不属于 ros2 官方提供的,但可以依赖 ros2 官方 msg,后面的样例将对此举例。
(2)自定义 msg 的两种方式:
第一种:在大型系统中,一般都是将 msg 或者叫通信接口(interface)独立成包,独立维护,并作为上下游节点的依赖模块存在。这对于整个系统模块间的松耦合非常重要,这种方式也是 ros2 推荐的方式。
第二种:当软件规模比较小的时候,比如收发节点都在一个软件包里,直接把自定义 msg 放在一起,肯定更加方便。我们的 ros1 系列博客ROS高效入门系列基本都采用这种方式。
(3)自定义 msg 放在模块包里引发的思考:
在ROS2高效学习第三章 – 梳理 ros 编译工具,开始 ros2 编程,第一个 hello ros2 样例这篇博客里,我们讨论了 ros2 的两种软件包的构建区别,一个是纯 cpp,构建类型是 ament_cmake ;另一个是纯 python,构建类型是 ament_python 。
针对用户自定义 msg,ros2 要求必须使用 ament_cmake 构建类型。如果用户想混用 cpp 和 python,比如发送节点是 cpp,接受节点是 python,怎么办?
解决办法是:构建类型选 ament_cmake ,并使用 ros2 提供的 ament_cmake_python 把 python 程序安装出来。这也是 ros2 支持 cpp 和 python 混合编程的唯一方式。

2.2 自定义 msg 独立存在

2.2.1 自定义 msg 包(diy_interface)

(1)创建 diy_interface 软件包和相关文件

cd ~/colcon_ws/src
ros2 pkg create --build-type ament_cmake  --license Apache-2.0 diy_interface
cd diy_interface
mkdir msg
touch msg/Student.msg msg/Sphere.msg

(2)编写 Student.msg

string name
uint8 age

(3)编写 Sphere.msg

geometry_msgs/Point center	# 依赖 ros2 官方的 geometry_msgs/Point
float64 radius

(4)编写 CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(diy_interface)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(geometry_msgs REQUIRED)
// rosidl_default_generators 必须加
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}"msg/Student.msg""msg/Sphere.msg"DEPENDENCIES geometry_msgs
)
ament_package()

(5)添加 package.xml

  <depend>geometry_msgs</depend>// 定义 msg , 这三个是刚需<buildtool_depend>rosidl_default_generators</buildtool_depend><exec_depend>rosidl_default_runtime</exec_depend><member_of_group>rosidl_interface_packages</member_of_group>

(6)编译并测试

~/colcon_ws
colcon build --packages-select diy_interface
source install/local_setup.bash
ros2 interface show diy_interface/msg/Student
ros2 interface show diy_interface/msg/Sphere

在这里插入图片描述

2.2.2 pubsub_cpp 收发自定义 msg

(1)创建新的 cpp 和 launch 文件

cd ~/colcon_ws/src/pubsub_cpp
touch launch/pubsub_diy_msg_launch.py
touch src/pub_diy_msg.cpp src/sub_diy_msg.cpp

(2)编写 pub_diy_msg.cpp

#include <chrono>
#include <memory>#include "rclcpp/rclcpp.hpp"
#include "diy_interface/msg/student.hpp"
#include "diy_interface/msg/sphere.hpp"class Publisher : public rclcpp::Node 
{
public:Publisher() : Node("test_pub_diy_msg"), count_(0) {pub_student_ = this->create_publisher<diy_interface::msg::Student>("student_topic", 10);pub_sphere_ = this->create_publisher<diy_interface::msg::Sphere>("sphere_topic", 10);timer_ = this->create_wall_timer(std::chrono::seconds(1), std::bind(&Publisher::timer_callback, this));}private:void timer_callback() {auto stu_msg = diy_interface::msg::Student();stu_msg.name = students_[count_ % students_.size()].first;stu_msg.age = students_[count_ % students_.size()].second;RCLCPP_INFO(this->get_logger(), "publishing student in cpp: %s, %d", stu_msg.name.c_str(), stu_msg.age);pub_student_->publish(stu_msg);auto sphere_msg = diy_interface::msg::Sphere();sphere_msg.center.x = std::get<0>(spheres_[count_ % spheres_.size()].first);sphere_msg.center.y = std::get<1>(spheres_[count_ % spheres_.size()].first);sphere_msg.center.z = std::get<2>(spheres_[count_ % spheres_.size()].first);sphere_msg.radius = spheres_[count_ % spheres_.size()].second;RCLCPP_INFO(this->get_logger(), "publishing sphere in cpp: (%f, %f, %f), %f", sphere_msg.center.x, sphere_msg.center.y, sphere_msg.center.z, sphere_msg.radius);pub_sphere_->publish(sphere_msg);count_++;}private:rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<diy_interface::msg::Student>::SharedPtr pub_student_;rclcpp::Publisher<diy_interface::msg::Sphere>::SharedPtr pub_sphere_;size_t count_;std::vector<std::pair<std::string, int>> students_ = {{"yi", 32}, {"miao", 18}, {"bao", 3}};std::vector<std::pair<std::tuple<float, float, float>, float>> spheres_ = {{{1.0f, 2.0f, 3.0f}, 4.0f}, {{1.1f, 2.1f, 3.1f}, 4.1f}};
};int main(int argc, char * argv[]) {rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<Publisher>());rclcpp::shutdown();return 0;
}

(3)编写 sub_diy_msg.cpp

#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "diy_interface/msg/student.hpp"
#include "diy_interface/msg/sphere.hpp"class Subscriber : public rclcpp::Node 
{
public:Subscriber() : Node("test_sub_diy_msg") {sub_student_ = this->create_subscription<diy_interface::msg::Student>("student_topic", 10, std::bind(&Subscriber::student_topic_callback, this, std::placeholders::_1));sub_sphere_ = this->create_subscription<diy_interface::msg::Sphere>("sphere_topic", 10, std::bind(&Subscriber::sphere_topic_callback, this, std::placeholders::_1));}private:void student_topic_callback(const diy_interface::msg::Student &msg) const {RCLCPP_INFO(this->get_logger(), "i received student in cpp: %s, %d", msg.name.c_str(), msg.age);}void sphere_topic_callback(const diy_interface::msg::Sphere &msg) const {RCLCPP_INFO(this->get_logger(), "i received sphere in cpp: (%f, %f, %f), %f", msg.center.x, msg.center.y, msg.center.z, msg.radius);}private:rclcpp::Subscription<diy_interface::msg::Student>::SharedPtr sub_student_;rclcpp::Subscription<diy_interface::msg::Sphere>::SharedPtr sub_sphere_;
};int main(int argc, char * argv[]) {rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<Subscriber>());rclcpp::shutdown();return 0;
}

(4)编写 pubsub_diy_msg_launch.py

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='pubsub_cpp',namespace='cpp',executable='talker_diy',name='talker_diy'),Node(package='pubsub_cpp',namespace='cpp',executable='listener_diy',name='listener_diy')])

(5)添加 CMakeLists.txt

find_package(diy_interface REQUIRED)
add_executable(talker_diy src/pub_diy_msg.cpp)
ament_target_dependencies(talker_diy rclcpp diy_interface)
add_executable(listener_diy src/sub_diy_msg.cpp)
ament_target_dependencies(listener_diy rclcpp diy_interface)
install(TARGETStalkerlistenertalker_diylistener_diyDESTINATION lib/${PROJECT_NAME})

(6)添加 package.xml

  <depend>diy_interface</depend>

(7)编译并运行

~/colcon_ws
colcon build --packages-select diy_interface pubsub_cpp
source install/local_setup.bash
ros2 launch pubsub_cpp pubsub_diy_msg_launch.py

在这里插入图片描述

2.2.3 pubsub_py 收发自定义 msg

(1)创建新的 python 和 launch 文件

cd ~/colcon_ws/src/pubsub_py
touch launch/pubsub_diy_msg_launch.py
touch pubsub_py/pub_diy_msg.py pubsub_py/sub_diy_msg.py

(2)编写 pub_diy_msg.py

#! /usr/bin/env python3
# -*- coding: utf-8 -*-import rclpy
from rclpy.node import Nodefrom diy_interface.msg import Student
from diy_interface.msg import Sphereclass Publisher(Node):def __init__(self):super().__init__('test_pub_diy_msg')self._pub_student = self.create_publisher(Student, "student_topic", 10)self._pub_sphere = self.create_publisher(Sphere, "Sphere_topic", 10)self._timer = self.create_timer(0.5, self.timer_callback)self._i = 0self._students = [("yi", 32),("miao", 18),("bao", 3)]self._spheres = [((1.0, 2.0, 3.0), 4.0),((1.1, 2.1, 3.1), 4.1)]def timer_callback(self):stu_msg = Student()stu_msg.name = self._students[self._i % len(self._students)][0]stu_msg.age = self._students[self._i % len(self._students)][1]self.get_logger().info("Publishing student in python: {0}, {1}".format(stu_msg.name, stu_msg.age))self._pub_student.publish(stu_msg)sph_msg = Sphere()sph_msg.center.x = self._spheres[self._i % len(self._spheres)][0][0]sph_msg.center.y = self._spheres[self._i % len(self._spheres)][0][1]sph_msg.center.z = self._spheres[self._i % len(self._spheres)][0][2]sph_msg.radius = self._spheres[self._i % len(self._spheres)][1]self.get_logger().info("Publishing sphere in python: ({0}, {1}, {2}), {3}".format(sph_msg.center.x, sph_msg.center.y, sph_msg.center.z, sph_msg.radius))self._pub_sphere.publish(sph_msg)self._i += 1def main(args=None):rclpy.init(args=args)pub_node = Publisher()rclpy.spin(pub_node)pub_node.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

(3)编写 sub_diy_msg.py

#! /usr/bin/env python3
# -*- coding: utf-8 -*-import rclpy
from rclpy.node import Nodefrom diy_interface.msg import Student
from diy_interface.msg import Sphereclass Subscriber(Node):def __init__(self):super().__init__('test_sub_diy_msg')self._sub_student = self.create_subscription(Student, "student_topic", self.student_topic_callback, 10)self._sub_sphere = self.create_subscription(Sphere, "sphere_topic", self.sphere_topic_callback, 10)def student_topic_callback(self, msg):self.get_logger().info("i received student in python: {0}, {1}".format(msg.name, msg.age))def sphere_topic_callback(self, msg):self.get_logger().info("i received sphere in python: ({0}, {1}, {2}), {3}".format(msg.center.x, msg.center.y, msg.center.z, msg.radius))def main(args=None):rclpy.init(args=args)sub_node = Subscriber()rclpy.spin(sub_node)sub_node.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

(4)编写 pubsub_diy_msg_launch.py

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='pubsub_py',namespace='python',executable='talker_diy',name='talker_diy'),Node(package='pubsub_py',namespace='python',executable='listener_diy',name='listener_diy')])

(5)添加 package.xml

  <exec_depend>diy_interfaces</exec_depend>

(6)添加 setup.py

    entry_points={'console_scripts': ['talker = pubsub_py.publisher:main','talker_diy = pubsub_py.pub_diy_msg:main','listener = pubsub_py.subscriber:main','listener_diy = pubsub_py.sub_diy_msg:main'],},

(7)编译并运行

~/colcon_ws
colcon build --packages-select diy_interface pubsub_py
source install/local_setup.bash
ros2 launch pubsub_py pubsub_diy_msg_launch.py

在这里插入图片描述

2.3 自定义 msg 放在模块包里(pubsub_mix )

(1)创建 pubsub_mix 软件包和相关文件

cd ~/colcon_ws/src
ros2 pkg create --build-type ament_cmake  --license Apache-2.0 pubsub_mix
cd pubsub_mix
mkdir launch msg scripts
touch launch/pubsub_mix_launch.py
touch msg/AddressBook.msg
touch src/publish_address_book.cpp scripts/subscribe_address_book.py

(2)编写 publish_address_book.cpp

#include <chrono>
#include <functional>
#include <memory>
#include <string>#include "rclcpp/rclcpp.hpp"
#include "pubsub_mix/msg/address_book.hpp"class Publisher : public rclcpp::Node 
{
public:Publisher() : Node("address_book_publisher"), count_(0) {publisher_ = this->create_publisher<pubsub_mix::msg::AddressBook>("address_book", 10);timer_ = this->create_wall_timer(std::chrono::seconds(1), std::bind(&Publisher::timer_callback, this));}private:void timer_callback() {auto msg = pubsub_mix::msg::AddressBook();msg.first_name = "yi";msg.last_name = "cao";msg.phone_number = "123456789";msg.phone_type = msg.PHONE_TYPE_MOBILE;RCLCPP_INFO(this->get_logger(), "publishing in cpp: %s %s %s %d", msg.first_name.c_str(), msg.last_name.c_str(), msg.phone_number.c_str(), msg.phone_type);publisher_->publish(msg);}private:rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<pubsub_mix::msg::AddressBook>::SharedPtr publisher_;size_t count_;
};int main(int argc, char * argv[]) {rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<Publisher>());rclcpp::shutdown();return 0;
}

(3)编写 subscribe_address_book.py

#! /usr/bin/env python3
# -*- coding: utf-8 -*-import rclpy
from rclpy.node import Node
from pubsub_mix.msg import AddressBookclass Subscriber(Node):def __init__(self):super().__init__('address_book_subscriber')self._subscriber = self.create_subscription(AddressBook, "address_book", self.topic_callback, 10)def topic_callback(self, msg):self.get_logger().info("subscribe in python: {0}, {1}, {2}, {3}".format(msg.first_name, msg.last_name, msg.phone_number, msg.phone_type))def main(args=None):rclpy.init(args=args)sub_node = Subscriber()rclpy.spin(sub_node)sub_node.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()

(4)编写 AddressBook.msg

uint8 PHONE_TYPE_HOME=0
uint8 PHONE_TYPE_WORK=1
uint8 PHONE_TYPE_MOBILE=2string first_name
string last_name
string phone_number
uint8 phone_type

(5)编写 CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(pubsub_mix)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(rosidl_default_generators REQUIRED)
find_package(rclcpp REQUIRED)
find_package(ament_cmake_python REQUIRED)
// 生成自定义消息结构体
set(msg_files"msg/AddressBook.msg"
)
rosidl_generate_interfaces(${PROJECT_NAME}${msg_files}
)
// 申明自定义消息运行环境依赖
ament_export_dependencies(rosidl_default_runtime)add_executable(publish_address_book src/publish_address_book.cpp)
ament_target_dependencies(publish_address_book rclcpp)
// 因为自定义消息在软件包里,这句就要加
rosidl_get_typesupport_target(cpp_typesupport_target${PROJECT_NAME} rosidl_typesupport_cpp)
target_link_libraries(publish_address_book "${cpp_typesupport_target}")install(TARGETSpublish_address_bookDESTINATION lib/${PROJECT_NAME})install(DIRECTORYlaunchDESTINATION share/${PROJECT_NAME}
)
// 使用install把python程序安装出来
install(PROGRAMSscripts/subscribe_address_book.pyDESTINATION lib/${PROJECT_NAME}
)
ament_package()

(6)添加 package.xml

  <depend>ament_cmake_python</depend><buildtool_depend>rosidl_default_generators</buildtool_depend><exec_depend>rosidl_default_runtime</exec_depend><member_of_group>rosidl_interface_packages</member_of_group>

(7)编写 pubsub_mix_launch.py

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='pubsub_mix',namespace='mix',executable='publish_address_book',name='publish_address_book'),Node(package='pubsub_mix',namespace='mix',executable='subscribe_address_book.py',name='subscribe_address_book')])

(8)编译并运行

~/colcon_ws
colcon build --packages-select pubsub_mix
source install/local_setup.bash
ros2 launch pubsub_mix pubsub_mix_launch.py

在这里插入图片描述

总结

本文的代码托管在本人的github上:pubsub_cpp,pubsub_py,pubsub_mix

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2809030.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

逻辑思维1000题丨【Exercise 1】解析

目录 声明 解析 声明 解析网上是搜不到的&#xff0c;100%原创。本专栏只会讲解重难点题目&#xff0c;简单题目不做讲解。 解析 2.What is the missing number? 1 12 13 124 15 1236 17 1248 139 12510 111 1234612 113 12714 13515 &#xff1f; 观察每个数字的末尾分别是…

Redis高并发分布锁实战

Redis高并发分布锁实战 问题场景 场景一: 没有捕获异常 // 仅仅加锁 // 读取 stock15 Boolean ret stringRedisTemplate.opsForValue().setIfAbsent("lock_key", "1"); // jedis.setnx(k,v) // TODO 业务代码 stock-- stringRedisTemplate.delete(&quo…

HarmonyOS服务卡片开发指导(Stage模型)概述

服务卡片概述 服务卡片&#xff08;以下简称“卡片”&#xff09;是一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到卡片&#xff0c;以达到服务直达、减少体验层级的目的。卡片常用于嵌入到其他应用&#xff08;当前卡片使用方只支持系统应用&#xff0c;如桌…

Android Gradle 开发与应用 (一) : Gradle基础

1. Gradle是什么 Gradle是一个通用的构建工具&#xff0c;支持诸多主要的 IDE&#xff0c;包括 Android Studio、IntelliJ IDEA、Visual Studio 等 Gradle 的底层实现(核心引擎和框架)其实是用 Java 编写的开发者通常使用 Groovy 或 Kotlin 来编写构建脚本 1.1 那么为什么Gra…

你真的了解@Async吗?

你真的了解Async吗&#xff1f; 使用场景&#xff1a; 开发中会碰到一些耗时较长或者不需要立即得到执行结果的逻辑&#xff0c;比如消息推送、商品同步等都可以使用异步方法&#xff0c;这时我们可以用到Async。但是直接使用 Async 会有风险&#xff0c;当我们没有指定线程池…

速度提高100倍 - 扩展 RAG 应用程序,以实现数十亿个嵌入,并行计算余弦相似度

原文链接&#xff1a;100x Faster — Scaling Your RAG App for Billions of Embeddings 2024 年 2 月 15 日 RAG应用程序最大的问题之一是它们的计算检索时间。想象一下&#xff0c;你有一个向量数据库&#xff0c;包含一万亿条Embedding向量的记录。当您尝试将用户查询与一…

数字化转型导师坚鹏:政府数字化转型智慧城市类案例研究

政府数字化转型智慧城市类案例研究 课程背景&#xff1a; 很多地方政府存在以下问题&#xff1a; 不清楚政府数字化转型的智慧城市类成功案例 不清楚政府数字化转型的城市大脑类成功案例 不清楚政府数字化转型的综合实践类成功案例 课程特色&#xff1a; 针对性强 …

LDRA Testbed软件静态分析_软件质量度量

系列文章目录 LDRA Testbed软件静态分析_操作指南 LDRA Testbed软件静态分析_自动提取静态分析数据生成文档 LDRA Testbed软件静态分析_Jenkins持续集成_(1)自动进行静态分析的环境搭建 LDRA Testbed软件静态分析_Jenkins持续集成_(2)配置邮件自动发送静态分析结果 LDRA Testb…

LeetCode--代码详解 236. 二叉树的最近公共祖先

236. 二叉树的最近公共祖先 题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&am…

python 循环语句 while 循环

while循环 Python 编程中 while 语句用于循环执行程序&#xff0c;即在某条件下&#xff0c;循环执行某段程序&#xff0c;以处理需要重复处理的相同任务。其基本形式为&#xff1a; while 判断条件(condition)&#xff1a; 执行语句(statements)…… 执行语句可以是单个语句…

遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

【数据结构】周末作业

1.new(struct list_head*)malloc(sizeof(struct list_head*)); if(newNULL) { printf("失败\n"); return; } new->nextprev->next; prev->nextnew; return; 2.struct list_head* pprev->next; prev->nextp->next; p->next->prevpr…

Oracle conn / as sysdba遇到ORA-01031: insufficient privileges错误

背景 oracle 突然挂了&#xff0c;处于锁定状态&#xff0c;然后打算重新启动一下子。 遂 sqlplus /nolog conn / as sysdba 然后就出现了以下错误。。 ORA-01031: insufficient privileges 1.查了一圈&#xff0c;有说是 计算机 》 管理》本地用户和组》组》ORA_DBA&am…

python 3.11中安装sympy(符号工具包)

1.python环境&#xff1a; 2.安装遇到问题&#xff1a; … 3.升级pip cmd命令行中&#xff0c;执行如下命令&#xff1a; python.exe -m pip installl --upgrade pip 4.再次安装sympy cmd命令行中&#xff0c;执行如下命令&#xff1a; pip install sympy 5.简单应用 对…

kuka示教器嵌套UR界面操作ros中rviz的UR机器人

摘要 本例展示了用QT增加一个网页视图&#xff0c;背景是kuka示教器界面&#xff0c;中间增加UR的VNC网页界面显示。本人博客中一起有写过ros2运行UR的操作。 ros2 UR10仿真包运行_基于ros的ur仿真-CSDN博客 效果如下&#xff1a; 1.打开UR机器人的ros2仿真文件 sudo su ros2…

杀疯啦!yolov9+bytetrack的目标跟踪实现

目录 YOLOV9介绍 bytetrack介绍&#xff1a; yolov9结合bytetrack实现目标跟踪 效果展示 训练与预测 UI设计 其他功能展示 完整代码实现UI界面 此次yolov9bytetrack不论是准确率还是稳定性&#xff0c;都超越了之前的yolobytetrack系列。 YOLOV9介绍 在目标检测…

Mysql5.7主从复制搭建

注意不适用Mysql8 Docker搭建Mysql主从复制 docker run -p 3307:3306 --name mysql-master \ -v /usr/local/develop/mysql-master/log:/var/log/mysql \ -v /usr/local/develop/mysql-master/data:/var/lib/mysql \ -v /usr/local/develop/mysql-master/conf:/etc/mysql/con…

个人健康|个人健康管理小程序|基于微信小程序的个人健康管理系统设计与实现(源码+数据库+文档)

个人健康管理小程序目录 目录 基于微信小程序的个人健康管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、微信小程序前台 2、管理员后台 &#xff08;1&#xff09;用户信息管理 &#xff08;2&#xff09;运动教程管理 &#xff08;3&#xff09;公告…

JAVA毕业设计129—基于Java+Springboot+thymeleaf的物业管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootthymeleaf的物业管理系统(源代码数据库)129 一、系统介绍 本项目前后端分离&#xff0c;本系统分为管理员、小区管理员、用户三种角色 1、用户&#xff1a; 登…

2024最新互联网大厂面试题,(java,python,vue)

最近又赶上跳槽的高峰期&#xff0c;好多粉丝&#xff0c;都问我要有没有最新面试题&#xff0c;索性&#xff0c;我就把我看过的和我面试中的真题&#xff0c;及答案都整理好&#xff0c;整理了《第3版&#xff1a;互联网大厂面试题》并分类150份 PDF&#xff0c;累计 7701页&…