【ROS2实操一】话题通信与自定义消息

news2024/10/24 23:16:18

一、准备工作

1.请先创建工作空间

mkdir -p ws01_plumbing/src      //创建工作空间
colcon build                    //在工作空间目录下编译

2.创建专门的接口功能包定义接口文件(需要注意的是,目前为止无法在Python功能包中定义接口文件),终端下进入工作空间的src目录,执行如下命令:

ros2 pkg create --build-type ament_cmake base_interfaces_demo    //该功能包将用于保存自定义的接口文件

3.终端下进入工作空间的src目录,调用如下两条命令分别创建C++功能包和Python功能包。

ros2 pkg create cpp01_topic --build-type ament_cmake --dependencies rclcpp std_msgs base_interfaces_demo
ros2 pkg create py01_topic --build-type ament_python --dependencies rclpy std_msgs base_interfaces_demo

 二、话题通信之原生消息(C++)

1.发布方实现

        功能包cpp01_topic的src目录下,新建C++文件demo01_talker_str.cpp.

/*  
  需求:以某个固定频率发送文本“hello world!”,文本后缀编号,每发送一条消息,编号递增1。
  步骤:
    1.包含头文件;
    2.初始化 ROS2 客户端;
    3.定义节点类;
      3-1.创建发布方;
      3-2.创建定时器;
      3-3.组织消息并发布。
    4.调用spin函数,并传入节点对象指针;
    5.释放资源。
*/

// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

// 3.定义节点类;
class MinimalPublisher : public rclcpp::Node
{
  public:
    MinimalPublisher()
    : Node("minimal_publisher"), count_(0)
    {
      // 3-1.创建发布方;
      publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
      // 3-2.创建定时器;
      timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    void timer_callback()
    {
      // 3-3.组织消息并发布。
      auto message = std_msgs::msg::String();
      message.data = "Hello, world! " + std::to_string(count_++);
      RCLCPP_INFO(this->get_logger(), "发布的消息:'%s'", message.data.c_str());
      publisher_->publish(message);
    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;
};

int main(int argc, char * argv[])
{
  // 2.初始化 ROS2 客户端;
  rclcpp::init(argc, argv);
  // 4.调用spin函数,并传入节点对象指针。
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  // 5.释放资源;
  rclcpp::shutdown();
  return 0;
}

2.订阅方实现

        功能包cpp01_topic的src目录下,新建C++文件demo02_listener_str.cpp.

/*  
    需求:订阅发布方发布的消息,并输出到终端。
    步骤:
        1.包含头文件;
        2.初始化 ROS2 客户端;
        3.定义节点类;
            3-1.创建订阅方;
            3-2.处理订阅到的消息。
        4.调用spin函数,并传入节点对象指针;
        5.释放资源。
*/

// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;

// 3.定义节点类;
class MinimalSubscriber : public rclcpp::Node
{
  public:
    MinimalSubscriber()
    : Node("minimal_subscriber")
    {
      // 3-1.创建订阅方;
      subscription_ = this->create_subscription<std_msgs::msg::String>("topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

  private:
    // 3-2.处理订阅到的消息;
    void topic_callback(const std_msgs::msg::String & msg) const
    {
      RCLCPP_INFO(this->get_logger(), "订阅的消息: '%s'", msg.data.c_str());
    }
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  // 2.初始化 ROS2 客户端;
  rclcpp::init(argc, argv);
  // 4.调用spin函数,并传入节点对象指针。
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  // 5.释放资源;
  rclcpp::shutdown();
  return 0;
}

3.编辑配置文件

        在C++功能包中,配置文件主要关注package.xml与CMakeLists.txt。

        1.package.xml

        在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:

<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>base_interfaces_demo</depend>    //在本案例中不是必须的
        2.CMakeLists.txt

        CMakeLists.txt中发布和订阅程序核心配置如下:

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(base_interfaces_demo REQUIRED)

add_executable(demo01_talker_str src/demo01_talker_str.cpp)
ament_target_dependencies(
  demo01_talker_str
  "rclcpp"
  "std_msgs"
)

add_executable(demo02_listener_str src/demo02_listener_str.cpp)
ament_target_dependencies(
  demo02_listener_str
  "rclcpp"
  "std_msgs"
)

install(TARGETS 
  demo01_talker_str
  demo02_listener_str
  DESTINATION lib/${PROJECT_NAME})

4.编译

        终端中进入当前工作空间,编译功能包:

colcon build --packages-select cpp01_topic

5.执行

        当前工作空间下,启动两个终端,终端1执行发布程序,终端2执行订阅程序。

        终端1输入如下指令:

. install/setup.bash
ros2 run cpp01_topic demo01_talker_str

        终端2输入如下指令:

. install/setup.bash 
ros2 run cpp01_topic demo02_listener_str

三、话题通信之原生消息(Python) 

1.发布方实现

        功能包py01_topic的py01_topic目录下,新建Python文件demo01_talker_str_py.py.

"""  
    需求:以某个固定频率发送文本“hello world!”,文本后缀编号,每发送一条消息,编号递增1。
    步骤:
        1.导包;
        2.初始化 ROS2 客户端;
        3.定义节点类;
            3-1.创建发布方;
            3-2.创建定时器;
            3-3.组织消息并发布。
        4.调用spin函数,并传入节点对象;
        5.释放资源。
"""
# 1.导包;
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

# 3.定义节点类;
class MinimalPublisher(Node):

    def __init__(self):
        super().__init__('minimal_publisher_py')
        # 3-1.创建发布方;
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        # 3-2.创建定时器;
        timer_period = 0.5 
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0

    # 3-3.组织消息并发布。
    def timer_callback(self):
        msg = String()
        msg.data = 'Hello World(py): %d' % self.i
        self.publisher_.publish(msg)
        self.get_logger().info('发布的消息: "%s"' % msg.data)
        self.i += 1

def main(args=None):
    # 2.初始化 ROS2 客户端;
    rclpy.init(args=args)
    # 4.调用spin函数,并传入节点对象;
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    # 5.释放资源。
    rclpy.shutdown()

if __name__ == '__main__':
    main()

2.订阅方实现

        功能包py01_topic的py01_topic目录下,新建Python文件demo02_listener_str_py.py.

"""  
    需求:订阅发布方发布的消息,并输出到终端。
    步骤:
        1.导包;
        2.初始化 ROS2 客户端;
        3.定义节点类;
            3-1.创建订阅方;
            3-2.处理订阅到的消息。
        4.调用spin函数,并传入节点对象;
        5.释放资源。
"""
# 1.导包;
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

# 3.定义节点类;
class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__('minimal_subscriber_py')
        # 3-1.创建订阅方;
        self.subscription = self.create_subscription(
            String,
            'topic',
            self.listener_callback,
            10)
        self.subscription  

    # 3-2.处理订阅到的消息。
    def listener_callback(self, msg):
        self.get_logger().info('订阅的消息: "%s"' % msg.data)

def main(args=None):
    # 2.初始化 ROS2 客户端;
    rclpy.init(args=args)

    # 4.调用spin函数,并传入节点对象;
    minimal_subscriber = MinimalSubscriber()
    rclpy.spin(minimal_subscriber)

    # 5.释放资源。
    rclpy.shutdown()

if __name__ == '__main__':
    main()

3.编辑配置文件

        在Python功能包中,配置文件主要关注package.xml与setup.py。

        1.package.xml

        在创建功能包时,所依赖的功能包已经自动配置了,配置内容如下:

<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>base_interfaces_demo</depend>
        2.setup.py

  entry_points字段的console_scripts中添加如下内容:

entry_points={
    'console_scripts': [
        'demo01_talker_str_py = py01_topic.demo01_talker_str_py:main',
        'demo02_listener_str_py = py01_topic.demo02_listener_str_py:main'
    ],
},

4.编译

        终端中进入当前工作空间,编译功能包:

colcon build --packages-select py01_topic

5.执行

        当前工作空间下,启动两个终端,终端1执行发布程序,终端2执行订阅程序。

        终端1输入如下指令:

. install/setup.bash
ros2 run py01_topic demo01_talker_str_py

        终端2输入如下指令:

. install/setup.bash 
ros2 run py01_topic demo02_listener_str_py

四、话题通信自定义接口消息

        自定义接口消息的流程与在功能包中编写可执行程序的流程类似,主要步骤如下:

1.创建并编辑 .msg文件;

2.编辑配置文件;

3.编译;

4.测试。

接下来,我们可以自定义一个文件,该文件中包含学生的姓名、年龄、身高等字段。

1.创建并编辑 .msg 文件

        功能包base_interfaces_demo下新建 msg 文件夹,msg文件夹下新建Student.msg文件

string   name
int32    age
float64  height

2.编辑配置文件

        1.package.xml文件

        在package.xml中需要添加一些依赖包,具体内容如下:

<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
        2.CMakeLists.txt文件

        为了将.msg文件转换成对应的C++和Python代码,还需要在CMakeLists.txt中添加如下配置:

find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Student.msg"
)

3.编译

        终端中进入当前工作空间,编译功能包:

colcon build --packages-select base_interfaces_demo

4.测试

        编译完成之后,在工作空间下的install目录下将生成Student.msg文件对应的C++和Python文件,我们也可以在终端下进入工作空间,通过如下命令查看文件定义以及编译是否正常:

. install/setup.bash
ros2 interface show base_interfaces_demo/msg/Student

正常情况下,终端将会输出与Student.msg文件一致的内容。

五、话题通信之自定义消息(C++)

        准备工作

        C++文件中包含自定义消息相关头文件时,可能会抛出异常,可以配置VSCode中c_cpp_properties.json文件,在文件中的 includePath属性下添加一行:

"${workspaceFolder}/install/base_interfaces_demo/include/**"

添加完毕后,包含相关头文件时,就不会抛出异常了,其他接口文件或接口包的使用也与此同理。

1.发布方实现

        功能包cpp01_topic的src目录下,新建C++文件demo01_talker_stu.cpp.

/*  
  需求:以某个固定频率发送文本学生信息,包含学生的姓名、年龄、身高等数据。
*/

// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces_demo/msg/student.hpp"

using namespace std::chrono_literals;
using base_interfaces_demo::msg::Student;
// 3.定义节点类;
class MinimalPublisher : public rclcpp::Node
{
  public:
    MinimalPublisher()
    : Node("student_publisher"), count_(0)
    {
      // 3-1.创建发布方;
      publisher_ = this->create_publisher<Student>("topic_stu", 10);
      // 3-2.创建定时器;
      timer_ = this->create_wall_timer(500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    void timer_callback()
    {
      // 3-3.组织消息并发布。
      auto stu = Student();
      stu.name = "张三";
      stu.age = count_++;
      stu.height = 1.65;
      RCLCPP_INFO(this->get_logger(), "学生信息:name=%s,age=%d,height=%.2f", stu.name.c_str(),stu.age,stu.height);
      publisher_->publish(stu);

    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<Student>::SharedPtr publisher_;
    size_t count_;
};

int main(int argc, char * argv[])
{
  // 2.初始化 ROS2 客户端;
  rclcpp::init(argc, argv);
  // 4.调用spin函数,并传入节点对象指针。
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  // 5.释放资源;
  rclcpp::shutdown();
  return 0;
}

2.订阅方实现

        功能包cpp01_topic的src目录下,新建C++文件demo04_listener_stu.cpp.

/*  
    需求:订阅发布方发布的学生消息,并输出到终端。
*/

// 1.包含头文件;
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces_demo/msg/student.hpp"

using std::placeholders::_1;
using base_interfaces_demo::msg::Student;
// 3.定义节点类;
class MinimalSubscriber : public rclcpp::Node
{
  public:
    MinimalSubscriber()
    : Node("student_subscriber")
    {
      // 3-1.创建订阅方;
      subscription_ = this->create_subscription<Student>("topic_stu", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

  private:
    // 3-2.处理订阅到的消息;
    void topic_callback(const Student & msg) const
    {
      RCLCPP_INFO(this->get_logger(), "订阅的学生消息:name=%s,age=%d,height=%.2f", msg.name.c_str(),msg.age, msg.height);
    }
    rclcpp::Subscription<Student>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  // 2.初始化 ROS2 客户端;
  rclcpp::init(argc, argv);
  // 4.调用spin函数,并传入节点对象指针。
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  // 5.释放资源;
  rclcpp::shutdown();
  return 0;
}

3.编辑配置文件

        package.xml无需修改,CMakeLists.txt文件需要添加如下内容:

add_executable(demo03_talker_stu src/demo03_talker_stu.cpp)
ament_target_dependencies(
  demo03_talker_stu
  "rclcpp"
  "std_msgs"
  "base_interfaces_demo"
)

add_executable(demo04_listener_stu src/demo04_listener_stu.cpp)
ament_target_dependencies(
  demo04_listener_stu
  "rclcpp"
  "std_msgs"
  "base_interfaces_demo"
)

        文件中install修改为如下内容:

install(TARGETS 
  demo01_talker_str
  demo02_listener_str
  demo03_talker_stu
  demo04_listener_stu
  DESTINATION lib/${PROJECT_NAME})

4.编译

        终端中进入当前工作空间,编译功能包:

colcon build --packages-select cpp01_topic

5.执行

        当前工作空间下,启动两个终端,终端1执行发布程序,终端2执行订阅程序。

        终端1输入如下指令:

. install/setup.bash
ros2 run cpp01_topic demo03_talker_stu

        终端2输入如下指令:

. install/setup.bash 
ros2 run cpp01_topic demo04_listener_stu

六、话题通信之自定义消息(Python)

        准备工作

        Python文件中导入自定义消息相关的包时,为了方便使用,可以配置VSCode中settings.json文件,在文件中的python.autoComplete.extraPaths和python.analysis.extraPaths属性下添加一行:

"${workspaceFolder}/install/base_interfaces_demo/local/lib/python3.10/dist-packages"

添加完毕后,代码可以高亮显示且可以自动补齐,其他接口文件或接口包的使用也与此同理。

1.发布方实现

        功能包py01_topic的py01_topic目录下,新建Python文件demo03_talker_stu_py.py.

"""  
    需求:以某个固定频率发送文本学生信息,包含学生的姓名、年龄、身高等数据。
"""
# 1.导包;
import rclpy
from rclpy.node import Node
from base_interfaces_demo.msg import Student

# 3.定义节点类;
class MinimalPublisher(Node):

    def __init__(self):
        super().__init__('stu_publisher_py')
        # 3-1.创建发布方;
        self.publisher_ = self.create_publisher(Student, 'topic_stu', 10)
        # 3-2.创建定时器;
        timer_period = 0.5 
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0

    # 3-3.组织消息并发布。
    def timer_callback(self):
        stu = Student()
        stu.name = "李四"
        stu.age = self.i
        stu.height = 1.70
        self.publisher_.publish(stu)
        self.get_logger().info('发布的学生消息(py): name=%s,age=%d,height=%.2f' % (stu.name, stu.age, stu.height))
        self.i += 1


def main(args=None):
    # 2.初始化 ROS2 客户端;
    rclpy.init(args=args)
    # 4.调用spin函数,并传入节点对象;
    minimal_publisher = MinimalPublisher()
    rclpy.spin(minimal_publisher)
    # 5.释放资源。
    rclpy.shutdown()


if __name__ == '__main__':
    main()

2.订阅方实现

        功能包py01_topic的py01_topic目录下,新建Python文件demo04_listener_stu_py.py.

"""  
    需求:订阅发布方发布的学生消息,并输出到终端。
"""

# 1.导包;
import rclpy
from rclpy.node import Node
from base_interfaces_demo.msg import Student

# 3.定义节点类;
class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__('stu_subscriber_py')
        # 3-1.创建订阅方;
        self.subscription = self.create_subscription(
            Student,
            'topic_stu',
            self.listener_callback,
            10)
        self.subscription  

    # 3-2.处理订阅到的消息。
    def listener_callback(self, stu):
        self.get_logger().info('订阅的消息(py): name=%s,age=%d,height=%.2f' % (stu.name, stu.age, stu.height))


def main(args=None):
    # 2.初始化 ROS2 客户端;
    rclpy.init(args=args)

    # 4.调用spin函数,并传入节点对象;
    minimal_subscriber = MinimalSubscriber()
    rclpy.spin(minimal_subscriber)

    # 5.释放资源。
    rclpy.shutdown()


if __name__ == '__main__':
    main()

3.编辑配置文件

        package.xml无需修改,需要修改setup.py文件,entry_points字段的console_scripts中修改为如下内容:

entry_points={
    'console_scripts': [
        'demo01_talker_str_py = py01_topic.demo01_talker_str_py:main',
        'demo02_listener_str_py = py01_topic.demo02_listener_str_py:main',
        'demo03_talker_stu_py = py01_topic.demo03_talker_stu_py:main',
        'demo04_listener_stu_py = py01_topic.demo04_listener_stu_py:main'
    ],
},

4.编译

        终端中进入当前工作空间,编译功能包:

colcon build --packages-select py01_topic

5.执行

        当前工作空间下,启动两个终端,终端1执行发布程序,终端2执行订阅程序。

        终端1输入如下指令:

. install/setup.bash
ros2 run py01_topic demo03_talker_stu_py

        终端2输入如下指令:

. install/setup.bash 
ros2 run py01_topic demo04_listener_stu_py

 下期服务通信见!

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

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

相关文章

线程基础学习

线程的实现 通过实现Runnable接口的方式&#xff0c;实现其中的run方法。继承Thread类&#xff0c;然后重写其中的run方法。通过线程池创建线程&#xff0c;默认采用DefaultThreadFactory。有返回值的callable&#xff0c;实现callable接口&#xff0c;实行call方法。 本质上…

wait和waitpid

在Linux中&#xff0c;wait 和 waitpid 是用于进程控制的系统调用&#xff0c;它们主要用来让父进程等待子进程的终止&#xff0c;并获取子进程的退出状态。下面详细介绍它们的用法和区别。 1. wait() 函数 wait() 会阻塞调用进程&#xff0c;直到一个子进程终止。它的典型用…

怎么ping网络ip地址通不通

怎么Ping网络IP地址通不通&#xff1f;要检查网络中的IP地址是否连通&#xff0c;可以使用‌Ping命令。Ping命令通过发送ICMP&#xff08;Internet Control Message Protocol&#xff0c;因特网控制消息协议&#xff09;Echo请求报文并等待回应&#xff0c;来判断目标主机是否可…

ARP限制网速攻击

ARP限制网速攻击 大家没想到吧&#xff0c;ARP还能限制对方网速。当kali欺骗了网关和受害者的时候&#xff0c;受害者访问网络就需要经过kali的网卡&#xff0c;那我们限制kali网卡的速度或者转发的速度就可以限制对方的网速。这里可以使用的工具有tc、iptables、WonderShaper…

Unix Standardization and Implementations

Unix标准化 在Unix未制定较为完备的标准时&#xff0c;各个平台的系统调用方式各异&#xff0c;所开发出的应用程序存在可移植性差的特点&#xff0c;因此人们呼吁指定一套Unix标准来规范接口&#xff0c;增加应用程序的可移植性。所谓Unix标准即适用于Unix环境下的一系列函数…

AI 时代技术盛宴 —— 稀土掘金 × 豆包 MarsCode 青训营等你来!

各位 CSDN 的小伙伴们&#xff0c;今天我要给大家带来一个超级棒的消息&#xff01;稀土掘金与豆包 MarsCode 强强联手&#xff0c;共同打造的青训营再次上线啦&#xff01; 在这个飞速发展的 AI 时代&#xff0c;这场青训营玩出了不一样的精彩。它携手 AI 伙伴豆包 MarsCode&…

一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景

文章目录 一、常用数据库概览1.1 关系型数据库1.2 非关系型数据库1.2.1 KV数据库1.2.2 文档型数据库1.2.3 列式存储数据库1.2.4 图数据库 1.3 SQL与NoSQL区别1.3.1 结构化与非结构化1.3.2 关联和非关联1.3.3 查询方式1.3.4 事务1.3.5 总结 二、MySQL三、PostgreSQL3.1 特点、适…

计组_中断响应条件

2024.10.13&#xff1a;计算机组成原理学习笔记 中断响应条件 条件1&#xff1a;CPU要处于开中断状态条件2&#xff1a;至少要有一个未被屏蔽的中断请求屏蔽&#xff1f;中断优先级屏蔽字的作用 条件3&#xff1a;当前指令刚执行完 条件1&#xff1a;CPU要处于开中断状态 当CP…

Redis:分布式 - 主从复制

Redis&#xff1a;分布式 - 主从复制 概念配置主从模式info replicationslave-read-onlytcp-nodelay 命令slaveof 主从结构一主一从一主多从 主从复制流程数据同步命令全量同步部分同步实时同步 节点晋升 概念 Redis的最佳应用&#xff0c;还是要在分布式系统中。对于非分布式…

如何解决 Vim 中的 “E212: Can‘t open file for writing“ 错误:从编辑到权限管理(sudo)

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

Squad战术小队开服教程

1、登录服务器&#xff08;百度莱卡云游戏面板&#xff09; 登录面板的信息在绿色的登陆面板按键下方&#xff0c;不是你的莱卡云账号 进入控制面板后会出现正在安装的界面&#xff0c;大约10分钟左右就能安装完成 2、设置 点击目录上的网络&#xff0c;你可以看到三个端口 然…

【Python】Twisted:让自定义网络应用开发变得简单

Twisted 是 Python 中一个成熟、功能强大的事件驱动网络编程框架。它支持多种协议&#xff0c;如 HTTP、FTP、SMTP 等&#xff0c;可以用于构建高性能的网络应用&#xff0c;包括网络服务器、客户端、代理服务器等。Twisted 的核心是基于事件驱动模型&#xff0c;能够有效处理大…

el-date-picker设置只有某些日期可选

示例图&#xff1a; <el-date-pickerv-model"topFormObj.upTime"type"date"value-format"timestamp"format"dd/MM/yyyy":picker-options"pickerOptions" /> 固定限制每周的周末周三不可选 data() {return {pickerOp…

Leetcode 乘积最大子数组

该算法的目的是求出一个整数数组中乘积最大的连续子数组。 算法思想&#xff1a; 问题分析&#xff1a; 我们需要在数组中找到连续的子数组&#xff0c;使得该子数组的乘积最大。这个问题类似于“最大子序和”&#xff0c;但乘积相比求和有更多的复杂性&#xff0c;特别是当数…

销售管理的五大职能

什么是销售管理 销售管理&#xff0c;这一看似简单的概念&#xff0c;实则蕴含着丰富的内涵与细致的操作。它不仅仅是对销售团队的监督和对客户满意度的追求&#xff0c;更是通过一系列策略和手段&#xff0c;优化销售流程&#xff0c;提升业务成果的过程。 销售管理的内核 …

electron本地OCR实现

使用tesseract.js - npm (npmjs.com) 官方demo&#xff1a;GitHub - Balearica/tesseract.js-electron: An example to use tesseract.js in electron 目录结构&#xff1a; async function ocr() {const worker await Tesseract.createWorker("chi_sim", 1, {wor…

前端打印功能(vue +springboot)

后端 后端依赖生成pdf的方法pdf转图片使用(用的打印模版是带参数的 ,参数是aaa)总结 前端页面 效果 后端 依赖 依赖 一个是用模版生成对应的pdf,一个是用来将pdf转成图片需要的 <!--打印的--><dependency><groupId>net.sf.jasperreports</groupId>&l…

探索 YOLO11:更快、更智能、更高效

点击下方卡片&#xff0c;关注“小白玩转Python”公众号 在人工智能这个不断进化的世界中&#xff0c;有一件事我们可以肯定&#xff1a;模型不断变得更好、更快、更智能。就在你以为 YOLO 系列已经达到顶峰时&#xff0c;Ultralytics 推出了最新升级——YOLO11。没错&#xff…

K-means 聚类算法:目标函数推导、迭代过程及可视化解析

一、K-means 的背景 在机器学习领域&#xff0c;许多任务涉及 训练模型来做预测或分类 。比如&#xff0c;医生可能希望通过以往的病例数据来预测某个病人未来是否会患上某种疾病&#xff0c;或者新闻网站可能需要根据文章的主题将新闻自动分类。这些任务通常依赖于有标签的数…

Qt之TCP收发图片的例子

一.效果 二.实现 1.发图片 void MainWindow::slotSendImage() {matrix.rotate(90);QPixmap tempPixmap = pixmap.transformed(matrix);QBuffer buffer;tempPixmap.save(&buffer,"jpg");ui->labelImage->setPixmap(tempPixmap);int dataLength = buffer.d…