自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(625)
  • 收藏
  • 关注

原创 【机械臂模块项目实战】机械臂轨迹规划、跟踪控制方向

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对机械臂轨迹规划、跟踪控制方向做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容复杂机器人系统(人形机器人、多足机器人和移动物体的机械臂等)【防盗标记–盒子君hzj】的运动规划轨迹和控制是富有挑战性的问题,机器人不仅需要时刻控制多个关节的自由度,还需要处理和环境物体之间的接触、摩擦以及碰撞,这些环境交互给机器人系统带来了非常复杂的运动约束。

2022-11-08 19:16:14 4067

原创 【局部规划模块项目实战】基于Frenet车道线坐标系,结合DP探索、QP优化实现无人车速度轨迹生成并优化

本文先对基于Frenet车道线坐标系,采用DP探索、QP优化进行速度解耦局部规划做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

2022-11-06 23:22:44 2566 4

原创 【全局路径规划模块全覆盖算法】覆盖式路径规划

【路径探索篇】(5)全局路径规划

2022-11-06 23:21:42 2948

原创 【局部规划模块曲线算法】路径曲线插值、拟合和逼近的区别

全局路径由一系列路径点构成,这些路径点包含空间位置信息,也可以包含姿态信息,但不需要与时间相关。轨迹则在路径的基础上加入了时间约束,轨迹点是一种特殊形式的路径点,它在路径点的基础上加入了时间信息。本文先对路径插值与抽稀篇做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容在选择插值、拟合或逼近方法时,需要考虑路径的用途、所需的精度以及计算资源的限制。对于需要高精度的应用场景,如精密制造或医疗手术,插值方法可能是首选。

2022-11-06 17:52:23 1102 1

原创 【局部规划模块曲线算法】曲线平滑介绍

本文先对轨迹平滑问题做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容(1)适合给移动机器人运动的路径【满足运动学,高阶平滑】(2)高阶的运动学不能够突变的【至少三阶的加速度不能突变,最好四阶的jerk和五阶的snap也不能突变】(3)在转弯的地方不会停下来(4)加减速均衡,节省能量(5)节省时间的。

2022-04-15 16:12:58 5143 3

原创 【行为决策模块项目实战】解耦控制--多控制器管理与切换的方法(附C++代码)

[请添加图片描述](https://img-blog.csdnimg.cn/c11300d9e4fe421e9070f474a468d1db.jpeg)本文先对多控制器管理与切换的方法做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容VERTICAL_VEL, //垂直速度PID控制器VERTICAL_POS, //垂直位置PID控制器HORIZONTAL, //水平速度PID控制器YAW, //航向角yaw位置逻辑控制器。

2021-12-06 14:37:41 962 1

原创 【控制模块项目实战】车线控底盘开发

无人车&无人机导航合集本文先对无人车线控底盘开发做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容线控系统的主要作⽤是减少复杂的机械传动机构,使整体质量更轻,降低油耗,降低制造成本,控制更简洁同时便于增加计算机辅助控制。线控技术包括很多部分,如线控转向,线控制动,【防盗标记–盒子君hzj】线控油⻔和线控悬架等都属于线控技术范畴。

2021-11-06 16:53:07 3716 2

原创 【规控模块项目实战】决策规划控制方向的架构部署

无人车&无人机导航合集提示:以下是本篇文章正文内容我认为,任务决策模块比较偏业务层了,具体的根据机器人/无人驾驶业务层得需求进行设计根据业务量的复杂程度,选用不同的任务决策工具和方法,实现既能满足现在的业务需求,又能又一定的拓展性全局路径规划算法难度不算复杂,一般根据高精度地图、栅格地图或者其他地图格式,从出发点到目标点之间的纯几何路径规划,无关时间序列,无关车辆动力学(位置速度加速度),得到一条可通行的路径。

2021-10-24 16:35:51 2935 2

原创 运动轨迹预测

将车辆状态和车道段作为输入,该模型用于提供车辆可能采用每个车道序列的概率,希望模型能够学习新的行为因此应该使用观测数据对模型进行经验性训练,在训练中将真实的车辆行为提供给模型,不仅包括车道段和对象的状态,还包括对象最终选择哪条车道序列。基于车辆的物理学来进行预测的方法, 包括基于车辆动力学模型, 车辆运动学模型. 动力学模型的预测方法可能会非常复杂, 但是对于预测方法来说, 复杂的动力学模型带来的效果提升非常有限. 在大部分情况下, 简单的运动学模型(通常使用自行车模型)即可满足预测需求.

2025-04-07 08:51:22 300

原创 【路径平滑】窗口滑动滤波结合随机梯度下降法实现平滑路径

在移动过程中,为了保证路径无碰撞,需要进行碰撞检测,当移动后的点发生碰撞时,不对该点移动操作。在定义了平滑度后,可以发现通过移动P点的位置,平滑度会发生改变,那么当平滑度最小时,P的位置在哪个地方,或者说P点朝哪个方向移动多少距离?这是一个最小值问题。依次选取5个路径点定义平滑度与路径点的关系,通过移动第3个点的位置,求解出使5个路径点平滑度最小的值,梯度方向为第3个点的移动方向,如下图所示。(2)Pa为P−2 与P的中点,Pb 为P−1与P1的中点,Pc为P2 与P的中点。4、平滑度的定义不唯一;

2025-04-07 08:49:31 433

原创 【路径平滑】窗口滑动滤波结合共轭梯度下降法实现平滑路径

对于一个 二次型优化问题:一般情况下,分别用 梯度下降法(GD) 和 共轭方向法(CG),有如下图的收敛轨迹:显然可以看出,梯度下降法需要经过多次迭代,而共轭方向法只需要经过两次迭代。

2025-04-07 08:49:04 586

原创 【轨迹后端优化】PiecewiseJerkPathOptimizer多项式速度优化

算法入口在 planning\tasks\optimizers\path_time_heuristic\path_time_heuristic_optimizer.cc。速度规划这块,可以参考一下EM Planner,保留了EM的思想,DP+QP。1、S-T图离散,动态规划(代价最小的有向图搜索)

2025-04-07 08:48:18 404

原创 日志关键信息提取--正则表达式std::regex

Regex”是“Regular Expression”(正则表达式)的缩写,它是一种强大的文本处理工具,用于匹配、搜索、替换和操作字符串。正则表达式在编程、文本编辑、数据处理等领域广泛应用。正则表达式的用途文本匹配:检查字符串是否符合特定的模式。例如,验证电子邮件地址、电话号码等。搜索和替换:在文本中查找符合模式的内容,并进行替换。字符串分割:根据特定规则将字符串分割成多个子字符串。数据提取:从复杂文本中提取特定格式的数据。正则表达式的语法。

2025-04-07 08:47:29 288

原创 参数自适应的相关方法

相反,对于出现频率较高的参数采用较小的学习率。这里的改动就在于分号下面的根号,根号中有两个符号,第二个符号比较好理解,它就是为了避免除0而人为引入的一个很小的常数,例如可以设为:0.001。对比原始的算法过程可以看出,改进算法最大的区别是:在寻找目标值时会在最终结果上下跳动,但是越往后跳动的幅度越小,这也就是动量所产生的效果。对比梯度下降的泛化公式,这个算法的主要区别就是引入了vt,并且,每个时刻的vt受前一个时刻vt−1的影响。事实上,学习率的取值未必一定要是一个常数,关于这个值的设定有很多的研究。

2025-04-07 08:46:57 1166

原创 第一章:【可视化工具项目实战】ROS jsk_rviz_plugins可视化插件介绍

是一个为 RViz 提供额外插件的 ROS(机器人操作系统)包。功能概述提供了一系列原始的 RViz 插件、面板和工具,用户可以通过启动 RViz 来直接使用这些功能。具体插件:用于显示分割数组。和:用于显示边界框及其数组。CameraInfo:显示相机信息。Footstep:显示脚印。:显示人体骨骼数组。:显示线性仪表。Normal:显示法线。:在 RViz 界面上叠加文本。:显示人员位置测量数组。Pictogram:显示图形符号。PieChart:显示饼图。Plotter2D。

2025-04-07 08:46:33 279

原创 【项目实战】自动驾驶决策模块设计思路及代码解析

首先根据当前位置获取当前车道的左右宽度,然后根据左右借道获取相邻车道的宽度(当然,fallback设定不借道),最后综合各因素,更新PathBound。依据原先设计好的规则,对各种path进行assess,排序得到最优的路径,并在规划路径上的采样点添加标签作为路径筛选的依据,并为速度规划提供限制。和上述的Process方法相对应。当参考线起点与终点距离小于某个阈值,说明没有办法规划出一条较长的路径,所以我们需要对终点添加stop fence ,这时候需要退出动态重规划的过程,而是在一段距离后停车。

2025-04-07 08:45:58 665

原创 轨迹非线性优化

Voronoi图是在收到栅格地图的回调函数处理生成的,Voronoi图就是根据栅格地图障碍物代价生成的一系列原理障碍物的蓝色点路径,蓝色点路径和之前路径探索得到的路径是不完全吻合和,【防盗标记–盒子君hzj】使用蓝色点路径优化原有路径可以实现车辆也能很好地通过狭窄路段,使路径远离障碍物。voronoi 场表明到最近的 voronoi 边缘和最近的障碍物的距离。在stage 1的子节点扩张的过程中,路径会有一些额外的不必要控制动作(即steering),所以算法的第二个部分就是对生成点曲线进行平滑处理。

2025-04-07 08:45:05 504

原创 【全局路径规划模块图搜索算法】greedy best frist search贪心算法

这个代码实现了一个基本的贪婪最佳优先搜索算法,用于在一个给定的网格中找到从起点到终点的路径。注意,这个实现仅适用于整数网格,并且假设网格中的数字表示高度。总的来说,贪婪最佳优先搜索通过优先考虑那些最有可能导向目标的节点,从而高效地找到最短路径。然而,这种方法并不保证总是找到绝对的最短路径,特别是在存在障碍物或其他复杂情况的地图中。这个函数通常基于一些已知的信息,比如实际距离、地形难度等,来估计到达目标的代价。(1)启发式的搜索会指导一个靠近目标点的正确方向【防盗标记–盒子君hzj】

2025-04-07 08:44:28 265

原创 【全局路径规划模块图搜索算法】Dijkstra算法

在开集中,若是当前节点的邻节点将会被更新代价,若不是当前节点的邻节点其代价为无穷大。第二步:2.收录节点后遍历该节点的邻接节点,【防盗标记–盒子君hzj】更新计算n节点的所有临近节点m的代价值g(m)【防盗标记–盒子君hzj】第一步:从未访问的节点选择距离(代价)最小的节点收录,【防盗标记–盒子君hzj】g(n)表示从起点开始到当前节点的代价累加值(基于贪心思想)1、定义一个节点类,包含当前节点的位置、父节点、g值(从起点到当前节点的实际距离)和h值(从当前节点到目标节点的估计距离)。

2025-04-07 08:43:58 265

原创 【全局路径规划模块图搜索算法】A*算法

(1)地图:在代价地图上进行路径探索(规划用到的地图格式和ros的格式不一样,是mat类型的(可以理解为一个二维数组,输入xy,判断对应的节点是以下那个状态nodetype【openlist、closelist、free、obstacle】))(2)节点信息储存的列表:openlist、closelist(3)节点信息:node【point、f_cost、g_cost、h_cost、parent_node】astar算法的理解。

2025-04-07 08:43:30 265

原创 【全局路径规划模块智能体算法】蚁群算法

感性分析蚂蚁走多了就有经验了!不断参考前车之鉴的思想进行迭代–是多只的蚂蚁去走【第一个循环】,走很多次【第二个循环】!蚁群算法常被用在全局路径探索,一方面是因为探索出来的路径比较粗糙,在复杂提点的场景一般不能直接用于执行。另一方面是只有在大地图(全局地图)中,蚁群算法的优势才能被显现出来。

2025-04-07 08:43:02 265

原创 【行为决策模块项目实战】第八章:Behavior Tree的Control Nodes功能及源码解析

BehaviorTree.CPP中内建的控制节点如下,都继承自 BehaviorTree.CPP\include\behaviortree_cpp_v3\control_node.h 中的ControlNode类。很明显,该类有多个子节点,其执行顺序就是控制节点的核心内容。默认子节点是从左到右执行。除了这些ControlNodes之外,其他开源库实现的个性化nodes,用起来也很方便,开发者可以自行导入。FallbackNode也被成为Selector,适用于“如果子节点返回FAILURE该怎么办?”的场

2025-04-06 07:46:33 290

原创 决策的相关方法

1、简单的导航Dome只追求做处效果,没有产品化的要处理的复杂的细节,因此dome大都不会太注重决策模块的设计,只有业务发展到一定程度、要处理的场景十分复杂、算法功能是西安与调度相互冗余与冲突的时候,架构化的决策模块才体现出价值来。特点:树型决策结构更清晰(因为有明确的起始节点和目标阶段,不会有环形的多次循环),设计的代码量比FSM多,复杂的决策做好用库支持,简单的决策可通过移植库中的部分代码实现。本质:决策信息与规则都在行为树中,决策效率很取决于行为树的树型结构的设计(并行、串行、串并行结构)

2025-04-06 07:46:11 290

原创 【无人机实战】第二章:Ego Planner程序框架及代码解析

上面生成的轨迹并不是B样条轨迹,接下来需要将其变成B样条轨迹(通过求解最小二乘问题获得B样条的控制带你来进行转换),该部分内容是通过调用parameterizeToBspline函数完成的,该函数的具体程序位于uniform_bspline.cpp文件中,该函数的输入参数中point_set是轨迹上的点,start_end_derivatives是起点和终点的高阶约束。在BsplineOptimizeTrajRefine函数中,调用了refine_optimize函数来执行具体的优化过程。

2025-04-06 07:45:43 434

原创 【行为决策模块项目实战】第十章:Behavior Tree的Decorator Nodes功能及源码解析

但tick()函数中并没有使用__shared_blackboard port,而是在 BehaviorTree.CPP\src\xml_parsing.cpp中使用的,这点要注意,SubtreePlusNode的__autoremap port也是如此。如果子节点执行后返回RUNNING或SUCCESS,下次tick()继续执行子节点,直到子节点返回FAILURE。延时delay_msec毫秒后,执行子节点,并返回子节点的执行结果。如果子节点执行后返回SUCCESS,该节点返回SUCCESS,不再执行;

2025-04-06 07:45:07 289

原创 【行为决策模块项目实战】第七章:BehaviorTree类的基本类型

可见registration_ID_和node的class name相同(非强制,下篇讲解),而name可以随意指定,如nodes[4],当不设置时默认是registration_ID_,如其中的nodes[2]和nodes[5]。以BehaviorTree.CPP/examples/t03_generic_ports.cpp为例,在构造BehaviorTreeFactory实例后立即打印这3个容器的元素的名称,可以发现输出结果仅顺序不同,说明Factory构造后默认包含了内建的29个nodes。

2025-04-06 07:44:46 284

原创 【行为决策模块项目实战】第九章: Behavior Tree的ActionNode同步与异步

行为树(BT,Behavior Tree)是一种 tree-structured control architecture,常用来做任务或状态管理。最先也最多应用于游戏领域,后来引入到机器人、自动驾驶等需要规划决策的领域。

2025-04-06 07:43:51 289

原创 【行为决策模块项目实战】第六章:BehaviorTree的数据交互

MainTree中包含1个MoveRobot subtree,所以有2个blackboard,blackboard[0]是MainTree的(一定是最外层树的),具有move_result和move_goal 2个entry,而MoveRobot具有output和target 2个entry。我们把blackboard的数量和包含的entry的名称打印出来,size=1因为没有子树,且只有1个名为"the_answer"的entry。当然,从外部设置entry的值并不受其是empty/full的影响。

2025-04-06 07:43:17 280

原创 【行为决策模块项目实战】第五章:Behavior Tree的基本概念

*一个称为“ tick ”的信号,由开发者发送到树的根部并在树的节点中传播,直到它到达树的底部——叶节点。**接收到tick信号的节点会执行它的回调,即被设定的该节点的任务,然后向上返回执行的结果。,没有子节点,需要由开发者实现,不可以返回RUNNING,必须atomic and synchronous,负责任务执行的判断条件,不应该改变系统的状态。,没有子节点,需要由开发者实现,负责执行具体任务。,有且仅有1个子节点,负责重复执行子节点,或更改子节点的返回结果。,有至少1个子节点,负责控制执行流程;

2025-04-06 07:42:18 28

原创 【行为决策模块项目实战】第四章:Behavior Tree的相关调试工具

在Groot中可以图形化的方式创建节点(node),为节点添加输入输出端口(port),可以像Visio一样拖动、连接节点,从而构造行为树,而无需在意节点代码是否完成。该函数定义在BehaviorTree.CPP/include/behaviortree_cpp_v3/behavior_tree.h中,声明和运行效果如下。Groot会自动获得树的结构,无需用户手动加载,但是它会自动展开1棵树中的所有子树,使得界面内容非常密集,因此复杂的树并不方便观察。作用:在终端打印行为树中的节点执行状态变化。

2025-04-06 07:41:46 29

原创 【行为决策】有限状态机实现简单的车辆变道

在此例子下,做变道安全检查时一般都是用比较简单的规则。如下图所示,一般会检查自车跟前车的距离,或跟目标车道前车和后车的距离与相对速度是否满足安全的变道条件,以此也可以看出,整个状态机比较简单,为考虑过于复杂的交互场景,因此不太适合复杂的城市道路场景,更适用于结构化高速公路场景。因此在main函数中,我们定义了一些基础变量:起始点,轨迹长度和分辨率等。在tests/decision/fsm_test.py 中,首先我们定义了FSM的核心概念:状态,事件,动作(在变道功能中没有动作,因此不定义)和状态转移。

2025-04-06 07:40:57 28

原创 【优化理论】第五章:最优化理论在自动驾驶、机器人等领域的应用

也非常多,对于工业机器人或者移动机器人的轨迹规划,往往需要先生成一个轨迹族,然后制定评价函数,再通过一些约束,如环境约束,或者本身的动力学约束等,最后通过最优化算法得到的最优解就是最优轨迹。最优化在机器学习与深度学习的应用比较热门,因为无论是机器学习还是深度学习,很多时候最核心的还是构造一个非常复杂的函数,然后求其最优解,而所。建立模型迭代求最小值或者极小值,通道求解结果套入模型得到控制输出,前者是优化理论(数值优化等),后者是控制理论(控制输出,反馈输入)通过栅格地图转换成ESDF地图实现。

2025-04-06 07:40:26 31

原创 【优化理论】第四章:最优算法优化处理技巧

最优化问题通常需要对实际需求进行定性和定量分析,建立恰当的数学模型来描述该问题,设计合适的计算方法来寻找问题的最优解,探索研究模型和算法的理论性质,考察算法的计算性能等多方面。

2025-04-06 07:40:02 39

原创 【优化理论】第三章之七:目标函数的求解之Ipopt非线性求解器求解带约束的非线性最优化问题

最优化问题的求解是一个迭代的过程, 从初始点(初始解)x0开始, 通过迭代方法(梯度下降法, 牛顿法等)逐步更新xi, 直至逼近最优解x∗上图形象的展示了这个迭代的过程, 从初始解start点开始, 逐步迭代至最优解. 在这个1维问题上, 迭代方向只有左和右(-, +), 我们如何确定迭代的方向和步长呢? 或者更高维度的问题里, 如何确定每个维度的方向和步长呢?详细介绍如何使用Ipopt非线性求解器求解带约束的最优化问题,结合给出的带约束的最优化问题示例,给出相应的完整的C++程序,并给出详细的解释和注

2025-04-06 07:39:39 36

原创 【优化理论】第三章之六:目标函数的求解之信赖阈算法

最优化问题的求解是一个迭代的过程, 从初始点(初始解)x0开始, 通过迭代方法(梯度下降法, 牛顿法等)逐步更新xi, 直至逼近最优解x∗上图形象的展示了这个迭代的过程, 从初始解start点开始, 逐步迭代至最优解. 在这个1维问题上, 迭代方向只有左和右(-, +), 我们如何确定迭代的方向和步长呢? 或者更高维度的问题里, 如何确定每个维度的方向和步长呢?信赖域方法(Trust Region Methods)是一种用于非线性优化的数值优化方法,旨在寻找目标函数的最小值。信赖域算法是一种迭代算法。核

2025-04-06 07:39:11 29

原创 【优化理论】第三章之五:目标函数的求解之QP优化【适用于目标函数为二次型构型的函数】

二次规划(Quadratic Programming)优化,是指优化问题的目标函数为二次函数, 且约束条件为线性的问题。

2025-04-06 07:38:49 27

原创 【优化理论】第三章之四:目标函数的求解之0.618比例进退法

该方法的基本思想是:先选定初始点α 0> 0 和一个初始步长 γ 0> 0,从α 0起,以 γ 0为步长向前搜索一步,得 α 0 +γ 0 .若这一点的目标函数值较α 0 处的目标函数值减小了(说明极值点在选取的初始点右侧,继续向右搜索),则加大γ 0 ,继续向前搜索,直至新一点的目标函数值较前一点的目标函数值增大了,搜索结束。上图形象的展示了这个迭代的过程, 从初始解start点开始, 逐步迭代至最优解. 在这个1维问题上, 迭代方向只有左和右(-, +), 我们如何确定迭代的方向和步长呢?

2025-04-05 11:25:31 53

原创 【优化理论】第三章之三:目标函数的求解之牛顿法\拟牛顿法优化(二阶导数)【适用于固定步长】

上图形象的展示了这个迭代的过程, 从初始解start点开始, 逐步迭代至最优解. 在这个1维问题上, 迭代方向只有左和右(-, +), 我们如何确定迭代的方向和步长呢?最优化问题的求解是一个迭代的过程, 从初始点(初始解)x0开始, 通过迭代方法(梯度下降法, 牛顿法等)逐步更新xi, 直至逼近最优解x∗。3、全局视野:牛顿法在选择下降方向时,不仅考虑当前位置的梯度,还考虑未来位置梯度的变化趋势,因此具有更强的全局视野。下图展示了梯度下降法(绿)和牛顿法(红)的对比, 可以看到牛顿法要高效的多.

2025-04-05 11:25:13 55

原创 【优化理论】第三章之二:目标函数的求解之梯度下降优化(一阶导数)【适用于线搜索】

当初始步长不满足准则是, 我们一般使用一些简单的缩放来寻找满足要求的步长. 上图就是常见的回退法, 当步长α不满足要求时, 给定一个γ∈(0,1), 不停的缩小步长直到其满足准则.因为步长α是从大变小的, 这保证了α尽可能的大.在梯度下降优化的方法中,步长是固定的,收敛速度较慢,我们通过一些不等式, 判断步长是否合适, 通过缩放步长, 来快速找到满足不等式的步长,加快收敛的速度。在line_search_test() 中, 定义了初始点(−5,8), 基于梯度下降法, 使用不同的线搜索方法求最优解.

2025-04-05 11:24:54 47

原创 【优化理论】第三章之一:目标函数的求解之目标函数求导取极值【针对线性优化问题求解】

最优化问题的求解是一个迭代的过程, 从初始点(初始解)x0开始, 通过迭代方法(梯度下降法, 牛顿法等)逐步更新xi, 直至逼近最优解x∗上图形象的展示了这个迭代的过程, 从初始解start点开始, 逐步迭代至最优解. 在这个1维问题上, 迭代方向只有左和右(-, +), 我们如何确定迭代的方向和步长呢?或者更高维度的问题里, 如何确定每个维度的方向和步长呢?

2025-04-05 11:24:37 50

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除