无人驾驶(移动机器人)路径规划之RRT与RRTStar算法及其matlab实现

       在自动驾驶与移动机器人路径规划时,必定会用到经典的算法RRT与RRT Star。下面是RRT与RRTStar的matlab实现效果。可以发现RRTStar效果明显改善。

目录

一、效果比较

1.1 RRT算法效果(黑色为障碍物,红色线为最终路径,蓝色三角形为开始点,粉色三角形为目标点)

1.2 RRTStar算法效果(黑色为障碍物,红色线为最终路径,蓝色三角形为开始点,粉色三角形为目标点)

二、RRT与RRTStar算法

2.1 RRT算法

2.2 RRTStar算法

三、核心代码(完整代码见上述链接)

3.1 地图创建

 3.2 RRT主代码

3.3 RRTStar主代码

3.4 rewire代码。


一、效果比较

1.1 RRT算法效果(黑色为障碍物,红色线为最终路径,蓝色三角形为开始点,粉色三角形为目标点)

代码链接:

移动机器人自主路径规划之RRT算法MATLAB实现代码资源-CSDN文库

(1)原始地图信息。

(2)规划路径信息。

1.2 RRTStar算法效果(黑色为障碍物,红色线为最终路径,蓝色三角形为开始点,粉色三角形为目标点)

代码链接:

移动机器人自主路径规划之RRTStar算法MATLAB实现代码资源-CSDN文库

(1)原始地图信息。

(2)规划路径信息。

 

二、RRT与RRTStar算法

2.1 RRT算法

       RRT算法,全称为Rapidly-Exploring Random Tree(快速探索随机树),是一种在路径规划和运动规划领域广泛应用的算法,特别是在自动驾驶、机器人导航等场景下。该算法由Steven M. LaValle于1998年提出,其核心在于利用随机采样技术构建一个能够快速覆盖配置空间(Configuration Space)的随机树结构,从而找到从初始状态到目标状态的可行路径。

  1. 初始化:算法开始时,从起始点创建一个单一的节点作为随机树的根节点。

  2. 随机采样:算法在每一步中都会随机选取一个状态空间中的点,这个点通常是在整个可行区域或者配置空间中随机产生的。

  3. 接近性判断与树扩展:计算新采样点与树中最近节点的距离,并检查从最近节点沿直线向采样点方向延伸是否遇到障碍物。如果没有障碍阻挡,就在该方向上添加一个新节点至采样点的位置,这个新节点成为树的一部分。

  4. 目标检测与终止条件:如果新添加的节点或采样点落在目标区域,或者与目标点足够接近(依据预设的阈值),则认为找到了一条可行路径,并停止扩展。此时可以通过回溯随机树从起始节点到目标节点来获取路径。

  5. 重复采样与扩展:如果上述步骤未达到终止条件,则重复步骤2至4,直至找到路径或满足其他停止条件(如达到最大迭代次数、计算资源限制等)。

       RRT算法具有概率完备性,即只要存在可行路径,随着迭代次数的增加,算法总能以概率1找到这条路径。然而,RRT算法生成的路径通常不是最优的,且可能包含很多不必要的转折。因此,RRT经常与其他算法(如优化算法)结合使用,以改进路径的质量。

       RRT算法在许多领域都有广泛的应用,包括机器人导航、无人机飞行路径规划、自动驾驶等。它特别适用于那些难以用传统方法(如网格法)处理的复杂环境,能够高效地处理障碍物多且分布不规则的情况。

2.2 RRTStar算法

         RRTStar(Rapidly-exploring Random Tree Star)算法是RRT(Rapidly-exploring Random Tree)算法的一个改进版本,旨在提高路径规划的质量和效率。RRTStar算法继承了RRT算法的基本框架,即通过在空间中随机采样和构建树来探索可行路径。然而,与RRT相比,RRTStar引入了一些关键的改进,使得它在路径优化和避免局部最优解方面更具优势。

以下是RRTStar算法的主要特点和改进之处:

  1. 路径优化:RRTStar算法在构建树的过程中,不仅关注如何快速找到一条从起点到终点的路径,还致力于优化这条路径。它采用了重连策略,即在添加新节点后,会检查是否存在更优的连接方式,如果有,则重新连接树中的节点,以形成更平滑、更短的路径。这种优化过程随着采样点的增加而持续进行,使得最终得到的路径质量更高。

  2. 避免局部最优解:RRT算法有时可能陷入局部最优解,即找到一条看似不错的路径但实际上并不是全局最优的。RRTStar通过引入启发式函数和重新布线策略来避免这个问题。启发式函数用于估计当前节点与目标点之间的距离,引导树的扩展方向,使其更有可能找到全局最优解。重新布线策略则通过调整树的结构,使得路径更加平滑,并减少不必要的转折。

  3. 适应性和鲁棒性:RRTStar算法对不同类型的环境和问题具有较好的适应性和鲁棒性。无论是障碍物分布密集还是稀疏的环境,无论是二维还是三维空间,RRTStar都能有效地进行路径规划。此外,由于它是基于随机采样的方法,因此不依赖于特定的地图表示或环境模型,使得它在实际应用中更加灵活和方便。

       需要注意的是,虽然RRTStar算法在路径优化和避免局部最优解方面表现出色,但它仍然存在一定的局限性。例如,在复杂环境中,RRTStar可能需要较长的计算时间来找到一条满意的路径。此外,由于算法基于随机采样,因此生成的路径可能不是严格的最优解,而是在可接受范围内的次优解。在实际应用中,需要根据具体需求和环境特点来选择合适的算法参数和策略。

      RRT*的实现通常涉及复杂的启发式搜索策略、成本函数的设计以及高效的邻近节点查询机制,比如使用KD树或平衡二叉树来加速最近节点的查找过程,确保算法的高效执行。此外,算法还可能包括对采样策略的优化,以更好地探索环境并避免陷入局部最优。

三、核心代码(完整代码见上述链接)

3.1 地图创建

RRT与RRTStar所用到的地图是相同的。

function [start,target,max_x,max_y,wall,resolution]=creat_map_ob()%创建障碍物地图
%创建地图
clear all;
resolution = 1;%每个格子的长度%map的边界
max_x = 50;
max_y = 50;%obstacle
obstacle(1,:) = [25,5,10,5];
obstacle(2,:) = [15,25,5,25];
obstacle(3,:) = [40,20,5,10];
obstacle(4,:) = [30,25,5,10];
obstacle(5,:) = [5,0,5,20];
figure;%创建新窗口
axis([0 max_x 0 max_y]);
set(gca,'XTick',0:resolution:max_x);%x轴的间隔为1
set(gca,'YTick',0:resolution:max_y);%y轴的间隔为1
grid on;
title('RRT');
xlabel('x');
ylabel('y');
hold on;wall = [obstacle];
for i = 1:1:size(wall,1)fill([wall(i,1),wall(i,1) + wall(i,3),wall(i,1) + wall(i,3),wall(i,1)],...[wall(i,2),wall(i,2),wall(i,2) + wall(i,4),wall(i,2) + wall(i,4)],'k');
end
pause(1);%延时一秒
%初始点
h=msgbox('初始位置标记!');%弹出初始框提示标记初始位置
uiwait(h,3);%3s后关闭对话框
if ishandle(h) == 1%删除对话框delete(h);
end
xlabel('请设置初始点X轴! ','Color','black');%设置x轴
but = 0;
while(but ~= 1)%收到左键点击[xval,yval,but] = ginput(1);xval=floor(xval);yval=floor(yval);
end
start.x = xval;%初始位置
start.y = yval;
plot(xval,yval,'b^','MarkerFaceColor','b','MarkerSize',10*resolution);%绘制初始点
text(xval + 1,yval + 0.5,'Start');
pause(1);%延时一秒
%目标点
h=msgbox('目标位置标记!');%弹出目标提示标记目标位置
uiwait(h,3);%3s后关闭对话框
if ishandle(h) == 1%删除对话框delete(h);
end
xlabel('请设置目标点X轴! ','Color','black');%设置x轴
but1 = 0;
while(but1 ~= 1)%收到左键点击[xval,yval,but1] = ginput(1);xval=floor(xval);yval=floor(yval);
end
target.x = xval;%目标位置
target.y = yval;
plot(xval,yval,'m^','MarkerFaceColor','m','MarkerSize',10*resolution);%绘制目标点
text(xval + 1,yval + 0.5,'Target');
hold on;

 3.2 RRT主代码

function RRT()
clc
clear all
close all;
[start,target,max_x,max_y,wall,resolution] = creat_map_ob();
figure;%创建新窗口
axis([0 max_x 0 max_y]);
set(gca,'XTick',0:resolution:max_x);%x轴的间隔为1
set(gca,'YTick',0:resolution:max_y);%y轴的间隔为1
grid on;
title('RRT');
xlabel('x');
ylabel('y');
hold on;
for i = 1:1:size(wall,1)fill([wall(i,1),wall(i,1) + wall(i,3),wall(i,1) + wall(i,3),wall(i,1)],...[wall(i,2),wall(i,2),wall(i,2) + wall(i,4),wall(i,2) + wall(i,4)],'k');
end
plot(start.x,start.y,'b^','MarkerFaceColor','b','MarkerSize',20*resolution);%绘制初始点
text(start.x + 1,start.y + 0.5,'Start');
plot(target.x,target.y,'m^','MarkerFaceColor','m','MarkerSize',20*resolution);%绘制目标点
text(target.x + 1,target.y + 0.5,'Target');
%初始化随机树
tree.child = [];%存储所有节点
tree.parent = [];%存储节点的父节点
tree.distance = [];%存储child到起点的距离tree.child = start;
tree.parent = start;
tree.distance = 0;%存储新衍生的节点,起点初始化
%target_distance用于存储new_node到终点的距离
new_node.x = start.x;
new_node.y = start.y;target_distance = sqrt((target.x-new_node.x)^2+(target.y-new_node.y)^2);
grow_distance = 1;
target_radius = 1.5;
while target_distance > target_radiusrandom_point.x = max_x*rand();random_point.y = max_y*rand();handle1 = plot(random_point.x,random_point.y,'p','MarkerEdgeColor',[0.9290 0.6940 0.1250],'MarkerFaceColor',[0.9290 0.6940 0.1250],'MarkerSize',10*resolution);[angle,min_idx] = find_closet_node(random_point.x,random_point.y,tree);pause(0.001);handle2 = plot([tree.child(min_idx).x,random_point.x],[tree.child(min_idx).y,random_point.y],'-','Color',[0.7 0.7 0.7],'LineWidth',0.8*resolution); %根据步长选择新节点pause(0.001);new_node.x = tree.child(min_idx).x + grow_distance*cos(angle);new_node.y = tree.child(min_idx).y + grow_distance*sin(angle);handle3 = plot(new_node.x,new_node.y,'.r','MarkerFaceColor','r','MarkerSize',10*resolution);obflag = 1;step = 0.01;%判断路径是否位于障碍物之中if new_node.x < tree.child(min_idx).xstep = -step;endfor k = 1:1:size(wall,1)for i = tree.child(min_idx).x:step:new_node.xif angle>pi/2-5e-03 && angle<pi/2+5e-03j = tree.child(min_idx).y+i-tree.child(min_idx).x;elseif angle>-pi/2-5e-03 && angle<-pi/2+5e-03j = tree.child(min_idx).y-i+tree.child(min_idx).x;elsej = tree.child(min_idx).y+(i-tree.child(min_idx).x)*tan(angle);endif i >= wall(k,1) - 0.005 && i <= (wall(k,1)+wall(k,3)) + 0.005if j >= wall(k,2) - 0.005 && j <= (wall(k,2) + wall(k,4)) + 0.005obflag = 0;breakendendendif obflag == 0breakendend%更新pause(0.001);if obflag == 1tree.child(end + 1) = new_node;tree.parent(end + 1) = tree.child(min_idx);tree.distance(end + 1) = 1 + tree.distance(min_idx);target_distance = sqrt((target.x-new_node.x)^2 + (target.y-new_node.y)^2);%删除红色点delete(handle3);plot(new_node.x,new_node.y,'.g','MarkerFaceColor','g','MarkerSize',10*resolution); % draw the new node%画新连接线plot([tree.child(min_idx).x,new_node.x],[tree.child(min_idx).y,new_node.y],'-k','LineWidth',0.8*resolution);endpause(0.001);%删除随机点delete(handle1);%删除最近点与随机点连线。delete(handle2);pause(0.001);
end
tree.child(end + 1) = target;
tree.parent(end + 1) = new_node;
tree.distance(end + 1) = 2 + tree.distance(min_idx);
final_distance = tree.distance(end);
title('RRT, distance:',num2str(final_distance));
current_index = length(tree.child);
while current_index ~= 1plot([tree.child(current_index).x,tree.parent(current_index).x],[tree.child(current_index).y,tree.parent(current_index).y],'-','LineWidth',3*resolution,'Color',[0.8500 0.3250 0.0980]);for i = 1:length(tree.child)if tree.child(i).x == tree.parent(current_index).xif tree.child(i).y == tree.parent(current_index).ycurrent_index = i;breakendendend
end

3.3 RRTStar主代码

function RRT()
clc
clear all
close all;
[start,target,max_x,max_y,wall,resolution] = creat_map_ob();
figure;%创建新窗口
axis([0 max_x 0 max_y]);
set(gca,'XTick',0:resolution:max_x);%x轴的间隔为1
set(gca,'YTick',0:resolution:max_y);%y轴的间隔为1
grid on;
title('RRT');
xlabel('x');
ylabel('y');
hold on;
for i = 1:1:size(wall,1)fill([wall(i,1),wall(i,1) + wall(i,3),wall(i,1) + wall(i,3),wall(i,1)],...[wall(i,2),wall(i,2),wall(i,2) + wall(i,4),wall(i,2) + wall(i,4)],'k');
end
plot(start.x,start.y,'b^','MarkerFaceColor','b','MarkerSize',20*resolution);%绘制初始点
text(start.x + 1,start.y + 0.5,'Start');
plot(target.x,target.y,'m^','MarkerFaceColor','m','MarkerSize',20*resolution);%绘制目标点
text(target.x + 1,target.y + 0.5,'Target');
%初始化随机树
tree.child = [];%存储所有节点
tree.parent = [];%存储节点的父节点
tree.distance = [];%存储child到起点的距离tree.child = start;
tree.parent = start;
tree.distance = 0;
radius = 5;
%存储新衍生的节点,起点初始化
%target_distance用于存储new_node到终点的距离
new_node.x = start.x;
new_node.y = start.y;target_distance = sqrt((target.x-new_node.x)^2+(target.y-new_node.y)^2);
grow_distance = 1;
target_radius = 1.5;line1.l = [];
line1.id = [];
while target_distance > target_radiusrandom_point.x = max_x*rand();random_point.y = max_y*rand();handle1 = plot(random_point.x,random_point.y,'p','MarkerEdgeColor',[0.9290 0.6940 0.1250],'MarkerFaceColor',[0.9290 0.6940 0.1250],'MarkerSize',10*resolution);[angle,min_idx] = find_closet_node(random_point.x,random_point.y,tree);%pause(0.01);handle2 = plot([tree.child(min_idx).x,random_point.x],[tree.child(min_idx).y,random_point.y],'-','Color',[0.7 0.7 0.7],'LineWidth',0.8*resolution); %根据步长选择新节点%pause(0.01);new_node.x = tree.child(min_idx).x + grow_distance*cos(angle);new_node.y = tree.child(min_idx).y + grow_distance*sin(angle);handle3 = plot(new_node.x,new_node.y,'.r','MarkerFaceColor','r','MarkerSize',10*resolution);step = 0.005;%判断路径是否位于障碍物之中%更新pause(0.001);if isobstacle(wall,step,tree,new_node,min_idx,angle) == 1target_distance = sqrt((target.x-new_node.x)^2 + (target.y-new_node.y)^2);%删除红色点delete(handle3);plot(new_node.x,new_node.y,'.g','MarkerFaceColor','g','MarkerSize',10*resolution); % draw the new node%画新连接线handle4 = plot([tree.child(min_idx).x,new_node.x],[tree.child(min_idx).y,new_node.y],'-k','LineWidth',0.8*resolution);% pause(0.001);%删除随机点delete(handle1);%删除最近点与随机点连线。delete(handle2);%pause(0.001);theta = linspace(0, 2*pi, 100);handle6 = plot(new_node.x+radius*cos(theta),new_node.y+radius*sin(theta),'b--');[minid,min_dis_fs,newid] = chooseparent(wall,tree,radius,min_idx,new_node,step,resolution);tree.child(end + 1) = new_node;tree.parent(end + 1) = tree.child(minid);tree.distance(end + 1) = min_dis_fs;delete(handle4);line1.l(end+1) = plot([tree.child(minid).x,new_node.x],[tree.child(minid).y,new_node.y],'-k','LineWidth',0.8*resolution);line1.id(end+1) = length(tree.child);[deid] = rewire(wall,tree,minid,new_node,step,newid,min_dis_fs);if(deid ~= 0)for j = 1:1:length(line1.id)if(line1.id(j) == deid)%pause(2);delete (line1.l(j));breakendend% pause(2);line1.l(j) = plot([tree.child(deid).x,new_node.x],[tree.child(deid).y,new_node.y],'-k','LineWidth',0.8*resolution);%pause(2);enddelete(handle6);else%删除随机点%pause(0.001);delete(handle3);delete(handle1);%删除最近点与随机点连线。delete(handle2);%pause(0.001);endend
tree.child(end + 1) = target;
tree.parent(end + 1) = new_node;
tree.distance(end + 1) = 2 + tree.distance(min_idx);
final_distance = tree.distance(end);
title('RRT, distance:',num2str(final_distance));
current_index = length(tree.child);
while current_index ~= 1plot([tree.child(current_index).x,tree.parent(current_index).x],[tree.child(current_index).y,tree.parent(current_index).y],'-','LineWidth',3*resolution,'Color',[0.8500 0.3250 0.0980]);for i = 1:length(tree.child)if tree.child(i).x == tree.parent(current_index).xif tree.child(i).y == tree.parent(current_index).ycurrent_index = i;breakendendend
end

3.4 rewire代码。

function [deid] = rewire(wall,tree,minid,new_node,step,newid,min_dis_fs)
deid = 0;
for i = 1:1:length(newid)if(newid(i) ~= minid)newcost = min_dis_fs + sqrt((tree.child(newid(i)).x-new_node.x)^2+(tree.child(newid(i)).y-new_node.y)^2);if(newcost < tree.distance(newid(i)))angle = atan2(new_node.y-tree.child(newid(i)).y,new_node.x-tree.child(newid(i)).x);if isobstacle(wall,step,tree,new_node,newid(i),angle) == 1tree.parent(newid(i)) = new_node;tree.distance(newid(i)) = newcost;deid = newid(i);endendend
end

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

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

相关文章

C++之STL-vector+模拟实现

目录 一、vector的介绍和基本使用的方法 1.1 介绍 1.2 迭代器 1.3 vector的一些基本使用 1.3.1 构造函数 1.3.2 迭代器 1.3.3 有关容量的接口 1.3.4 增删查改 二、模拟实现vector 2.1 成员变量 2.2 迭代器的实现 2.3 容量接口的实现 2.3.1 size函数实现 2.3.2 capa…

阿斯达年代记三强争霸新手开荒注意事项 搬砖攻略和注意问题分享

阿斯达年代记三强争霸新手开荒注意事项 搬砖攻略和注意问题分享 阿斯达年代三强争霸这款游戏刚开始公测就获得了玩家们的集体关注&#xff0c;这是一款根据影视剧改编的MMORPG游戏&#xff0c;玩家将置身于名为阿斯大陆的奇幻世界&#xff0c;加入阿斯达、亚高、不法者三大势力…

Prompt之美:如何设计提示词让大模型变“聪明”

目录 一. Prompt关键要素 二. Prompt技巧 三. 实战中的Prompt优化 四. 参考文献 一. Prompt关键要素 Prompt是一个简短的文本输入&#xff0c;用于引导AI模型生成特定的回答或执行特定任务。换句话说&#xff0c;Prompt是你与AI模型沟通的方式。一个好的Prompt可以让AI更准…

从现在开始:让AI写代码,你只负责敲tab键

如果你是一名程序员&#xff0c;你一定有过这样的经历&#xff1a;在编写代码的时候&#xff0c;突然遇到了一个棘手的问题&#xff0c;需要花费大量的时间去查找资料、尝试不同的解决方案&#xff0c;甚至有时候还需要去问同事或者在网上寻求帮助。这样的情况不仅会浪费你的时…

用立方样条联合SHAP分析在危险因素鉴定中的作用

用立方样条联合SHAP分析在危险因素鉴定中的作用 1. SHAP分析告诉我们变量之间的关系 SHAP分析计算的SHAP值代表了某变量对于结局指标的贡献&#xff0c;代表了相关性的趋势&#xff0c;SHAP分析中的散点图是对以上关系的可视化&#xff0c;从中我们可以直观看到随着变量值的变…

百度 | 如何白嫖文心一言4.0,偷偷的用!

文心一言4.0 官方价一个月 59.9&#xff0c;贵不贵&#xff0c;很贵啊 现在有个白嫖文心一言4.0的方法 分享给大家 效果比3.0好用 如何使用 这里用到文心智能体平台&#xff0c;也是百度出的&#xff0c;和字节跳动的coze很像 这里打开文心智能体平台&#xff0c;自行百度…

diskMirror docker 使用容器部署 diskMirror 服务器!!!

Welcome to diskMirror-docker 获取项目 这个项目是 diskMirror-spring-boot 镜像版本的项目&#xff0c;您可以使用下面的命令将此项目编译为一个镜像&#xff01; # 进入到您下载的源码包目录 cd diskMirror-docker# 点击脚本来进行版本的设置以及对应版本的下载 设置 和 编…

JavaEE:File类查询一个文件的路径(举例+源码 )

一、File类概述 Java 中通过 java.io.File 类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。File 类中的方法可以对文件路径以及文件名等信息进行查询&#xff0c;也可以对文件进行各项增删改操作&#xff0c;本文主要介绍 File 类的查询方法。 二、代码示例 …

Python入门第10篇(编码)

目录 一、编码是什么&#xff1f; 二、Python中编码 1.读取文件引发的问题 2.其实是Windows的问题 3.试着改改问题 4.各种骚操作 5.终极解决 6.推荐方案 总结 Python系列文章目录 前言 编码存在于所有文件&#xff0c;比较常见的ASCII、utf8、gbk等。最常用的还是ut…

大模型 AI 框架昇思 MindSpore 2.3.RC1 发布,训练、推理性能大幅提升,JIT 编译强化

经过社区开发者们几个月的开发与贡献&#xff0c;现正式发布昇思 MindSpore2.3.RC1 版本&#xff0c;通过多维混合并行以及确定性 CKPT 来实现超大集群的高性能训练&#xff0c;支持大模型训推一体架构&#xff0c;大模型开发训练推理更简、更稳、更高效&#xff0c;并在训推一…

【产品设计】B端产品权限设计~功能权限设计篇

对于B端设计而言&#xff0c;良好的权限设计架构是支持其复杂业务的基础和关键。 一、什么是权限管理 权限管理&#xff0c;一般指根据系统设置的安全规则或者安全策略&#xff0c;用户可以访问而且只能访问自己被授权的资源。 简而言之&#xff0c;用户登录系统后&#xff0…

使用 Redux 管理全局状态

Redux 是个状态集中管理框架&#xff0c;状态可以跨组件共享&#xff0c;状态更新后&#xff0c;调用监听器。其实状态可以认为就是个全局对象&#xff0c;为什么要做一个框架来管理呢&#xff1f;如果我们自己使用一个全解字典来管理状态是不是也行&#xff1f;如果不做任何控…

想在游泳健身的同时畅听音乐,随时哈氪漫游这款IP68防水的骨传导耳机

平时健身的过程中&#xff0c;音乐是许多健身爱好者的忠实伴侣。无论是在室内的健身房&#xff0c;还是户外的自然风光中&#xff0c;一副优质的耳机可以极大地提升我们的锻炼体验。现在市面上专为运动设计的耳机选择非常多&#xff0c;我喜欢用骨传导耳机&#xff0c;目前在用…

深入理解多线程编程

title: 深入理解多线程编程 date: 2024/4/25 17:32:02 updated: 2024/4/25 17:32:02 categories: 后端开发 tags:线程同步互斥锁死锁避免竞态条件线程池异步编程性能优化 第一章&#xff1a;多线程基础 1.1 线程概念与原理 线程&#xff1a;在操作系统中&#xff0c;一个程序…

ADB常用命令

大家好&#xff0c;今天给大家分享一些ADB的常用命令&#xff0c;我们作为测试了解ADB命令能给我们带来哪些好处呢&#xff1f; 1、ADB 命令可以帮助测试人员与Android设备进行交互&#xff0c;如安装、卸载应用&#xff0c;获取设备信息等&#xff0c;便于更深入地测试设备功能…

世强硬创获昕感科技授权代理,SiC MOSFET实现超低导通电阻

近日&#xff0c;世强先进&#xff08;深圳&#xff09;科技股份有限公司&#xff08;下称“世强先进”&#xff09;获北京昕感科技有限责任公司&#xff08;下称“昕感科技”&#xff0c;英文名&#xff1a;NEXIC&#xff09;授权代理&#xff0c;为光伏、储能、电网、新能源汽…

C# 给图片添加文字水印

目录 应用场景 开发运行环境 方法说明 方法代码 调用示例 小结 应用场景 在某些应用项目&#xff08;如电子档案信息管理&#xff09;中&#xff0c;查看电子图片信息是经常使用到的功能&#xff0c;此时我们就需要给显示在浏览器中的图片添加文字水印版权或提示信息。…

Golang对接Ldap(保姆级教程:概念搭建实战)

Golang对接Ldap&#xff08;保姆级教程&#xff1a;概念&搭建&实战&#xff09; 最近项目需要对接客户的LDAP服务&#xff0c;于是趁机好好了解了一下。LDAP实际是一个协议&#xff0c;对应的实现&#xff0c;大家可以理解为一个轻量级数据库。用户查询。比如&#xff…

力扣HOT100 - 114. 二叉树展开为链表

解题思路&#xff1a; class Solution {List<TreeNode> list new ArrayList<>();public void flatten(TreeNode root) {recur(root);for (int i 1; i < list.size(); i) {TreeNode pre list.get(i - 1);TreeNode cur list.get(i);pre.left null;pre.right…

使用Shell终端访问Linux

一、实验目的 1、熟悉Linux文件系统访问命令&#xff1b; 2、熟悉常用 Linux Shell的命令&#xff1b; 3、熟悉在Linux文件系统中vi编辑器的使用&#xff1b; 4、进一步熟悉虚拟机网络连接模式与参数配置&#xff01; 二、实验内容 1、使用root帐号登陆到Linux的X-windows…