ROS:话题通信机制详解

news2024/12/26 10:53:37

目录

  • ROS:通信机制
  • 一、话题通信简介
  • 二、话题通信实操(C++)
    • 2.1分析
    • 2.2发布方代码
    • 2.3订阅方代码
    • 2.4配置CMakeLists.txt
    • 2.5执行
    • 2.6注意
  • 三、话题通信实操(python)
    • 3.1分析
    • 3.2发布方代码
    • 3.3订阅方代码
    • 3.4添加可执行权限
    • 3.5配置 CMakeLists.txt
    • 3.6执行
  • 四、话题通信自定义msg
    • 4.1自定义msg实现
      • 4.1.1需求
      • 4.1.2流程
      • 4.1.3定义msg文件
      • 4.1.4编辑配置文件
      • 4.1.5编译
    • 4.2将自定义msg信息发布和订阅(C++)
      • 4.2.1需求
      • 4.2.2流程
      • 4.2.3vscode 配置
      • 4.2.4发布方
      • 4.2.5订阅方
      • 4.2.6配置 CMakeLists.txt
      • 4.2.7执行
    • 4.3将自定义msg信息发布和订阅(python)
      • 4.3.1需求
      • 4.3.2流程
      • 4.3.3vscode配置
      • 4.3.4发布方
      • 4.3.5订阅方
      • 4.3.6权限设置
      • 4.3.7配置 CMakeLists.txt
      • 4.3.8执行

ROS:通信机制

一、话题通信简介

话题在ROS中使用最为频繁,其通信模型也较为复杂。在ROS中有两个节点:一个是发布者Talker,另一个是订阅着Listener。两个节点分别发布、订阅同一个话题,启动顺序没有强制要求,此处假设Talker首先启动,可分为如下七步分析建立通信的详细过程。
在这里插入图片描述
0、Talker注册
Talker启动,通过1234端口使用RPC向ROS Master注册发布者的信息,包含所发布消息的话题名;ROS Master会将节点的注册信息加入注册列表中。
1、Listener注册
Listener启动,同样通过RPC向ROS Master注册订阅者的信息,包含需要订阅的话题名。
2、ROS Master进行信息匹配
Master根据Listener的订阅信息从注册列表中进行查找,如果没有找到匹配的发布者,则等待发布者的加入:如果找到匹配的发布者信息,则通过RPC向Listener发送Talker的RPC地址信息。
3、Listener发送连接请求
Listener接收到Master发回的Talker地址信息,尝试通过RPC向Talker发送连接请求,传输订阅的话题名、消息类型以及通信协议(TCP/UDP)
4、Talker确认连接请求
Talker接收到Listener发送的连接请求后,继续通过RPC向Listener确认连接信息,其中包含自身的TCP地址信息。
5、Listener尝试与Talker建立网络连接
Listener接收到确认信息后,使用TCP尝试与Talker建立网络连接。
6、Talker向Listener发布数据
成功建立连接后,Talker开始向Listener发送话题消息数据。
从上面的分析中可以发现,前五个步骤使用的通信协议都是RPC,最后发布数据的过程才使用到TCP。ROS Master在节点建立连接的过程中起到了重要作用,但是并不参与节点之间最终的数据传输。

二、话题通信实操(C++)

2.1分析

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为普通文本)

流程:
编写发布方实现;
编写订阅方实现;
编辑配置文件;
编译并执行。

2.2发布方代码

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "sstream"

/*
发布方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑并发布数据
*/



int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"erGouZi");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
    //5.编写发布逻辑并发布数据
    //要求以10HZ的频率发布数据,并且文本后添加编号
    //先创建被发布的消息
    std_msgs::String msg;
    //发布频率
    ros::Rate rate(10);
    //设置编号
    int count =0;
    //编写循环,循环中发布数据
    while (ros::ok())
    {
        count++;
        //msg.data = "hello";
        //实现字符串拼接数字
        std::stringstream ss;
        ss << "hello ---> " <<count;
        msg.data = ss.str();
        pub.publish(msg);

        //添加日志
        ROS_INFO("发布的数据是:%s",ss.str().c_str());

        rate.sleep();根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;

        ros::spinOnce();//官方建议添加回调函数
    }
    
    return 0;
}

2.3订阅方代码

#include "ros/ros.h"
#include "std_msgs/String.h"


/*
订阅方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建订阅者对象
5.处理订阅数据
6.sain()函数
*/

void doMsg(const std_msgs::String::ConstPtr &msg)
{
    //通过msg获取并操作订阅到的数据
    ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());

}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"cuihua");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("fang",10,doMsg);
    //5.处理订阅数据

    ros::spin();//循环读取接收的数据,并调用回调函数处理




    return 0;
}

2.4配置CMakeLists.txt

add_executable(demo01_pub src/demo01_pub.cpp)
add_executable(demo02_sub src/demo02_sub.cpp)

target_link_libraries(demo01_pub
  ${catkin_LIBRARIES}
)
target_link_libraries(demo02_sub
  ${catkin_LIBRARIES}
)

2.5执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
在这里插入图片描述

2.6注意

补充0:

vscode 中的 main 函数 声明 int main(int argc, char const *argv[]){},默认生成 argv 被 const 修饰,需要去除该修饰符

补充1:

ros/ros.h No such file or directory …

检查 CMakeList.txt find_package 出现重复,删除内容少的即可

参考资料:https://answers.ros.org/question/237494/fatal-error-rosrosh-no-such-file-or-directory/

补充2:

find_package 不添加一些包,也可以运行啊, ros.wiki 答案如下

You may notice that sometimes your project builds fine even if you did not call find_package with all dependencies. This is because catkin combines all your projects into one, so if an earlier project calls find_package, yours is configured with the same values. But forgetting the call means your project can easily break when built in isolation.


补充3:

订阅时,第一条数据丢失

原因: 发送第一条数据时, publisher 还未在 roscore 注册完毕

解决: 注册后,加入休眠 ros::Duration(3.0).sleep(); 延迟第一条数据的发送

三、话题通信实操(python)

3.1分析

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为普通文本)

流程:
编写发布方实现;
编写订阅方实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。

3.2发布方代码

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "sstream"

/*
发布方实现:
1.包含头文件
ROS中文本类型--->td_msgs/String.h
2.初始化ros节点
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑并发布数据
*/



int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化ros节点
    ros::init(argc,argv,"erGouZi");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
    //5.编写发布逻辑并发布数据
    //要求以10HZ的频率发布数据,并且文本后添加编号
    //先创建被发布的消息
    std_msgs::String msg;
    //发布频率
    ros::Rate rate(10);
    //设置编号
    int count =0;
    //编写循环,循环中发布数据
    while (ros::ok())
    {
        count++;
        //msg.data = "hello";
        //实现字符串拼接数字
        std::stringstream ss;
        ss << "hello ---> " <<count;
        msg.data = ss.str();
        pub.publish(msg);

        //添加日志
        ROS_INFO("发布的数据是:%s",ss.str().c_str());

        rate.sleep();//根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;

        ros::spinOnce();//官方建议添加回调函数
    }
    
    return 0;
}

3.3订阅方代码

#! /usr/bin/env python

import rospy
from std_msgs.msg import String #发布消息的类型

"""
使用py 实现消息订阅
1.导包
2.初始化ROS节点
3.创建订阅者对象
4.回调函数处理数据
spin

"""
def doMsg(msg):
    rospy.loginfo("我订阅的数据:%s",msg.data)


if __name__ == "__main__":
    # 2.初始化ROS节点
    rospy.init_node("huahua")#传入节点名称
    # 3.创建订阅者对象
    sub = rospy.Subscriber("che",String,doMsg,queue_size=10)
    # 4.回调函数处理数据
    #5.spin
    rospy.spin()

3.4添加可执行权限

终端下进入 scripts 执行:chmod +x *.py

3.5配置 CMakeLists.txt

catkin_install_python(PROGRAMS
  scripts/demo01_pub_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
catkin_install_python(PROGRAMS
  scripts/demo02_sub_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

3.6执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
在这里插入图片描述
注:可以使用 rqt_graph 查看节点关系。

四、话题通信自定义msg

在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息… std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型

msgs只是简单的文本文件,每行具有字段类型和字段名称,可以使用的字段类型有:

int8, int16, int32, int64 (或者无符号类型: uint*)
float32, float64
string
time, duration
other msg files
variable-length array[] and fixed-length array[C]
ROS中还有一种特殊类型:Header,标头包含时间戳和ROS中常用的坐标帧信息。会经常看到msg文件的第一行具有Header标头。

4.1自定义msg实现

4.1.1需求

创建自定义消息,该消息包含人的信息:姓名、身高、年龄等。

4.1.2流程

按照固定格式创建 msg 文件
编辑配置文件
编译生成可以被 Python 或 C++ 调用的中间文件

4.1.3定义msg文件

功能包下新建 msg 目录,添加文件 Person.msg

string name
uint16 age
float64 height

4.1.4编辑配置文件

package.xml中添加编译依赖与执行依赖

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
  <!-- 
  exce_depend 以前对应的是 run_depend 现在非法
  -->

CMakeLists.txt编辑 msg 相关配置

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# 需要加入 message_generation,必须有 std_msgs
## 配置 msg 源文件
add_message_files(
  FILES
  Person.msg
)


# 生成消息时依赖于 std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)


#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)


4.1.5编译

编译后的中间文件查看:
C++ 需要调用的中间文件(…/工作空间/devel/include/包名/xxx.h)
在这里插入图片描述
Python 需要调用的中间文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg)
在这里插入图片描述

4.2将自定义msg信息发布和订阅(C++)

4.2.1需求

编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布自定义消息,订阅方订阅自定义消息并将消息内容打印输出。

4.2.2流程

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为自定义消息)

流程:
编写发布方实现;
编写订阅方实现;
编辑配置文件;
编译并执行。

4.2.3vscode 配置

为了方便代码提示以及避免误抛异常,需要先配置 vscode,将前面生成的 head 文件路径配置进 c_cpp_properties.json 的 includepath属性:

{
    "configurations": [
        {
            "browse": {
                "databaseFilename": "",
                "limitSymbolsToIncludedHeaders": true
            },
            "includePath": [
                "/opt/ros/noetic/include/**",
                "/usr/include/**",
                "/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 
            ],
            "name": "ROS",
            "intelliSenseMode": "gcc-x64",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}

4.2.4发布方

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"

/*
发布方:发布人的消息
1.包含头文件;
2.初始化ROS节点;
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑,发布数据

*/

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ROS_INFO("这是消息的发布方");
// 2.初始化ROS节点;
    ros::init(argc,argv,"banZhuRrn");
// 3.创建节点句柄
    ros::NodeHandle nh;
// 4.创建发布者对象
    ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("LiaoTian",10);
// 5.编写发布逻辑,发布数据
//5.1创建发布数据
    plumbing_pub_sub::Person person;
    person.name = "张三";
    person.age = 0;
    person.height = 1.73;

//5.2发布频率
    ros::Rate rate(1);

//5.3循环发布数据
    while(ros::ok())
    {
        person.age +=1;
        //核心:发布数据
        pub.publish(person);
        ROS_INFO("发布的消息:%s,%d,%.2f",person.name.c_str(),person.age,person.height);
        //休眠
        rate.sleep();
        //调用回头函数
        ros::spinOnce();
    
    }

    return 0;
}

4.2.5订阅方

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"


/*
订阅方实现:
1.包含头文件
2.初始化ros节点
3.创建节点句柄
4.创建订阅者对象
5.处理订阅数据
6.spin()函数
*/

void doPerson(const plumbing_pub_sub::Person::ConstPtr & person)
{
    //通过msg获取并操作订阅到的数据
    ROS_INFO("订阅的的数据:%s,%d,%.2f",person->name.c_str(),person->age,person->height);

}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ROS_INFO("这是消息的订阅方");
    //2.初始化ros节点
    ros::init(argc,argv,"jiaZhang");
    //3.创建节点句柄
    ros::NodeHandle nh;
    //4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("LiaoTian",10,doPerson);
    //5.处理订阅数据

    ros::spin();//循环读取接收的数据,并调用回调函数处理




    return 0;
}

4.2.6配置 CMakeLists.txt

需要添加 add_dependencies 用以设置所依赖的消息相关的中间文件。

add_executable(demo03_pub_person src/demo03_pub_person.cpp)
add_executable(demo04_sub_person src/demo04_sub_person.cpp)

add_dependencies(demo03_pub_person ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(demo04_sub_person ${PROJECT_NAME}_generate_messages_cpp)

target_link_libraries(demo03_pub_person
  ${catkin_LIBRARIES}
)
target_link_libraries(demo04_sub_person
  ${catkin_LIBRARIES}
)

4.2.7执行

1.启动 roscore;

2.启动发布节点;

3.启动订阅节点。
在这里插入图片描述

4.3将自定义msg信息发布和订阅(python)

4.3.1需求

编写发布订阅实现,要求发布方以1HZ(每秒1次)的频率发布自定义消息,订阅方订阅自定义消息并将消息内容打印输出。

4.3.2流程

分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
发布方
接收方
数据(此处为自定义消息)

流程:
编写发布方实现;
编写订阅方实现;
为python文件添加可执行权限;
编辑配置文件;
编译并执行。

4.3.3vscode配置

为了方便代码提示以及误抛异常,需要先配置 vscode,将前面生成的 python 文件路径配置进 settings.json

{
    "python.autoComplete.extraPaths": [
        "/opt/ros/noetic/lib/python3/dist-packages",
        "/xxx/yyy工作空间/devel/lib/python3/dist-packages"
    ]
}


4.3.4发布方

#! /usr/bin/env python

import rospy
from plumbing_pub_sub.msg import Person #发布消息的类型

"""
使用py 实现人的消息发布
1.导包
2.初始化ROS节点
3.创建发布者对象
4.编写发布逻辑并发布数据

"""

if __name__ == "__main__":

#2.初始化ROS节点
    rospy.init_node("dama")#传入节点名称
# 3.创建发布者对象
    pub = rospy.Publisher("jiaoshetou",Person,queue_size=10)
# 4.编写发布逻辑并发布数据
    #创建数据
    p =Person()
    p.name = "奥特曼"
    p.age = 8
    p.height = 1.85
    #指定发布频率
    rate = rospy.Rate(1)
    #设置计数器
    count = 0
    #使用循环发布数据
    while not rospy.is_shutdown():
    #发布数据
        pub.publish(p)
        rospy.loginfo("发布的数据是:%s,%d,%.2f",p.name,p.age,p.height)
        rate.sleep()

4.3.5订阅方

#! /usr/bin/env python

import rospy
from plumbing_pub_sub.msg import Person #发布消息的类型

"""
使用py 实现消息订阅
1.导包
2.初始化ROS节点
3.创建订阅者对象
4.回调函数处理数据
spin

"""
def doPerson(p):
    rospy.loginfo("订阅的数据是:%s,%d,%.2f",p.name,p.age,p.height)


if __name__ == "__main__":
    # 2.初始化ROS节点
    rospy.init_node("daye")#传入节点名称
    # 3.创建订阅者对象
    sub = rospy.Subscriber("jiaoshetou",Person,doPerson,queue_size=10)
    # 4.回调函数处理数据
    #5.spin
    rospy.spin()

4.3.6权限设置

终端下进入 scripts 执行:chmod +x *.py

4.3.7配置 CMakeLists.txt

catkin_install_python(PROGRAMS
  scripts/demo03_pub_person_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
catkin_install_python(PROGRAMS
  scripts/demo04_sub_person_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.3.8执行

启动 roscore;

启动发布节点;

启动订阅节点。
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Apache Log4j2 漏洞原理

Apache Log4j 远程代码执行漏洞 1.漏洞危害 Apache Log4j被发现存在一处任意代码执行漏洞&#xff0c;由于Apache Log4j2某些功能存在递归解析功能&#xff0c;攻击者可直接构造恶意请求&#xff0c;触发远程代码执行漏洞。经验证&#xff0c;Apache Struts2、Apache Solr、Ap…

Win10控制面板在哪里打开?Win10控制面板打开方式介绍

Win10控制面板在哪里打开&#xff1f;当前很多用户都在使用Win10系统&#xff0c;一些新手用户不清楚在哪里才能打开Win10系统的控制面板&#xff0c;以下给大家介绍三种方式&#xff0c;帮助用户们轻松快速打开Win10控制面板&#xff0c;打开控制面板后用户即可展开不同的设置…

5-1图像信息提取适当剪掉像素点(matlab程序)

代码及运行结果 clear ; close all; gr imread(cameraman.tif); subplot(1,3,1); imshow(gr); subplot(1,3,2); D dct2(gr); F log(abs(D)); imshow(F,[]); subplot(1,3,3); D(abs(D)<200) 0; %会丢掉很多点 &#xff0c;但是原图还可识别&#xff0c;适合做信息提取 M …

这所院校很保护一志愿,学硕爆冷,全部录取,专硕初试第三竟主动放弃录取!

一、学校及专业介绍 广州大学&#xff08;Guangzhou University&#xff09;&#xff0c;简称广大&#xff08;GU&#xff09;&#xff0c;是由广东省广州市人民政府举办的全日制普通高等学校&#xff0c;实行省市共建、以市为主的办学体制&#xff0c;是国家“111计划”建设高…

c语言结构体属性之__attribute__((packed))

c语言结构体属性之__attribute__((packed)) 0. 引出 事情是这样的&#xff0c;最近在做代码移植时见到了这样一段代码 typedef struct {uint16_t len;uint8_t data[PAIRING_MAX_LEN]; } pairing_rx_buffer_t;static pairing_rx_buffer_t pairing_rx_buffer {}; typedef str…

四大世界权威大学排名指标及侧重点

U.S.News、QS、ARWU、THE是公认的四大权威世界大学排名&#xff0c;每个排名的侧重点各有不同&#xff0c;故知识人网小编撰文加以介绍。 很多博士后、访问学者和联合培养博士的申请者会注重学校排名。那么都有哪些排名体系呢&#xff1f;一般来说&#xff0c;国际公认的四大权…

PLC技能在职场中的竞争力如何?

在当前的工作市场上&#xff0c;仅仅掌握PLC可能会限制您的竞争力。尽管PLC在自动化控制系统中扮演重要的角色&#xff0c;但现代工业界对多样化技能和知识的需求越来越高。 为了提高竞争力&#xff0c;以下是一些建议&#xff1a; 学习其他自动化技术&#xff1a;除了PLC&am…

人脸跟踪:基于人脸检测API的连续检测与姿态估计技术

人脸跟踪技术在视频监控、虚拟现实和人机交互等领域发挥着重要作用。通过连续的人脸检测与姿态估计&#xff0c;可以实现对人脸在视频序列中的跟踪和姿态分析。 本文将介绍基于人脸检测API的人脸跟踪技术&#xff0c;探讨其原理、应用场景以及未来发展前景。 人脸跟踪的意义和…

typescript中interface,type和Record的使用

vitevue3ts中interface&#xff0c;type和Record的使用 vitevue3ts中interface&#xff0c;type和Record的使用 interface&#xff1a;接口type&#xff1a;类型别名 基本类型组合元组类型捕捉遍历属性 扩展 interface扩展interface&#xff08;合并&#xff09;interface扩展i…

你以为的网络工程师VS实际工作中的网络工程师

我的网工朋友&#xff0c;大家好。 前两天不是端午节嘛&#xff0c;去亲戚家吃饭。饭后闲聊说起&#xff0c;他们家的电脑开不了机了&#xff0c;问我能不能修下。 我说我不太会&#xff0c;让他们打电话报修&#xff0c;会有人上门看的。 结果亲戚蹦出一句话&#xff1a;你…

Qt Widget提升为QChartView绘制曲线

1、在工程文件"*.pro"中添加"charts"组件 在工程文件"*.pro"中添加"charts"组件&#xff0c;同时在工程文件添加qcustomplot类。 QT core gui printsupport charts下载qcustomplot类。 网址&#xff1a;https://www.qcustom…

技术小知识:分布式中的BASE和CAP原则 ③

一、CAP 理论和 BASE 理论 理论是指导业界实现的纲领&#xff0c;也是提炼了多年研究的精华&#xff0c;在分布式一致性领域&#xff0c;最主要的指导理论是 CAP 和 BASE 两个。 二、CAP理论 CAP原则又称CAP定理&#xff0c;指的是在一个分布式系统中&#xff0c; Consistency&…

面试官:SpringBoot如何快速实现分库分表?

一、什么是 ShardingSphere&#xff1f; shardingsphere 是一款开源的分布式关系型数据库中间件&#xff0c;为 Apache 的顶级项目。其前身是 sharding-jdbc 和 sharding-proxy 的两个独立项目&#xff0c;后来在 2018 年合并成了一个项目&#xff0c;并正式更名为 ShardingSp…

低代码搭建100分的酷炫大屏看板,3分钟打动老板!

不久前的一个热门话题是“00后整顿职场”&#xff0c;其实完全是胡说八道&#xff0c;因为大半的00后连工作都找不到&#xff01; 在行业危机&#xff0c;裁员话题不时火爆的今天&#xff0c;别说00后了&#xff0c;90后的打工人们纷纷都有了人还没到中年的就有的危机感。别说升…

【基于Django框架的在线教育平台开发-01】账号登录及退出登录功能开发

文章目录 1 模型层开发2 视图层开发3 form表单验证4 配置urls.py5 模板层开发6 效果展示 1 模型层开发 用户数据表如下所示&#xff1a; FieldTypeExtraidintPrime Key & Auto Incrementpasswordvarchar(128)last_logindatetime(6)Allow Nullis_superusertinyint(1)usern…

适用于 SAP 解决方案的 OpenText Extended ECM(企业内容管理)

适用于SAP 解决方案的 Extended ECM 概述 创建一种更好的将您的企业内容和企业应用程序连接起来工作方式&#xff0c;并从全面的数字内容管理平台中受益&#xff0c;该平台以产品化的方式无缝集成到任何 SAP 业务应用程序中&#xff0c;无论是在本地还是在云中。 SAP 解决方案…

Flutter 组件(二)文本 与 输入框组件

Flutter开发笔记 Flutter 组件&#xff08;二&#xff09;文本 与 输入框组件 - 文章信息 - Author: Jack Lee (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChineAddress of this article:https://blog.csdn.net/qq_28550263/art…

第一章 计算机系统的概述①

一、操作系统概述 1、操作系统的概念&#xff08;什么是操作系统&#xff09; 概念&#xff1a;操作系统 (Operating System&#xff0c; 0s) 是指控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分配:以提供给用户和其他软件方便…

✅【值得收藏】超全期刊缩写查询网址

【SciencePub学术干货】英文论文写作中会插入参考文献&#xff0c;而参考文献中的期刊名称时常需要使用缩写。期刊缩写一般包括两种格式&#xff1a;JCR缩写和ISO缩写。比如 Journal of controlled release 杂志&#xff1a; 期刊名&#xff1a;JOURNAL OF CONTROLLED RELEASE…

力扣算法刷题Day47|周日总结:动态规划之背包问题

背包问题 〉题型分类 解题套路 〉动规五部曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 解题技巧 〉递推公式 问背包装满后的最大价值&#xff1a;dp[j] max(dp[j], dp[j - weight[i]] value[i]) …