ROS参数服务器(Param):通信模型、Hello World与拓展

news2024/9/24 15:23:15

参数服务器在ROS中主要用于实现不同节点之间的数据共享。

参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。

使用场景一般存储一些机器人的固有参数,如产品定义、全局配置等。

主要思想就是一个共享数据域,供不同节点使用。

一、参数服务器通讯模型

参数服务器模型涉及到三个角色:

  • Master (管理者)
  • Setter(设置者)
  • User(使用者)

Master 负责管理参数与 Setter/User 的操作,Setter 可以向 Master 设置参数,User 可以从 Master 获取参数。

这里只是方便说明,实际上通讯方操作参数前不会向 ROS Master 注册身份信息,所以对 ROS Master 而言,没有 SetterUser 之分,每个访问参数服务器的通讯方都是使用者。

在这里插入图片描述

通讯流程:

  • 1)Setter设置参数

Setter 通过 RPC 向参数服务器设置参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。

  • 2)User获取参数

User 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。

  • 3)ROS Master返回参数信息

ROS Master 根据请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 User

参数服务器使用 XMLRPC 数据格式存储参数,支持的数据类型如下:

  • 32-bit integers
  • booleans
  • strings
  • doubles
  • iso8601 dates
  • lists
  • base64-encoded binary data

Note:

二、Param Hello World

万物始于Hello World,同样,使用Hello World介绍参数服务器的简单使用。

使用参数服务器,通讯方操作参数前没有向 ROS Master 注册身份信息,直接对参数进行操作。

接下来实现一个简单的参数操作,设置不同数据类型的参数,如机器人的名字(name)长(length)宽(width)高(height)等,并对其进行读取删除等操作。

2.1 创建并初始化功能包

(这一步不是必须,这里只是为了方便清晰的说明,也可以使用已有的包,在包里新增节点等方法)

首先创建 param_hello_world 包,命令如下:

catkin_creat_pkg param_hello_world roscpp rospy

创建后,文件结构如下:

在这里插入图片描述

2.2 操作参数(C++版)

ROSC++ 提供了两套 API,如下:

  • 通过 ros::NodeHandle 对象调用
  • 通过 ros::param 名空间调用

示例如下:

在创建的 param_hello_world 包路径下有一个 src 目录,在这里存储C++源码,我们创建 param_hello_world_set.cppparam_hello_world_get.cpp ,修改 CMakeLists.txt ,添加如下内容:

add_executable(${PROJECT_NAME}_set src/param_hello_world_set.cpp)
add_executable(${PROJECT_NAME}_get src/param_hello_world_get.cpp)

target_link_libraries(${PROJECT_NAME}_set
  ${catkin_LIBRARIES}
)

target_link_libraries(${PROJECT_NAME}_get
  ${catkin_LIBRARIES}
)

编辑 param_hello_world_set.cpp 内容如下:

#include <ros/ros.h>

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "param_hello_world_set");
    ros::NodeHandle nh;

    std::cout << std::endl
              << "********** ros::NodeHandle **********" << std::endl;
    {
        std::string name = "vbot";
        std::string geometry = "rectangle";
        double wheel_radius = 0.1;
        int wheel_num = 4;
        bool vision = true;
        std::vector<double> base_size = {0.7, 0.6, 0.3};
        std::map<std::string, int> sensor_id = {{"camera", 0}, {"laser", 2}};

        // 设置参数
        std::cout << "-- 设置参数 --" << std::endl;
        nh.setParam("name", "vbot");               // 字符串, char*
        nh.setParam("geometry", geometry);         // 字符串, string
        nh.setParam("wheel_radius", wheel_radius); // double
        nh.setParam("wheel_num", wheel_num);       // int
        nh.setParam("vision", vision);             // bool
        nh.setParam("base_size", base_size);       // vector
        nh.setParam("sensor_id", sensor_id);       // map
        // 验证是否设置成功
        system("rosparam get name");
        system("rosparam get geometry");
        system("rosparam get wheel_radius");
        system("rosparam get wheel_num");
        system("rosparam get vision");
        system("rosparam get base_size");
        system("rosparam get sensor_id");
    }


    std::cout << std::endl
              << "********** ros::param **********" << std::endl;
    {
        std::string name = "vbot";
        std::string geometry = "rectangle";
        double wheel_radius = 0.1;
        int wheel_num = 4;
        bool vision = true;
        std::vector<double> base_size = {0.7, 0.6, 0.3};
        std::map<std::string, int> sensor_id = {{"camera", 0}, {"laser", 2}};
        // 设置参数
        std::cout << "-- 设置参数 --" << std::endl;
        ros::param::set("name_p", "vbot");               // 字符串, char*
        ros::param::set("geometry_p", geometry);         // 字符串, string
        ros::param::set("wheel_radius_p", wheel_radius); // double
        ros::param::set("wheel_num_p", wheel_num);       // int
        ros::param::set("vision_p", vision);             // bool
        ros::param::set("base_size_p", base_size);       // vector
        ros::param::set("sensor_id_p", sensor_id);       // map
        // 验证是否设置成功
        system("rosparam get name_p");
        system("rosparam get geometry_p");
        system("rosparam get wheel_radius_p");
        system("rosparam get wheel_num_p");
        system("rosparam get vision_p");
        system("rosparam get base_size_p");
        system("rosparam get sensor_id_p");
    }

    return 0;
}

编译运行,结果如下:

在这里插入图片描述

编辑 param_hello_world_get.cpp 内容如下:

#include <ros/ros.h>

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "param_hello_world_get");
    ros::NodeHandle nh;

    std::cout << std::endl
              << "********** ros::NodeHandle **********" << std::endl;
    {
        // 修改参数
        std::cout << std::endl
                  << "-- 修改参数 --" << std::endl;
        nh.setParam("name", "mybot");        // 字符串, char*
        nh.setParam("geometry", "circular"); // 字符串, char*
        nh.setParam("wheel_radius", 0.15);   // double
        nh.setParam("wheel_num", 2);         // int
        nh.setParam("vision", false);        // bool
        std::vector<double> base_size = {0.2, 0.04};
        nh.setParam("base_size", base_size); // vector
        std::map<std::string, int> sensor_id = {{"camera", 0}, {"laser", 2}};
        sensor_id.insert({"ultrasonic", 5});
        ros::param::set("sensor_id", sensor_id); // map

        // 获取参数
        std::cout << std::endl
                  << "-- 获取参数 --" << std::endl;
        std::string name;
        std::string geometry;
        double wheel_radius;
        int wheel_num;
        bool vision;
        nh.getParam("name", name);
        nh.getParam("geometry", geometry);
        nh.getParam("wheel_radius", wheel_radius);
        nh.getParam("wheel_num", wheel_num);
        nh.getParam("vision", vision);
        nh.getParam("base_size", base_size);
        nh.getParam("sensor_id", sensor_id);
        ROS_INFO("ros::NodeHandle getParam, name: %s, geometry: %s, wheel_radius: %lf, wheel: %d, vision: %s, base_size: (%lf, %lf)",
                 name.c_str(), geometry.c_str(), wheel_radius, wheel_num, vision ? "true" : "false",
                 base_size[0], base_size[1]);
        for (auto sensor : sensor_id)
        {
            ROS_INFO("ros::NodeHandle getParam, %s_id: %d", sensor.first.c_str(), sensor.second);
        }


        // 删除参数
        std::cout << std::endl
                  << "-- 删除参数 --" << std::endl;
        nh.deleteParam("vision");
        system("rosparam get vision");

        // 其他操作函数
        std::cout << std::endl
                  << "-- 其他操作函数 --" << std::endl;
        double wheel_radius1;
        wheel_radius1 = nh.param("wheel_radius", wheel_radius1);
        ROS_INFO("param, wheel_radius: %lf", wheel_radius1);

        nh.getParamCached("wheel_radius", wheel_radius1);

        std::vector<std::string> keys_v;
        nh.getParamNames(keys_v);
        for (auto key : keys_v)
        {
            ROS_INFO("getParamNames, key: %s", key.c_str());
        }

        if (nh.hasParam("vision"))
        {
            ROS_INFO("hasParam, 存在该参数");
        }
        else
        {
            ROS_INFO("hasParam, 不存在该参数");
        }

        std::string result;
        nh.searchParam("name", result);
        ROS_INFO("searchParam, result: %s", result.c_str());
    }


    std::cout << std::endl
              << "********** ros::param **********" << std::endl;
    {
        // 修改参数
        std::cout << std::endl
                  << "-- 修改参数 --" << std::endl;
        ros::param::set("name_p", "mybot");        // 字符串, char*
        ros::param::set("geometry_p", "circular"); // 字符串, char*
        ros::param::set("wheel_radius_p", 0.15);   // double
        ros::param::set("wheel_num_p", 2);         // int
        ros::param::set("vision_p", false);        // bool
        std::vector<double> base_size = {0.2, 0.04};
        ros::param::set("base_size_p", base_size); // vector
        std::map<std::string, int> sensor_id = {{"camera", 0}, {"laser", 2}};
        sensor_id.insert({"ultrasonic", 5});
        ros::param::set("sensor_id_p", sensor_id); // map

        // 获取参数
        std::cout << std::endl
                  << "-- 获取参数 --" << std::endl;
        std::string name;
        std::string geometry;
        double wheel_radius;
        int wheel_num;
        bool vision;
        ros::param::get("name_p", name);
        ros::param::get("geometry_p", geometry);
        ros::param::get("wheel_radius_p", wheel_radius);
        ros::param::get("wheel_num_p", wheel_num);
        ros::param::get("vision_p", vision);
        ros::param::get("base_size_p", base_size);
        ros::param::get("sensor_id_p", sensor_id);
        ROS_INFO("ros::param get, name: %s, geometry: %s, wheel_radius: %lf, wheel: %d, vision: %s, base_size: (%lf, %lf)",
                 name.c_str(), geometry.c_str(), wheel_radius, wheel_num, vision ? "true" : "false",
                 base_size[0], base_size[1]);
        for (auto sensor : sensor_id)
        {
            ROS_INFO("ros::param getParam, %s_id: %d", sensor.first.c_str(), sensor.second);
        }

        // 删除参数
        std::cout << std::endl
                  << "-- 删除参数 --" << std::endl;
        ros::param::del("vision_p");
        system("rosparam get vision_p");

        // 其他操作函数
        std::cout << std::endl
                  << "-- 其他操作函数 --" << std::endl;
        double wheel_radius1;
        wheel_radius1 = ros::param::param("wheel_radius", wheel_radius1);
        ROS_INFO("param, wheel_radius: %lf", wheel_radius1);

        ros::param::getCached("wheel_radius", wheel_radius1);

        std::vector<std::string> keys_v;
        ros::param::getParamNames(keys_v);
        for (auto key : keys_v)
        {
            ROS_INFO("getParamNames, key: %s", key.c_str());
        }

        if (ros::param::has("vision"))
        {
            ROS_INFO("has, 存在该参数");
        }
        else
        {
            ROS_INFO("has, 不存在该参数");
        }

        std::string result;
        ros::param::search("name", result);
        ROS_INFO("search, result: %s", result.c_str());
    }

    return 0;
}

编译运行,结果如下:

在这里插入图片描述

2.3 其他操作参数的函数

除了上文提到的setParam()getParam()deleteParam() 函数,还有一些其他的参数操作函数,如下:

这里只以通过 ros::NodeHandle 对象调用为例,通过 ros::param 名空间调用类似,只多了一个 unsubscribeCachedParam函数,后面说明

1.param

获取 param_name 的值,如果 param_name 不存在,则返回 default_val

原型: T param(const std::string& param_name, const T& default_val) const

double wheel_radius2;
wheel_radius2 = nh.param("wheel_radius", wheel_radius2);
ROS_INFO("param, wheel_radius: %lf", wheel_radius2);

2.getParamCached()

getParam()使用方法一样。

首次调用会判断该参数是否获取过,如果获取过则从缓存读取,并向 Master 订阅该参数的变化,不再像getParam()一样通过 RPCMaster获取,以提高效率。

示例参考 getParam()

3.getParamNames()

获取所有设置到 Master 的参数的键,并通过 vector 返回。

原型:bool getParamNames(std::vector<std::string>& keys) const;

std::vector<std::string> keys_v;
nh.getParamNames(keys_v);
for (auto key : keys_v)
{
    ROS_INFO("getParamNames, key: %s", key.c_str());
}

4.hasParam()

判断是否存在该参数

原型:bool hasParam(const std::string& key) const;

if (nh.hasParam("vision"))
{
    ROS_INFO("存在该参数");
}
else
{
    ROS_INFO("不存在该参数");
}

5.searchParam()

搜索给定参数名,如果存在,返回键名,不存在返回空字符串。

原型:bool searchParam(const std::string& key, std::string& result) const;

std::string result;
nh.searchParam("name", result);
ROS_INFO("searchParam, result: %s", result.c_str());

6.unsubscribeCachedParam() (ros::param特有)

不明白该函数有什么具体作用,如果你知道欢迎交流(留言或加下方微信)。

没有找到官方说明,源码及注释如下:

头文件:param.h

在这里插入图片描述

源文件:param.cpp

在这里插入图片描述

直译注释为:取消订阅master中的缓存参数

猜测和 getCached() 有关, getCached() 会订阅参数变化,unsubscribeCachedParam则是取消订阅,但验证未生效:

// 设置参数
ros::param::set("wheel_radius", 0.15);

// 首次调用getCached,这里会订阅"wheel_radius"的变化
double wheel_radius;
ros::param::getCached("wheel_radius", wheel_radius);
ROS_INFO("before unsubscribeCachedParam, wheel_radius: %lf", wheel_radius);

// 调用unsubscribeCachedParam取消订阅
ros::param::unsubscribeCachedParam("wheel_radius");

// 修改master中的"wheel_radius"值
// 由于已取消参数变化的订阅,此次变化不会同步到缓存
// 所以master中的值是0.5,而缓存中的值是0.15
ros::param::set("wheel_radius", 0.5);

// 再次调用getCached,
// 理论上,再次调用getCached,会从缓存读取,此时缓存中的值是0.15
double wheel_radius1;
ros::param::getCached("wheel_radius", wheel_radius1);
ROS_INFO("after  unsubscribeCachedParam, wheel_radius1: %lf", wheel_radius1);

实际输出为:

before unsubscribeCachedParam, wheel_radius: 0.15
after  unsubscribeCachedParam, wheel_radius: 0.50

欢迎交流(留言或加下方微信)。

2.4 操作参数(Python版)

C++ 不同,ROS 只为 Python 提供了一套操作参数的 API

在创建的 param_hello_world 包路径下 src 目录的同级,创建一个 scripts 目录,在这里存储脚本(如python脚本),修改 CMakeLists.txt ,添加如下内容:

catkin_install_python(PROGRAMS
  scripts/param_hello_world_set.py
  scripts/param_hello_world_get.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

scripts 中创建 param_hello_world_set.py 编辑内容如下:

import rospy
import os


if __name__ == "__main__":
    rospy.init_node("param_hello_world_set")

    # 设置参数
    rospy.set_param("name", "vbot")                         # 字符串, string
    rospy.set_param("geometry", "rectangle")                # 字符串, string
    rospy.set_param("wheel_radius", 0.1)                    # double
    rospy.set_param("wheel_num", 4)                         # int
    rospy.set_param("vision", True)                         # bool
    rospy.set_param("base_size", [0.7, 0.6, 0.3])           # list
    rospy.set_param("sensor_id", {"camera": 0, "laser": 2}) # dictionary

    # 验证是否设置成功
    os.system("rosparam get name")
    os.system("rosparam get geometry")
    os.system("rosparam get wheel_radius")
    os.system("rosparam get wheel_num")
    os.system("rosparam get vision")
    os.system("rosparam get base_size")
    os.system("rosparam get sensor_id")

scripts 中创建 param_hello_world_get.py 编辑内容如下:

import rospy


if __name__ == "__main__":
    rospy.init_node("param_hello_world_get")

    # 修改参数
    rospy.set_param("name", "mybot")             # 字符串, string
    rospy.set_param("geometry", "circular")      # 字符串, string
    rospy.set_param("wheel_radius", 0.15)        # double
    rospy.set_param("wheel_num", 2)              # int
    rospy.set_param("vision", False)             # bool
    rospy.set_param("base_size", [0.2, 0.04])    # list
    rospy.set_param("sensor_id", {"camera": 0, "laser": 2, "ultrasonic": 5}) # dictionary

    # 获取参数
    name = rospy.get_param("name")                    # 字符串, string
    geometry = rospy.get_param("geometry")            # 字符串, string
    wheel_radius = rospy.get_param("wheel_radius")    # double
    wheel_num = rospy.get_param("wheel_num")          # int
    vision = rospy.get_param("vision")                # bool
    base_size = rospy.get_param("base_size")          # list
    sensor_id = rospy.get_param("sensor_id")          # dictionary
    rospy.loginfo("get_param, name: {}, geometry: {}, wheel_radius: {}, wheel: {}, vision: {}, base_size: ({}, {})"
                  .format(name, geometry, wheel_radius, wheel_num, vision, base_size[0], base_size[1]))
    for key, value in sensor_id.items():
        rospy.loginfo("get_param, sensor: {}, id: {}".format(key, value))

    # 删除参数
    rospy.delete_param("vision")

    # 其他操作
    wheel_radius1 = rospy.get_param_cached("wheel_radius")

    keys = rospy.get_param_names()
    for key in keys:
        rospy.loginfo("get_param_names, key: {}".format(key))

    if rospy.has_param("vision"):
        rospy.loginfo("has_param, 存在该参数")
    else:
        rospy.loginfo("has_param, 不存在该参数")

    result = rospy.search_param("name")
    rospy.loginfo("search_param, result: {}".format(result))

编译执行结果如下:

在这里插入图片描述

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

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

相关文章

【2023云栖】刘一鸣:Data+AI时代大数据平台建设的思考与发布

简介&#xff1a; 本文根据2023云栖大会演讲实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a;刘一鸣 | 阿里云自研大数据产品负责人 演讲主题&#xff1a;DataAI时代大数据平台应该如何建设 今天分享的主题是DataAI时代大数据平台应该如何建设&#xf…

Ubuntu系统安装Python3.6.8-Python源代码编译安装-Python环境安装

一、背景 本文将着重介绍如何在Python环境下&#xff0c;安装Python3.6.8&#xff0c;以满足在Ubuntu系统中使用Python的需求。 二、详细步骤 安装Python的方法有很多&#xff0c;本文中我们采用源代码的方式安装Python&#xff0c;首先我们需要下载Python源代码&#xff1a;源…

一起Talk Android吧(第五百五十四回:分享一个Retorfit使用错误的案例)

文章目录 1. 案例场景2. 案例现象3. 原因分析和解决方案3.1 原因分析3.2 解决方案4. 经验总结各位看官们大家好,上一回中咱们说的例子是"解析Retrofit返回的数据",本章回中将分享一个 Retrofit使用错误的案例。闲话休提,言归正转,让我们一起Talk Android吧! 1. …

Unity中Shader法线贴图(上)

文章目录 前言一、法线纹理的作用二、为什么法线贴图长这样&#xff1f;&#xff08;蓝色&#xff09;三、法线贴图能使纹理采样时&#xff0c;进行偏移采样四、在Shader中使用法线贴图1、在属性面板定义一个变量来接收法线贴图2、在使用前声明 _NormalTex3、在片元着色器中&am…

git使用及常用命令

在初入公司中&#xff0c;若使用的是git管理工具&#xff0c;需要做以下步骤&#xff1a; 1&#xff0c;常用命令在&#xff1a; &#xff08;1&#xff09;&#xff0c;git config --global user.name xxx(名字) //若不设置 那么下次提交代码时会报错 其次该设置名字和…

华为模拟器dhcp实验

实验需求&#xff0c;pc1 pc2 pc3 获取到地址且能ping通&#xff0c;pc1 pc2 为地址池模式&#xff0c;pc3为接口模式 上配置 #sysname AR1# dhcp enable # interface GigabitEthernet0/0/0ip address 10.0.47.254 255.255.255.0 dhcp select relaydhcp relay server-ip 10.0…

李宏毅2023机器学习作业HW05解析和代码分享

ML2023Spring - HW5 相关信息&#xff1a; 课程主页 课程视频 Sample code HW05 视频 HW05 PDF 个人完整代码分享: GitHub | Gitee | GitCode 运行日志记录: wandb P.S. HW05/06 是在 Judgeboi 上提交的&#xff0c;完全遵循 hint 就可以达到预期效果。 因为无法在 Judgeboi 上…

windows上安装MySQL Server.

进入官网 MySQL 找到 下载&#xff0c;并点进入。 往下翻&#xff0c;找到社区下载&#xff0c;进入页面 选择 Mysql community Server 选择系统&#xff0c;下载 之后解压。 将解压文件夹下的bin路径添加到变量值中 配置初始化的my.ini文件 [mysqld] # 设置3306端口 port330…

YOLOv5 学习记录

文章目录 整体概况数据增强与前处理自适应Anchor的计算Lettorbox 架构SiLU激活函数YOLOv5改进点SSPF 模块 正负样本匹配损失函数 整体概况 YOLOv5 是一个基于 Anchor 的单阶段目标检测&#xff0c;其主要分为以下 5 个阶段&#xff1a; 1、输入端&#xff1a;Mosaic 数据增强、…

Parity Game——种类并查集、权值并查集、离散化

题目描述 思路 怎么得到这个序列中每一段的关系&#xff1f; 我们可以把这个只包含0和1的序列看作一个数组&#xff0c;0表示当前位置为0&#xff0c;1表示当前位置为1&#xff0c;利用前缀和的性质可以知道某一段中所包含的1的数量sum1 a[r] - a[l-1] 如果sum1为偶数&…

【0到1学习Unity脚本编程】第一人称视角的角色控制器

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;【0…

深信服AC流量管理技术

拓扑图 一.保证通道针对修仙部&#xff0c;访问网站&#xff0c;邮件&#xff0c;DNS&#xff0c;IM&#xff0c;办工 OA&#xff0c;微博论坛网上银行等常见应用保证带宽最低 50%&#xff0c;最高 100% 1. 先新建线路带宽 2.新增流量管理通道&#xff08;保证关键应用&#x…

吾爱破解置顶的“太极”,太好用了吧!

日常工作和娱乐&#xff0c;都需要用到不同类型的软件&#xff0c;哪怕软件体积不大&#xff0c;也必须安装&#xff0c;否则到用时找不到就非常麻烦了。 其实&#xff0c;很多软件不一定一样不剩地全部安装一遍&#xff0c;一方面原因是用的不多&#xff0c;另一方面多少有点…

安装第三方包报错 error: Microsoft Visual C++ 14.0 or greater is required——解决办法

1、问题描述 手动安装第三方软件时&#xff0c;可以使用setup.py&#xff0c;来安装已经下载的第三方包。一般文件下会存在setup&#xff0c;在所要安装库的目录下的cmd执行&#xff1a;python setup.py install报错&#xff1a;error: Microsoft Visual C 14.0 or greater i…

【LeetCode】二叉树OJ

目录 一、根据二叉树创建字符串 二、二叉树的层序遍历 三、二叉树的层序遍历 II 四、二叉树的最近公共祖先 五、二叉搜索树与双向链表 六、从前序与中序遍历序列构造二叉树 七、从中序与后序遍历序列构造二叉树 一、根据二叉树创建字符串 606. 根据二叉树创建字符串 - …

window上Clion配置C++版本的opencv

window上Clion配置opencv 注意版本一定要对的上&#xff0c;否则可能会出错&#xff0c;亲测 widnows 11mingw 8.1.0opencv 4.5.5 mingw8.1下载地址https://sourceforge.net/projects/mingw/ 配置环境变量 cmake下载 安装完添加环境变量 来到官网&#xff0c;下载 windows 对…

【华为HCIP | 华为数通工程师】刷题日记1116(一个字惨)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

真心建议看看这个盈亏平衡点计算方法及要点解析!

说实话&#xff0c;进行产品动态盈亏平衡计算是非常考验人的&#xff0c;因为不是人人都具备评估不同产品组合的盈利能力和掌握风险的方法。 当然最简单的方式就是套用诸如单产品动态盈亏平衡表之类的现成模板进行测算&#xff0c;可以实现以下三点基本需求&#xff1a; 弹性输…

AI实践与学习1_Milvus向量数据库实践与原理分析

前言 随着NLP预训练模型&#xff08;大模型&#xff09;以及多模态研究领域的发展&#xff0c;向量数据库被使用的越来越多。 在XOP亿级题库业务背景下&#xff0c;对于试题召回搜索单单靠着ES集群已经出现性能瓶颈&#xff0c;因此需要预研其他技术方案提高试题搜索召回率。…