干货技巧|关于Redis的16个使用技巧

1、什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么? 回答:持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。Redis 提供了两种持久化方式:RDB(默认) 和AOF。RDB,是Redis DataBase缩写,功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数AOF,f是Append-only file缩写每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作aof写入保存:WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。存储结构:内容是redis通讯协议(RESP )格式的命令文本存储。比较:aof文件比rdb更新频率高,优先使用aof还原数据。aof比rdb更安全也更大rdb性能比aof好如果两个都配了优先加载AOF 2、Redis 单线程为什么还能这么快 命令执行基于内存操作,在内存操作时间是几十纳秒,命令执行是单线程,没有线程切换开销,基于IO多路复用机制提升Redis的I/O利用率高效​ ​数据结构​​。 3、Redis到底是单线程还是多线程? Redis6.0版本之前的单线程指的是 网络I/O和键值对读写是由一个线程完成的。Redis6.0引入的多线程指的是网络请求过程采用了多线程;而键值对读写命令仍然是单线程处理的,Redis依然是并发安全的。即数据操作模块是单线程的,其它持久化、集群数据同步等,是由额外线程执行的。 4、使用过Redis分布式锁么,它是怎么实现的? 先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的! 5、什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免? 缓存穿透 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。 如何避免? 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。 对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。 缓存雪崩 当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。 如何避免? 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。 6、Redis的并发竞争问题如何解决? Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法: 客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。 服务器角度,利用setnx实现锁。 对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。 7、Redis 支持哪几种数据类型? String、List、Set、Sorted Set、hashes。 它还有三种特殊的数据结构类型 Geospatial Hyperloglog Bitmap 8、Redis 有哪几种数据淘汰策略? noeviction:返回错误当内存限制达到,并且客户端尝试执行会让更多内存被使用的命令。allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。 volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。 allkeys-random: 回收随机的键使得新添加的数据有空间存放。 volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。 9、Redis 集群为什么至少需要三个主节点 因为新主节点的选举现需要大于半数的集群主节点同意才能选举成功,只有两个的话,其中一个挂了,达不到选举新主节点条件的。 10、Redis集群为什么推荐奇数个节点 在挂掉相同机器的前提下,奇数和奇数+1的偶数,效果是一样的,但是却多浪费了一台机器

VUE页面表格数据多卡顿用虚拟表单

情景概况:页面表格想要通过滚动条展示非常多的数据,后端返回接口很快。 解决方法:虚拟滚动 vue + vxe-table 20220708_145309 element ui 表单已经不能满足这个需求,二次封装也很麻烦,所以推荐用现有插件vxetable 插件地址:vxe-table v4 第一步: 安装,右上角选择需要的版本 根据指南安装(选择版本后再npi,不然会出现未知错误) 第二步: 找到使用需要使用的功能,我这里以横向&纵向为例 第三步:直接上代码,根据需要API里面查找 <template> <div> <vxe-grid show-header-overflow border show-overflow :scroll-y="{ gt: 0 }" :scroll-x="{ gt: 0 }" ref="xGrid" :column-config="{ minWidth: '200' }" height="500" > </vxe-grid> </div> </template> <script> export default { data() { return { tableColumn: [], tableData: [], }; }, created() { for (let i = 0; i < 100; i++) { this.tableColumn.push({ field: "

Lidar_imu自动标定

系统版本:Ubuntu20.04 ROS版本:Noetic 前提条件,安装以下内容: Cmakeopencv 2.4eigen 3PCL 1.9Pangolin 执行以下命令,进行软件的编译: 这里给出程序的链接,自行下载: SensorsCalibration/lidar2imu/auto_calib at master · PJLab-ADG/SensorsCalibration · GitHubOpenCalib: A Multi-sensor Calibration Toolbox for Autonomous Driving - SensorsCalibration/lidar2imu/auto_calib at master · PJLab-ADG/SensorsCalibrationhttps://github.com/PJLab-ADG/SensorsCalibration/tree/master/lidar2imu/auto_calib下载成功后,执行以下命令: cd ~/auto_lib # mkdir build mkdir -p build && cd build # build cmake .. && make 小技巧:根据自己电脑的线程可选择编译的速度 ,make时可选择 make make -j4 make -j12 当自己进行编译时,出现以下错误: 第一个错误: 解决方法: 需要找到报错对应功能包,在功能包的CMakeList.txt文档里加入下面语句: set(CMAKE_CXX_STANDARD 14) 第二个错误: 解决方法: 首先检查一下有没有这个文件;如果有,则应该是文件路径不对,通过链接建立关系;如果没有,则下载该相关文件。 sudo apt-get install libjsoncpp-dev sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json #include <json/json.

Java中的四种引用详解

Java中的四种引用 Java中有四种引用类型:强引用、软引用、弱引用、虚引用。 强引用 强引用是最常见的一种引用类型,在实际开发中,几乎都是强引用类型。 Object obj = new Object(); 当我们的对象有强引用的时候,即使内存不足,JVM宁愿抛出OOM,也不会把该对象回收掉。如果需要让垃圾回收器回收此对象,需要将强引用关系打破,最简单的方式就是将对象赋值为null。下面写个例子做个简单说明: 创建一个Order对象,为了更好的知晓垃圾回收的情况,这里重写 finalize() 方法,因为对象被垃圾回收时都会调用此方法。 /** * 订单对象 */ public class Order { @Override protected void finalize() throws Throwable { System.out.println("order对象被垃圾回收"); } } 当对象的强引用关系被打破时,显式调用垃圾回收器 /** * 强引用类型垃圾回收 */ public class NormalReferenceTest { public static void main(String[] args) throws IOException { Order order = new Order(); // 破坏引用关系 order = null; // 调用垃圾回收器,进行垃圾回收 System.gc(); System.out.println(order); ​ // 阻塞Main主线程 System.in.read(); ​ } } 输出结果: null order对象被垃圾回收 根据输出结果,可知Order对象被垃圾回收掉了。

CentOS下JDK的安装配置过程

先卸载CentOS自带的OpenJDK,通过命令查看。 rpm -qa | grep jdk 如果存在,通过命令删除对应版本的JDK,示例如下。 rpm -e --nodeps java-1.8.0-openjdk-1.8.0.65-3.b17.el7.x86_64 rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.65- 3.b17.el7.x86_64 rpm -e --nodeps java-1.7.0-openjdk-1.7.0.91-2.6.2.3.el7.x86_64 rpm -e --nodeps java-1.7.0-openjdk-headless-1.7.0.91- 2.6.2.3.el7.x86_64 查看是否删除成功。在 /usr/local 目录下新建 java 文件夹,并进入。 cd /usr/local mkdir java cd java 打开Xftp上传JDK压缩包至 /usr/local/java文件夹。 JDK8压缩包 百度云:链接:https://pan.baidu.com/s/1waP5vfRwS36VTodK6I0EVw 提取码:5rda 解压JDK安装包,并删除。 tar -zxvf jdk-8u152-linux-x64.tar.gz //解压压缩包 rm -rvf jdk-8u152-linux-x64.tar.gz //删除压缩包 配置环境变量 和Windows系统类似,Linux同样需要配置环境变量。输入命令 vim /etc/profile 。 使用按键 ↓ 移动光标至文件末尾,并粘贴下面配置代码。按ESC退出编辑,输入 :wq 退出保存。 JAVA_HOME=/usr/local/java/jdk1.8.0_152 PATH=/usr/local/java/jdk1.8.0_152/bin:$PATH export JAVA_HOME PATH 使配置生效。 source /etc/profil 测试,输入java -version或javac。

python 基本概念整理

一、简介 1、基本概念 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。 Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。Python 是交互式语言: 这意味着,您可以在一个 Python 提示符 >>> 后直接执行代码。Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。 2、python 特点 1、易于学习:Python 有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。 2、易于阅读:Python 代码定义的更清晰。 3、易于维护:Python 的成功在于它的源代码是相当容易维护的。 4、一个广泛的标准库:Python 的最大的优势之一是丰富的库,跨平台的,在 UNIX,Windows 和 Macintosh 兼容很好。 5、互动模式:互动模式的支持,您可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片断。 6、可移植:基于其开放源代码的特性,Python已经被移植(也就是使其工作)到许多平台。 7、可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用 C 或 C++ 完成那部分程序,然后从你的Python程序中调用。 8、数据库:Python提供所有主要的商业数据库的接口。 9、GUI编程:Python支持GUI可以创建和移植到许多系统调用。 10、可嵌入: 你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。 3、官网 Welcome to Python.org 二、环境搭建 1、编译安装(Linux) Python3 环境搭建 | 菜鸟教程 (runoob.com) 2、环境变量 变量名描述PYTHONPATHPYTHONPATH 是 Python 搜索路径,默认我们 import 的模块都会从 PYTHONPATH 里面寻找。PYTHONSTARTUPPython 启动后,先寻找 PYTHONSTARTUP 环境变量,然后执行此变量指定的文件中的代码。PYTHONCASEOK加入 PYTHONCASEOK 的环境变量, 就会使 python 导入模块的时候不区分大小写.

Pyinstaller打包Pytorch框架

文章目录 前言基本流程一、安装Pyinstaller 和 测试Hello World二、打包整个项目,在本机上调试生成exe三、在新电脑上测试 参考资料 前言 第一次尝试用Pyinstaller打包Pytorch,碰见了很多问题,耗费了许多时间!想把这个过程中碰到的问题与解决方法记录一下,方便后来者。 基本流程 使用Pyinstaller打包流程可分为以下三步: 安装Pyinstaller,写个Hello world打包测试打包整个项目,在本机上调试生成exe将exe拷贝到新电脑上,测试和调试 一、安装Pyinstaller 和 测试Hello World 使用Pycharm打开项目,点击Terminal,输入以下命令: pip install pyinstaller 请确保Terminal所在路径为项目根目录,以免在后续打包过程中找不到一些模块。图中红框内(pytorch)是我的项目所需要的虚拟环境。 编写Hello World测试,新建test.py: if __name__ == '__main__': print("Hello World!") while True: pass 在Terminal输入以下命令,打包test.py: pyinstaller -F test.py 回车运行,开始打包!在文件夹 dist中找到 test.exe程序,运行测试,没报错说明Pyinstaller安装成功。 二、打包整个项目,在本机上调试生成exe 实际的项目一般是多文件,打包过程远比Hello World复杂多了。打包项目的核心要点有两个: 配置好spec文件补齐依赖项 关于.spec文件配置详见参考链接一,这里不再赘述。需要注意的是,在测试阶段,打包时应设置为-D模式,方便补齐dll。本文重点讲dll及其依赖项的补齐。先安装必备工具Dependens,通过这个工具,我们可以得到dll文件所需要的依赖项。在运行打包后的exe常常遇到以下的问题: 这提示我们系统缺少caffe2_nvrtc.dll**或其对应的依赖项。 先到对应路径查看caffe2_nvrtc.dll是否存在若不存在,直接在Anaconda配置环境的文件夹搜索,一般都可以找到。将找到的caffe2_nvrtc.dll复制粘贴到根目录下若存在,说明是缺少caffe2_nvrtc.dll的依赖项,使用Dependencies工具查看所需要的依赖项,后补齐到根目录下 Dependencies的使用非常简单,直接将.dll拖进去即可。这里以torch_python.dll举例 可以发现,缺少若干个dll文件,补齐便可。通过上述方法,依样画葫芦,基本可以解决关于dll报错的问题。 但每次重新打包后,需要手动复制粘贴dll文件,很是麻烦,通过配置.spec文件可简化操作。以记事本方式打开.spec,找到datas: 小括号内有两个路径,第一个路径’kernel32.dll’表示原始数据路径,存放kernel32.dll的路径;第二路径为’.'表示目标路径,打包后原始数据存放的路径。意思就是将第一路径的东西在打包后,放在第二路径上。需要注意的是,这边我设置的是相对路径,相对于.spec中的pathex 三、在新电脑上测试 我使用的是pytorch的GPU版本,在新电脑上运行发现会报如下错误,应该是缺少cuda库的缘故。 我的解决办法简单粗暴,直接拷贝cuda包到移动硬盘 每次到新的电脑,添加cuda到环境变量 建议在程序额外设置一个选项,可将网络切换成CPU推理,以便在其他电脑测试时,即使环境未配置成功,也可通过CPU推理验证打包成功与否。最后,祝大家好运,打包成功那一刻是蛮喜悦的! 参考资料 python项目(非单一.py文件)用Pyinstaller打包发布成exe,在windos上运行程序嘗試使用Pyinstaller打包yolov5中detect.py文件(含pytorch框架)所遇到的問題pyinstaller打包经验分享以及一些错误解决方法~~Dependencies安装链接

ByteBuffer和String相互转换,以及其中发现的问题

public static void main(String[] args) { //字符串转ByteBuffer //1.1 Buffer.put() 需要手动转为读模式 ByteBuffer buffer1 = ByteBuffer.allocate(16); //追踪getBytes方法的源码发现 默认使用StandardCharsets.UTF_8 不传这个参数也无妨 buffer1.put("hello".getBytes(StandardCharsets.UTF_8)); //没有转为读模式 此时打印的东西乱码 会引发一个问题 看2.1打印结果 hello后面跟了一个乱码的字符 System.out.println((char) buffer1.get()); //1.2 使用Charset.encode("") buffer2 自动转为读模式 ByteBuffer buffer2 = StandardCharsets.UTF_8.encode("hello"); //打印 h System.out.println((char) buffer2.get()); //1.3 ByteBuffer.wrap(byte[] sr) buffer3 自动转为读模式 ByteBuffer buffer3 = ByteBuffer.wrap("hello".getBytes()); // 打印 h System.out.println((char)buffer3.get()); //2 ByteBuffer转字符串 //2.1 Buffer.put() buffer1.flip(); String s = StandardCharsets.UTF_8.decode(buffer1).toString(); //hello后面跟了一个乱码的字符 System.out.println(s); //2.2 Charset.encode("") String s1 = StandardCharsets.UTF_8.decode(buffer2).toString(); //在1.2时调用了一次get 所以打印为ello //推断出decode方法获取的是buffer2中未读取过的数据即从position开始,而非buffer2中全部数据 System.

CentOS7.8忘记密码后如何重置

本文中的CentOS是从阿里云ECS服务器上迁移而来的,详情请看 《2021阿里云ECS镜像导入本地VMware虚拟机》,重置密码流程和普通CentOS7略微不同,但无伤大雅。 进入内核引导界面 重启虚拟机,并且此页面加载时按 ↑ 或 ↓ 键(其它任意键也可),进入引导页面。 选择第四项,原因在开头的文章中提到过(非ECS迁移的CentOS7.8一般只有两项,选择第一项即可。),按下e进入编辑模式。 目前已知的可以进入单用户的方式有如下三种,这里以第三种方式为例 rd.breakinit = /bin/bashrw init = /sysroot/bin/sh 找到以linux16开头的行,向下寻找 ro,并将其替换为 rw init = /sysroot/bin/sh 注意:ECS迁移的CentOS此时需要特别注意!!!此处需要删除 net.ifnames=0 console=tty0 console=ttys0.115200n8 noibrs,否则会卡死无法进入系统。(因为此问题浪费了非常久的时间,找了很多资料也没解决,最后发现这里比其它的CentOS多了一段内容,删除后即可进入系统) 按下Ctrl+X或者F10,等待片刻即可进入系统。 此时还无法直接修改密码,需要使用chroot命令,即chroot /sysroot 再次执行passwd root,即修改root用户的用户名,输入新密码,记得修改为自己能够牢记的密码😂。出现successfully字样即为成功。 (可选) 如果修改过Linux的内核状态,此处需要使用如下命令重新标记。 touch /.autorelabel 最终重启系统 执行 reboot -f 或 exec /sbin/reboot 重新登录即可。

电脑有网但打不开网页怎么办?

明明刚交了宽带年费,本地连接显示一切正常,但是打开网页总有问题。 换浏览器重启无效。我该怎么办?放心吧!下面,微点阅读小编整理了一些网络链接正常却上不了网的解决方法。 对于经常上网的朋友来说,除了手机购物,在Pc端玩网页游戏是很多小伙伴的首选。但是有时候宽带链接是连接的,但是打开浏览器就上不了网,有时候甚至会出现断断续续的现象。在此,我请大家解决网页打不开的问题。希望对大家有帮助! 解决方案1 1.点击桌面右下角的windows图标打开“运行”对话框(或按win R),输入命令“cmD”进入msDos界面。 2.在msDos界面输入命令“ipconfig /all”,可以在显示结果界面查看本地网关和Dns信息,记录IP地址和Dns服务器号。 3.打开控制面板,双击网络连接,然后右键单击本地连接并选择属性。 4.单击“internet协议”,然后单击其属性。然后选中“手动设置Dns”为当前连接设置Dns。设置好刚刚记录的IP地址和Dns服务器输入后,再检查一下是否可以正常上网。 如果还是打不开网页,很可能是局域网中了ARP病毒。这可以通过静态绑定ARP操作来实现。 解决方案2 1.打开360安全卫士,选择“人工服务”,然后输入问题“网页打不开”。 2.找到问题的解决方法,然后点击-立即修复,等待修复完成,然后重启电脑正常上网。 以上是关于有网络却打不开网页的解决方案。 原文地址:https://www.weidianyuedu.com/content/5020074895951.html

算法题:给定一个字符串,字符串中包含一些空格,将字符串中由空格隔开的单词反序,并反转每个字符的大小写。

神策算法题 题目描述:对于一个长度为 n 字符串,首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写,比如"Hello World"变形后就变成了"wORLD hELLO"。 思路分析: 1. 将字符串转换成字符串数组,并反转[‘World’, ‘Hello’]。 2. 上述结果中的每一个字符提取到字符串数组中。 3. 遍历整个字符串数组,根据其中字符的Unicode值来判定大小写,如果是97-122之间,则表示为小写,将其转换成大写,如果是65-90之间,则表示为大写,转换成小写。将转换后的字符添加到result结果数组中。在每个单词结束后,添加空格分隔。 4. 遍历完成之后,将最后一个空格删掉pop()。 5. 将result结果数组转换成字符串格式。 可使用C++、Java、JavaScript、Python等语言,这里使用最简便的JavaScript脚本语言。 let n = "Hello World" var ans = function(str){ var result = [] // 把字符串转换成字符串数组,并反转['World', 'Hello'] var s = n.split(' ').reverse() // 将s中的每一个字符串转换成字符串数组 var ss = [] //[['W', 'o', 'r','l', 'd'], ['H','e', 'l', 'l', 'o']] for(var i = 0; i< s.length; i++){ ss.push(s[i].split("")) } for(let i = 0;i<ss.length;i++) { for(let j = 0; j < ss[i].

electron功能实现---添加全局快捷键、开机自启、选择安装路径

一、注册全局快捷键 采用globalShortcut,是主进程 ps:快捷键方式是全局的‘即使应用程序没有键盘焦点,它也仍然在持续监听键盘事件。在app模块的ready事件就绪之前,这个模块不能使用。 import { app, BrowserWindow, ipcMain, globalShortcut, } from "electron"; // 主窗口函数 createMainWindow() { globalShortcut.register("ctrl+F5", () => { app.relaunch(); app.exit(); }); globalShortcut.register("ctrl+F4", () => { this.mainWindow?.reload(); }); globalShortcut.register("ctrl+F6", () => { app.exit(); }); globalShortcut.register("F11", () => { // 是否全屏 if (this.mainWindow?.isFullScreen()) { // this.mainWindow?.minimize(); this.mainWindow?.setFullScreen(false); this.mainWindow?.setMenuBarVisibility(true); } else { this.mainWindow?.setFullScreen(true); this.mainWindow?.setMenuBarVisibility(false); } }); globalShortcut.register("ctrl+F12", () => { this.mainWindow?.webContents.openDevTools({ mode: "detach" }); }); } app.on('will-quit', () => { // 注销快捷键 globalShortcut.

Vue项目中特殊字体的使用

数字30是‘led’字体,下载.ttf文件,在页面中注册字体。 @font-face { font-famliy:"led" //字体命名 src:url("../assets/fonts/led.ttf") //文件路径 } .cude { //类中直接通过font-famliy引用 font-family:"led" }

LIO-SAM从0到1运行自己的数据集

LIO-SAM从0到1运行自己的数据集 前言 ​ 笔者在学习LIO_SAM时踩了不少坑,在此记录从开始到最后整个踩坑过程。文中参考了很多大佬的文章,我只是个搬运工。可以直接跳到第二部分从0到1实现 有疑问可以随时联系我,欢迎交流。 一.LIO-SAM简单介绍 (这一部分可以不看哦,干货在第二部分) ⼀种激光惯导紧耦合的SLAM框架,可在室内和室外实现效果不错的建图。 (1) ImageProjection 激光运动畸变校正 功能简介 1、利用当前激光帧起止时刻间的imu数据计算旋转增量,IMU里程计数据(来自ImuPreintegration)计算平移增量,进而对该帧激光每一时刻的激光点进行运动畸变校正(利用相对于激光帧起始时刻的位姿增量,变换当前激光点到起始时刻激光点的坐标系下,实现校正); (激光帧的起始数据——由IMU得到旋转增量,由IMU里程计得到平移增量,通过位姿增量,变换当前激光点到原始激光点,实现校正。) 2、同时用IMU数据的姿态角(RPY,roll、pitch、yaw)、IMU里程计数据的的位姿,对当前帧激光位姿进行粗略初始化。 订阅 订阅原始IMU数据; 订阅IMU里程计数据,来自ImuPreintegration,表示每一时刻对应的位姿; 订阅原始激光点云数据。 发布 发布当前帧激光运动畸变校正之后的有效点云,用于rviz展示; 发布当前帧激光运动畸变校正之后的点云信息,包括点云数据、初始位姿、姿态角、有效点云数据等,发布给FeatureExtraction进行特征提取。 (2) FeatureExtraction 点云特征提取 功能简介 对经过运动畸变校正之后的当前帧激光点云,计算每个点的曲率,进而提取角点、平面点(用曲率的大小进行判定)。 订阅 订阅当前激光帧运动畸变校正后的点云信息,来自ImageProjection。 发布 发布当前激光帧提取特征之后的点云信息,包括的历史数据有:运动畸变校正,点云数据,初始位姿,姿态角,有效点云数据,角点点云,平面点点云等,发布给MapOptimization; 发布当前激光帧提取的角点点云,用于rviz展示; 发布当前激光帧提取的平面点点云,用于rviz展示。 (3) ImuPreintegration IMU预积分 TransformFusion类 功能简介 主要功能是订阅激光里程计(来自MapOptimization)和IMU里程计,根据前一时刻激光里程计,和该时刻到当前时刻的IMU里程计变换增量,计算当前时刻IMU里程计;rviz展示IMU里程计轨迹(局部)。 订阅 订阅激光里程计,来自MapOptimization; 订阅imu里程计,来自ImuPreintegration。 发布 发布IMU里程计,用于rviz展示; 发布IMU里程计轨迹,仅展示最近一帧激光里程计时刻到当前时刻之间的轨迹。 ImuPreintegration类 功能简介 用激光里程计,两帧激光里程计之间的IMU预计分量构建因子图,优化当前帧的状态(包括位姿、速度、偏置); 以优化后的状态为基础,施加IMU预计分量,得到每一时刻的IMU里程计。 订阅 订阅IMU原始数据,以因子图优化后的激光里程计为基础,施加两帧之间的IMU预计分量,预测每一时刻(IMU频率)的IMU里程计; 订阅激光里程计(来自MapOptimization),用两帧之间的IMU预计分量构建因子图,优化当前帧位姿(这个位姿仅用于更新每时刻的IMU里程计,以及下一次因子图优化)。 发布 发布imu里程计; (4) MapOptimization 因子图优化 功能简介 1、scan-to-map匹配:提取当前激光帧特征点(角点、平面点),局部关键帧map的特征点,执行scan-to-map迭代优化,更新当前帧位姿; 2、关键帧因子图优化:关键帧加入因子图,添加激光里程计因子、GPS因子、闭环因子,执行因子图优化,更新所有关键帧位姿; 3、闭环检测:在历史关键帧中找距离相近,时间相隔较远的帧设为匹配帧,匹配帧周围提取局部关键帧map,同样执行scan-to-map匹配,得到位姿变换,构建闭环因子数据,加入因子图优化。 订阅 1、订阅当前激光帧点云信息,来自FeatureExtraction; 2、订阅GPS里程计; 3、订阅来自外部闭环检测程序提供的闭环数据,本程序没有提供,这里实际没用上。 发布 1、发布历史关键帧里程计; 2、发布局部关键帧map的特征点云; 3、发布激光里程计,rviz中表现为坐标轴;

【值符】嵌入式必备知识点&面试点

【腾蛇】 最近在看外面的机会,刷刷嵌入式必备的知识点问题,也是基础,一定要深入了解,不单单只是停留在表面,原理才是王道 真谛!!! 1、I2C 必备知识点 2、SPI 必备知识点 3、uart 必备知识点 4、display (video out) 必备知识点 5、camera (video in) 必备知识点 6、audio 必备知识点 7、touch 必备知识点 8、usb 必备知识点 9、watchdog 必备知识点 10、rtc 必备知识点 11、pcie 必备知识点 12、DDR 必备知识点 13、emmc & nor flash & flash 必备知识点

Android返回多级Activity

Android返回多级Activity 在写任务的时候,发现返回键使用finish方法时需要一级一级返回,若使用传参方法修改返回事件则会变得比较为复杂。网上搜了一下简便一点的方法。大致方法如下 1.修改mainfest 假设activity为A activity->…->B activity。需要达到的效果为点击B返回按钮时,跳转回A界面。第一步需要修改的为在mainfest中在A中增加android:launchMode=“singleTop”` <activity android:name=".A" android:theme="@android:style/Theme.NoTitleBar" android:windowSoftInputMode="adjustPan" android:launchMode="singleTop"/> 2.在 Activity中重写onNewIntent方法 代码如下 @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (0 != (Intent.FLAG_ACTIVITY_CLEAR_TOP&intent.getFlags())) { finish(); } } 3.修改B Activity中的返回按钮时间 代码如下 bt_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Bundle bundle = new Bundle(); Intent intent = new Intent(B.this, A.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.putExtras(bundle); startActivity(intent); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); } });

求解递归方程的方法:递归树法

示例一 T(n)=2T(n/2)+n-1,求T(n)上界 将每一层的代价求和:(假设k层,k=nlogn) T(n)=kn + n-1 + n-2 + …… + n-2^(k-1) T(n)=kn - (2^k -1)=nlogn - n + 1=O(nlogn) 示例二 根据式 T(n)=3T(n/4)+ θ(n2 ),写出其递归树,并计算其时间复杂度。(要求写出时间复杂度的推导过程 ) 深度求解 将每一层代价求和

浏览器的任务队列-宏任务、微任务的执行顺序

重点: 1、首先要清楚常见的宏任务和微任务有哪些 宏任务:setTimeout、setInterval、ajax; 微任务:promise、async/await 2、其次要清楚的是 微任务 执行时机比 宏任务 早 1、微任务和宏任务的执行规则 此处需要注意的是,当所有微任务执行完毕后才会取出一个宏任务执行,宏任务中存在微任务的话还是需要将所有微任务执行完在取出一个宏任务继续执行。 2、JS运行机制 此处不做过多介绍,主要注意以下几点: js是单线程,所谓单线程就是指JS在引擎中只负责解释和执行JS代码的线程只有一个。这点事核心,将来也不会改变。同步任务会在调用栈中按照顺序等待主线程一次执行;异步任务会在异步任务有了结果后,将注册的回调函数放在任务队列中,等待主线程空闲的时候,被读取到栈内等待主线程的执行Promise本身事同步的立即执行函数,他的.then()和catch()方法是异步的(微任务)async/await是建立在Promise机制上,当调用一个async函数时,会返回一个promise对象,而await操作符后面的表达式就是这个promise,返回值实际上就是peomise的回调函数resolve的参数。async方法执行时,遇到await会立即执行表达式,async表达式定义的函数是立即执行的,await表达式后面的代码放在微任务执行,包括赋值。 以下举几个例子 async function test1() { console.log("test1 begin"); const result = await test2(); console.log("result", result); console.log("test1 end"); } async function test2() { console.log("test2"); } console.log("script begin"); test1(); console.log("script end"); 控制台打印: 前面注意事项5中说了,async方法执行时,遇到await会立即执行表达式,所有第三次输出应该是test2。await后面的代码将放在微任务中排队。 结果: 1 4 7 5 2 3 6

报错:“ReferenceError: echarts is not defined“

前言:现在在敲Echarts绘制的图形,折线图,柱状图,饼状图,封装了一个公共组件~ 我就很烦,写完代码之后,要解决报错问题,但是所有问题都有解决的法子,所以要有耐心~~~ 把报错的解决了就好,我找到了报错原因 【错误写法】 import * as echart from "echarts"; 少写了一个s,应该写成【正确写法】 import * as echarts from "echarts"; 这个Echarts引入的时候报了很多错误,一点点解决就好。能解决的问题都不是问题。 注意一点,敲代码的时候一定要注意字母拼写,很多错误可能是因为自己粗心报的错 最后,加油,前端冲冲冲!!!