【启发式算法】RRT*算法详细介绍(Python)

        📢本篇文章是博主人工智能(AI)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉启发式算法专栏:

       【启发式算法】(9)---《RRT*算法详细介绍(Python)》

【启发式算法】RRT*算法详细介绍(Python)

目录

1. RRT*算法

2.算法原理

RRT*与RRT的区别

3.算法步骤

步骤详细说明

4.RRT*的关键原理

1. 树的扩展

2. 路径优化

3. 连接最短路径

4. 渐进最优性

[Python] RRT*算法实现

[Results] 运行结果

[Notice]  注意事项

5.优点与不足

6.总结


1. RRT*算法

        RRT*算法(Rapidly-exploring Random Tree Star)是一种用于机器人路径规划的算法,旨在为机器人找到从起点到目标的最短路径,同时避免障碍物。它是基于RRT(Rapidly-exploring Random Tree)算法的改进版,具有更高的路径质量和优化能力。RRT*的关键特点是它能够在搜索过程中逐渐优化路径,最终找到一条接近最短的路径。


2.算法原理

        想象你在一个森林里,从某个点出发(起点),想找到一条通向小屋(终点)的路径。森林里有很多树(障碍物),你看不到小屋在哪里。你开始随机地朝不同方向走,记录你走过的路,如果碰到障碍就绕开。

这就是 RRT 的基本思路:“快速而随机地扩展路径”

而 RRT* 在这个基础上更聪明:每走一步,它还会看一下有没有更短的路线可以替换原来的路线。

RRT*与RRT的区别

        RRT*算法与普通的RRT算法相比,最大的区别在于优化过程。RRT只能快速探索空间,但不保证找到最优路径。而RRT*则通过不断优化已经找到的路径,保证能找到一条接近最优的路径。


3.算法步骤

        RRT*的核心思想是通过不断扩展一个随机树,探索搜索空间,同时在扩展过程中优化路径。算法的基本步骤如下:

  1. **初始化树**:从起点出发,初始化一个树(可以是RRT树),树的根节点是起点。
  2.  **随机采样**:在空间中随机采样一个点,这个点是机器人可能需要经过的位置。
  3.  **扩展树**:通过找到树中距离该随机采样点最近的节点,然后朝这个随机点扩展一小步。树会不断向外扩展,探索新的区域。
  4. **连接路径**:扩展树的过程中,算法会检查是否能够找到更优的路径。如果新的节点能够连接到树中某个更接近目标的节点,或者可以替换掉原本的路径,那么就会更新树的结构,寻找更短的路径。
  5. **优化路径**:算法会在树扩展的过程中,反复优化路径,以确保最终路径是最优的。

步骤详细说明

        假设我们有一个机器人,起点在`(0, 0)`,目标点在`(10, 10)`,空间中有障碍物。我们来一步步看RRT*算法是如何工作的:

 1. 初始化树

        我们从起点`(0, 0)`开始,构建一个初始树。这个树只有一个节点,即起点。

2. 随机采样

        我们从空间中随机选择一个点,假设选择的是`(7, 4)`。这个点并不一定在树上,但我们希望树可以通过某种方式扩展到这个点。

3. 扩展树

        找到树中离`(7, 4)`最近的节点,比如起点`(0, 0)`,然后从`(0, 0)`朝着`(7, 4)`方向扩展,假设扩展的步长是1,所以新节点的位置可能是`(1, 0.57)`。这个新节点被加入到树中,树就变得更大了。

4. 检查路径优化

        如果新的节点在扩展时发现了更短的路径,或者有可能替代之前的路径,算法就会更新路径。例如,如果扩展的过程中,我们发现从`(1, 0.57)`到目标点`(10, 10)`的路径比原来的路径更短,算法就会更新路径。

5. 重复以上步骤

        算法会继续重复以上步骤,直到找到一条从起点到目标点的路径。随着树的扩展,路径不断优化,最终得到一条最短的路径。

6. 结束

        当树扩展到目标点附近,算法停止,输出路径。


4.RRT*的关键原理

        RRT*的核心原理不仅仅是树的扩展,而是在每次扩展时进行路径优化。为了保证路径的最优性,RRT*会在每次扩展时,检查是否能找到更短的路径。这个过程实际上是一个渐进最优的过程。

1. 树的扩展

        树的扩展是RRT*的基本操作,在空间中随机选择一个点,并扩展树的结构。这一过程类似于RRT算法中的“树扩展”步骤,但RRT*在扩展时增加了路径优化步骤。

给定一个随机采样点 q_{\text{rand}},树中某个节点q_{\text{nearest}},RRT*的目标是从 q_{\text{nearest}}q_{\text{rand}} 的q_{\text{new}}

q_{\text{new}} = q_{\text{nearest}} + \Delta t \cdot \frac{q_{\text{rand}} - q_{\text{nearest}}}{\|q_{\text{rand}} - q_{\text{nearest}}\|}

其中,\Delta t是扩展步长,q_{\text{new}}是新节点。

      计算 新节点的代价:假设在某一时刻,树中有一个节点 q_{\text{parent}},我们从这个节点扩展到新节点 q_{\text{new}},则新节点的代价可以定义为:

C(q_{\text{new}}) = C(q_{\text{parent}}) + \text{cost}(q_{\text{parent}}, q_{\text{new}})
其中,\text{cost}(q_{\text{parent}}, q_{\text{new}})是从父节点到新节点的代价,通常计算为两点之间的欧几里得距离:

\text{cost}(q_{\text{parent}}, q_{\text{new}}) = \|q_{\text{new}} - q_{\text{parent}}\|

2. 路径优化

        在RRT*中,路径优化是一个至关重要的步骤,它能够保证路径的最优性。优化过程的核心思想是检查新扩展的节点是否可以通过某些已有节点来形成更短的路径。具体来说,如果我们有两个节点 q_{\text{new}} 和 q_{\text{neighbour}},那么如果经过 q_{\text{new}}q_{\text{neighbour}} 的路径比原有路径更短,就更新路径。

        在这个过程中,RRT*需要计算从新节点到树中某些节点的路径长度,并选择能够带来路径优化的节点。这个步骤在每次扩展时都进行,最终产生一条近似最优的路径。

        假设新节点 q_{\text{new}} 通过与树中的节点 q_{\text{neighbour}}连接来优化路径。如果经过q_{\text{neighbour}}的路径比原路径更短,则更新路径。即,若有:

C(q_{\text{neighbour}}) > C(q_{\text{new}}) + \text{cost}(q_{\text{new}}, q_{\text{neighbour}})

则更新 q_{\text{neighbour}} 的父节点为 q_{\text{new}},并更新路径。

3. 连接最短路径

        RRT*的优化不仅体现在路径本身,还包括通过连接新节点和树中的某些节点,生成最短路径。假设已经有了一条路径 \pi_1,从起点到目标点。现在我们希望通过添加新的节点来更新这条路径。若新的路径 \pi_2比原路径更短,则替换原路径。更新过程可以通过“Rewiring”来完成,即调整树结构,使路径变得更短。

4. 渐进最优性

        RRT*的一个显著特征是它的渐进最优性。随着扩展步数的增加,RRT*会不断优化路径,最终趋近于最优路径。这种渐进最优性可以通过以下公式描述:

        在给定的空间中,如果我们对树进行足够多的扩展,路径的代价 C_{\text{path}}会趋近于最优路径的代价 C^*,满足:

C_{\text{path}} \to C^* \quad \text{as} \quad n \to \infty

其中,n$是扩展的次数。


[Python] RRT*算法实现

        RRT*算法我也是基于一位大佬的算法应用的,在大佬的代码基础上做了一点修改。

 项目代码我已经放入下面链接里面,可以通过下面链接跳转:🔥

【启发式算法】--- RRT*算法 

若是下面代码复现困难或者有问题,也欢迎评论区留言

"""《RRT*算法实现》时间:2025.06.25"""
import math
import os
import sysimport matplotlib.pyplot as plt
from celluloid import Camera  # 保存动图时用,pip install celluloid
sys.path.append("../RRT")
try:from rrt_planning import RRT
except ImportError:raiseshow_animation = Trueclass RRTStar(RRT):"""Class for RRT Star planning"""class Node(RRT.Node):def __init__(self, x, y):super().__init__(x, y)self.cost = 0.0def __init__(self,start,goal,obstacle_list,rand_area,expand_dis=3.0,goal_sample_rate=20,max_iter=50000,connect_circle_dist=50.0,search_until_max_iter=False,robot_radius=0.0):"""Setting Parameterstart:Start Position [x,y]goal:Goal Position [x,y]obstacleList:obstacle Positions [[x,y,size],...]randArea:Random Sampling Area [min,max]"""super().__init__(start, goal, obstacle_list, rand_area, expand_dis,goal_sample_rate, max_iter,robot_radius=robot_radius)self.connect_circle_dist = connect_circle_distself.goal_node = self.Node(goal[0], goal[1])self.search_until_max_iter = search_until_max_iterdef planning(self, animation=True, camera=None):"""rrt star path planninganimation: flag for animation on or off ."""self.node_list = [self.start]for i in range(self.max_iter):if i % 100 == 0:print("Iter:", i, ", number of nodes:", len(self.node_list))# print("Iter:", i, ", number of nodes:", len(self.node_list))rnd = self.sample_free()nearest_ind = self.get_nearest_node_index(self.node_list, rnd)new_node = self.steer(self.node_list[nearest_ind], rnd,self.expand_dis)near_node = self.node_list[nearest_ind]# 计算代价,欧氏距离new_node.cost = near_node.cost + math.hypot(new_node.x-near_node.x, new_node.y-near_node.y)if self.obstacle_free(new_node, self.obstacle_list, self.robot_radius):near_inds = self.find_near_nodes(new_node) # 找到x_new的邻近节点node_with_updated_parent = self.choose_parent(new_node, near_inds) # 重新选择父节点# 如果父节点更新了if node_with_updated_parent:# 重布线self.rewire(node_with_updated_parent, near_inds)self.node_list.append(node_with_updated_parent)else:self.node_list.append(new_node)if animation and i % 100 ==0:self.draw_graph(rnd, camera)if ((not self.search_until_max_iter) and new_node):  # if reaches goallast_index = self.search_best_goal_node()if last_index is not None:return self.generate_final_course(last_index)print("reached max iteration")last_index = self.search_best_goal_node()if last_index is not None:return self.generate_final_course(last_index)return Nonedef choose_parent(self, new_node, near_inds):"""在新产生的节点 $x_{new}$ 附近以定义的半径范围$r$内寻找所有的近邻节点 $X_{near}$,作为替换 $x_{new}$ 原始父节点 $x_{near}$ 的备选我们需要依次计算起点到每个近邻节点 $X_{near}$ 的路径代价 加上近邻节点 $X_{near}$ 到 $x_{new}$ 的路径代价,取路径代价最小的近邻节点$x_{min}$作为 $x_{new}$ 新的父节点Arguments:--------new_node, Noderandomly generated node with a path from its neared pointThere are not coalitions between this node and th tree.near_inds: listIndices of indices of the nodes what are near to new_nodeReturns.------Node, a copy of new_node"""if not near_inds:return None# search nearest cost in near_indscosts = []for i in near_inds:near_node = self.node_list[i]t_node = self.steer(near_node, new_node)if t_node and self.obstacle_free(t_node, self.obstacle_list, self.robot_radius):costs.append(self.calc_new_cost(near_node, new_node))else:costs.append(float("inf"))  # the cost of collision nodemin_cost = min(costs)if min_cost == float("inf"):print("There is no good path.(min_cost is inf)")return Nonemin_ind = near_inds[costs.index(min_cost)]new_node = self.steer(self.node_list[min_ind], new_node)new_node.cost = min_costreturn new_nodedef search_best_goal_node(self):dist_to_goal_list = [self.calc_dist_to_goal(n.x, n.y) for n in self.node_list]goal_inds = [dist_to_goal_list.index(i) for i in dist_to_goal_listif i <= self.expand_dis]safe_goal_inds = []for goal_ind in goal_inds:t_node = self.steer(self.node_list[goal_ind], self.goal_node)if self.obstacle_free(t_node, self.obstacle_list, self.robot_radius):safe_goal_inds.append(goal_ind)if not safe_goal_inds:return Nonemin_cost = min([self.node_list[i].cost for i in safe_goal_inds])for i in safe_goal_inds:if self.node_list[i].cost == min_cost:return ireturn Nonedef find_near_nodes(self, new_node):"""1) defines a ball centered on new_node2) Returns all nodes of the three that are inside this ballArguments:---------new_node: Nodenew randomly generated node, without collisions betweenits nearest nodeReturns:-------listList with the indices of the nodes inside the ball ofradius r"""nnode = len(self.node_list) + 1r = self.connect_circle_dist * math.sqrt((math.log(nnode) / nnode))# if expand_dist exists, search vertices in a range no more than# expand_distif hasattr(self, 'expand_dis'):r = min(r, self.expand_dis)dist_list = [(node.x - new_node.x)**2 + (node.y - new_node.y)**2for node in self.node_list]near_inds = [dist_list.index(i) for i in dist_list if i <= r**2]return near_indsdef rewire(self, new_node, near_inds):"""For each node in near_inds, this will check if it is cheaper toarrive to them from new_node.In such a case, this will re-assign the parent of the nodes innear_inds to new_node.Parameters:----------new_node, NodeNode randomly added which can be joined to the treenear_inds, list of uintsA list of indices of the self.new_node which containsnodes within a circle of a given radius.Remark: parent is designated in choose_parent."""for i in near_inds:near_node = self.node_list[i]edge_node = self.steer(new_node, near_node)if not edge_node:continueedge_node.cost = self.calc_new_cost(new_node, near_node)no_collision = self.obstacle_free(edge_node, self.obstacle_list, self.robot_radius)improved_cost = near_node.cost > edge_node.costif no_collision and improved_cost:near_node.x = edge_node.xnear_node.y = edge_node.ynear_node.cost = edge_node.costnear_node.path_x = edge_node.path_xnear_node.path_y = edge_node.path_ynear_node.parent = edge_node.parentself.propagate_cost_to_leaves(new_node)def calc_new_cost(self, from_node, to_node):d, _ = self.calc_distance_and_angle(from_node, to_node)return from_node.cost + ddef propagate_cost_to_leaves(self, parent_node):for node in self.node_list:if node.parent == parent_node:node.cost = self.calc_new_cost(parent_node, node)self.propagate_cost_to_leaves(node)def main():print("Start " )fig = plt.figure(1)camera = Camera(fig) # 保存动图时使用# camera = None # 不保存动图时,camara为Noneshow_animation = True# ====Search Path with RRT====# # 生成100个随机元组的列表import random# obstacle_list = [(random.randint(0, 200), random.randint(0, 200), random.randint(1, 10)) for _ in range(100)]# 分别生成100个x、y坐标对和100个size值positions = [(random.randint(0, 180), random.randint(0, 180)) for _ in range(100)]sizes = [random.randint(1, 10) for _ in range(100)]# 合并为100个三元组obstacle_list = [(x, y, size) for (x, y), size in zip(positions, sizes)]while True:goal = [random.randint(180, 199), random.randint(180, 199)]goal_ = tuple(goal)if goal_ not in positions:break# Set Initial parametersrrt_star = RRTStar(start=[0, 0],goal=goal,rand_area=[0, 200],obstacle_list=obstacle_list,expand_dis=3,robot_radius=0.8)path = rrt_star.planning(animation=show_animation,camera=camera)if path is None:print("Cannot find path")else:print(f"found path!!,路径长度{len(path)},路径{path}")# Draw final pathif show_animation:rrt_star.draw_graph(camera=camera)plt.plot([x for (x, y) in path], [y for (x, y) in path], 'r--')plt.grid(True)if camera!=None:camera.snap()animation = camera.animate()animation.save('trajectory.gif')plt.show()if __name__ == '__main__':main()

如果需要完整代码实现,可在下面自行前往大佬的github,链接。 


[Results] 运行结果


[Notice]  注意事项

​# 环境配置
Python                  3.11.5
torch                   2.1.0
torchvision             0.16.0
gym                     0.26.2

5.优点与不足

 优点:

1. **最优性**:通过不断优化路径,RRT\*能够提供最短路径(在有限的计算时间内)。
2. **灵活性**:适用于高维空间和复杂环境,能够处理障碍物的影响。
3. **渐进性**:随着搜索的进行,路径会越来越优化,适合动态环境。

不足:

1. **计算量大**:由于需要在每一步优化路径,计算量较大,可能不适合实时性要求高的应用。
2. **收敛速度慢**:对于复杂环境,算法可能需要较长时间才能找到最优路径。


6.总结

        RRT*算法是一种高效的路径规划算法,其关键在于通过路径优化和渐进最优性来生成接近最优的路径。通过在树扩展过程中不断进行路径优化,RRT*能够解决复杂环境中的路径规划问题。它通过多次扩展和优化,在计算资源允许的情况下,可以产生最优或近似最优的路径。RRT*算法特别适用于复杂的环境。虽然计算量较大,但它的最优性使得它在许多应用中仍然很有价值。

 更多强化学习文章,请前往:【启发式算法】专栏


        博客都是给自己看的笔记,如有误导深表抱歉。文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者添加VX:Rainbook_2,联系作者。✨

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

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

相关文章

Docker架构深度解析:从核心概念到企业级实践

Docker架构深度解析&#xff1a;从核心概念到企业级实践一、Docker架构全景图1.1 整体架构示意图二、核心组件深度解析2.1 Docker Daemon工作机制三、镜像与容器原理3.1 镜像分层结构3.2 容器生命周期四、网络架构详解4.1 网络模式对比4.2 Bridge网络实现原理五、存储架构与实践…

PPT自动化 python-pptx - 8: 文本(text)

在使用 python-pptx 库操作 PowerPoint 文档时&#xff0c;理解文本的结构和处理方式至关重要。本文将深入探讨文本在形状中的组织层级、访问方式以及各级别的格式化选项。文本容器与层级结构可容纳文本的形状&#xff1a; 只有自动形状 (Auto shapes) 和表格单元格 (table cel…

使用realsense进行目标检测并标识目标深度

涉及知识点都在代码中注释了&#xff0c;直接看代码 // This example is derived from the ssd_mobilenet_object_detection opencv demo // and adapted to be used with Intel RealSense Cameras // Please see https://github.com/opencv/opencv/blob/master/LICENSE#includ…

OpenWrt Network configuration

OpenWrt Network configuration device 和 interface 关系device device 表示底层的网络设备&#xff0c;如物理网卡、桥接设备&#xff08;bridge&#xff09;、VLAN 设备等。 通过 config device 定义&#xff0c;描述设备类型、端口成员、VLAN 等属性。 例如&#xff1a;br…

VuePress 使用详解

一、核心概念 VuePress 是 Vue.js 团队开发的静态网站生成器&#xff0c;专为技术文档优化&#xff0c;具备以下特性&#xff1a; Markdown 优先&#xff1a;原生支持 Markdown 语法扩展Vue 驱动&#xff1a;可在 Markdown 中使用 Vue 组件默认主题优化&#xff1a;内置响应式…

AI大模型前沿:Muyan-TTS开源零样本语音合成技术解析

AI大模型前沿&#xff1a;Muyan-TTS开源零样本语音合成技术解析引言&#xff1a;语音合成技术的演进与Muyan-TTS的突破性意义语音合成&#xff08;Text-to-Speech, TTS&#xff09;技术作为人机交互的核心接口之一&#xff0c;自20世纪30年代贝尔实验室首次尝试电子语音合成以来…

c# everthing.exe 通信

1 获取everthing进程 调用 Everything 搜索创建SearchWithEverything函数using Microsoft.Win32; using System; using System.Diagnostics; using System.IO; using System.Management; using System.Text;class EverythingHelper {// 方法 1&#xff1a;从进程获取路径publi…

Gitee:中国企业级DevOps平台的本土化突围之路

Gitee&#xff1a;中国企业级DevOps平台的本土化突围之路 在国内数字化转型浪潮下&#xff0c;DevOps平台作为企业研发效能提升的核心引擎&#xff0c;正在经历从工具到生态的全面升级。作为国内领先的一站式DevOps解决方案&#xff0c;Gitee凭借其本土化优势与全链路服务能力&…

C++法则22:运算符 ::* 和 ->* 和 ::* 是独特的整体运算符,是不可分的。

C法则22&#xff1a;运算符 ::* 和 ->* 和 ::* 是独特的整体运算符&#xff0c;是不可分的。1. ::*&#xff08;成员指针声明符&#xff09;作用&#xff1a;用于声明一个指向类成员的指针。语法&#xff1a;ReturnType (ClassName::*pointerName) &ClassName::MemberN…

Linux系统管理习题

Linux 系统管理练习题 1.请为此虚拟机配置以下网络参数&#xff1a; 1&#xff09;主机名&#xff1a;chenyu.example.com &#xff08;将chenyu改成自己名字的全拼&#xff09; 2&#xff09;IP 地址&#xff1a;192.168.100.100/24 3&#xff09;默认网关&#xff1a;192.168…

SQL166 每天的日活数及新用户占比

SQL166 每天的日活数及新用户占比 题目理解 本SQL查询旨在分析用户活跃数据&#xff0c;计算两个关键指标&#xff1a; 每日活跃用户数(DAU)每日新增用户占比(新用户占活跃用户的比例) 解题思路 1. 数据准备阶段 首先我们需要获取所有用户的活跃记录&#xff0c;包括&…

【33】C# WinForm入门到精通 ——表格布局器TableLayoutPanel【属性、方法、事件、实例、源码】

WinForm 是 Windows Form 的简称&#xff0c;是基于 .NET Framework 平台的客户端&#xff08;PC软件&#xff09;开发技术&#xff0c;是 C# 语言中的一个重要应用。 .NET 提供了大量 Windows 风格的控件和事件&#xff0c;可以直接拿来使用。 本专栏内容是按照标题序号逐渐…

uv使用教程

以下是使用 Python 包管理工具 uv 的常见命令指南。uv 是由 Astral&#xff08;Ruff 的开发者&#xff09;开发的高性能 Python 包安装器和解析器&#xff0c;旨在替代 pip 和 pip-tools&#xff1a; 1. 安装 uv uv官网仓库 # Linux/macOS curl -Ls https://astral.sh/uv/in…

SpringBoot3.x入门到精通系列:1.1 简介与新特性

SpringBoot 3.x 简介与新特性 &#x1f4d6; 什么是SpringBoot SpringBoot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化Spring应用的初始搭建以及开发过程。SpringBoot集成了大量常用的第三方库配置&#xff0c;SpringBoot应用中这些第三方库几乎可以零配…

二、搭建springCloudAlibaba2021.1版本分布式微服务-Nacos搭建及服务注册和配置中心

nacos介绍 1、Nacos简介 Nacos 是阿里巴巴推出来的一个新开源项目&#xff0c;这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、…

浅谈物联网嵌入式程序开发源码技术方案

在物联网蓬勃发展的时代&#xff0c;嵌入式程序作为连接硬件与软件的桥梁&#xff0c;发挥着至关重要的作用。以“边缘智能 云协同”为核心&#xff0c;为工业、医疗、家居、农业、智慧城市五大场景提供稳定、低功耗、可扩展的物联网终端与平台一体化解决方案。以下董技叔软件…

【笔记】重学单片机(51)

为学习嵌入式做准备&#xff0c;重新拿起51单片机学习。此贴为学习笔记&#xff0c;仅记录易忘点&#xff0c;实用理论基础&#xff0c;并不是0基础。 资料参考&#xff1a;清翔零基础教你学51单片机 51单片机学习笔记1. C语言中的易忘点1.1 数据类型1.2 位运算符1.3 常用控制语…

C++现代Redis客户端库redis-plus-plus详解

&#x1f680; C现代Redis客户端库redis-plus-plus详解&#xff1a;告别繁琐的hiredis&#xff0c;拥抱现代C的Redis操作 &#x1f4c5; 更新时间&#xff1a;2025年07月28日 &#x1f3f7;️ 标签&#xff1a;C | Redis | redis-plus-plus | 现代C | 后端开发 文章目录&#x…

Redis存储原理与数据模型(上)

一、Redis数据模型 1.1、查看Redis数据定义&#xff1a; typedef struct redisDb {kvstore *keys; /* The keyspace for this DB 指向键值存储的指针&#xff0c;用于快速访问和修改数据库中的键值对*/kvstore *expires; /* Timeout of keys with a t…

视频生成模型蒸馏的方法

1.fastvideo https://github.com/hao-ai-lab/FastVideohttps://github.com/hao-ai-lab/FastVideo Distillation support Recipes for video DiT, based on PCM. Support distilling/finetuning/inferencing state-of-the-art open video DiTs: 1. Mochi 2. Hunyuan. 2.l