首页/文章/ 详情

如何让小车自己识别车道线自动前行?

1年前浏览878

大家好,我是团长。我又来献丑了。

在前几期的内容中,我们讲解了相机标定、车道线检测、Simulink搭建小车的控制模型、道路模型的搭建、小车模型的创建和仿真,这一次,终于以将以前学的东西串起来,做一个简单的自动驾驶仿真了。

还是要先来讲一下流程。

1、在Simulink中创建一个独轮小车的动力学模型;
2、在Matlab中创建出小车和道路场景;
3、获取小车在道路上的第一视角图片;
4、将第一视角图片进行鸟瞰试图转换;
5、对鸟瞰视图的车道线进行识别及拟合;
6、控制场景中的车辆前行;

1、在Simulink中创建独轮小车模型

本次直接引用我们在上一期文章中创建的独轮小车的动力学模型;

 
   

如何利用Matlab/Simulink进行独轮小车的动力学模型搭建


需要将这个模型进行保存(如:unicycle.slx),我们在后期需要调用其为场景里的小车所用。

2、在Matlab中创建出小车和道路场景


















%%setup driving scenario;s = drivingScenario;R = 50;theta = 0:90;%degreeRoadCenter = [R*sind(theta)',R*cosd(theta)'];RoadWidth = 5;vel = 100 ;road(s,RoadCenter,RoadWidth);plot(s);%figure(1)%%f = figure(1);v = vehicle(s);initPosition = [-3,50,0];sensorLocation = [v.Length - v.FrontOverhang,0];v.Position = initPosition;s.updatePlots();%figure(1)

3、获取小车在道路上的第一视角图片













%%figure(1)ax = gca;height = 2;chasePlot(v,'Centerline','on','Viewlocation',sensorLocation,'ViewHeight',height,'Parent',ax);%figure(2)%drawnow();%refresh the plot.%%c = getframe(gcf);currentImage = c.cdata;%figure();%imshow(currentImage);

4、将第一视角图片进行鸟瞰试图转换

这部分包含相机标定的部分,相机的参数(内参和外参)相当重要,需要根据实际相机的标定来,但我这里只能简单设置下了,后期也容易引起问题。仅供参考。























%% camera calibration;focalLength = [309,344];imageSize = [480,640];principalPoint = fliplr(imageSize)/2;%exchange x and y.f.Position = [1,1,fliplr(imageSize)];pitch = 0; % pitch ange of camera.% to set the intrinsic parameters of a camera.camIntrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);% to create a camera.sensor = monoCamera(camIntrinsics,height,'Pitch',pitch,'sensorLocation',sensorLocation);distAheadOfSensor = 20; SpaceToOneSide = 6;bottomOffset = sensorLocation(1);outView = [bottomOffset, distAheadOfSensor, -SpaceToOneSide,SpaceToOneSide];outImageSize = [500,NaN];% to set the bird eye view to be output.birdsEyeConfigure = birdsEyeView(sensor,outView,outImageSize);%%I = imresize(currentImage,birdsEyeConfigure.Sensor.Intrinsics.ImageSize);birdsEyeImage = transformImage(birdsEyeConfigure,I);%bird's-eye-view image%


5、对鸟瞰视图的车道线进行识别及拟合












%Lane extraction.approxBoundaryWidth = 0.25;% to get segment lane marker features using a ridge filter.birdsEyeBW = segmentLaneMarkerRidge(rgb2gray(birdsEyeImage),birdsEyeConfigure,approxBoundaryWidth);[imageX,imageY] = find(birdsEyeBW);% to convert bird's-eye-view image locations to vehicle coordinates.xyBoundaryPoints = imageToVehicle(birdsEyeConfigure,[imageY,imageX]);% to fit the curve with function: Ax2+Bx+C=0.boundaries = findParabolicLaneBoundaries(xyBoundaryPoints,approxBoundaryWidth,'MaxNumBoundaries',1,'MaxSamplingAttempts',100);%

6、控制场景中的车辆前行;

先要导入小车动力学模型。

这个需要在一个循环中进行。

在单个循环中来讲,车辆的路径控制不再是简单的提前设置一个弯道的中心线给它,让它照着走就是了,而是通过图片识别处的车道线,算出一个计算步中的轨迹偏转角度,再将这个角度赋值给动力学模型作为方向盘转交输入,以此来控制汽车的行走轨迹的。



































%%load_system('unicycle');set_param('unicycle','FastRestart','on');plot(s);while advance(s)    % force update plots    updatePlots(s);%    % set figure location    f = figure(1);    ax = f.CurrentAxes;    ax.Position = [0,0,1,1];    c = getframe(gcf);    % Resize the image to fit sensor configuration;    I = imresize(c.cdata,birdsEyeConfigure.Sensor.Intrinsics.ImageSize);    birdsEyeImage = transformImage(birdsEyeConfigure,I);    %Lane extraction.    approxBoundaryWidth = 0.25;    birdsEyeBW = segmentLaneMarkerRidge(rgb2gray(birdsEyeImage),birdsEyeConfigure,approxBoundaryWidth);    [imageX,imageY] = find(birdsEyeBW);    xyBoundaryPoints = imageToVehicle(birdsEyeConfigure,[imageY,imageX]);    boundaries = findParabolicLaneBoundaries(xyBoundaryPoints,approxBoundaryWidth,'MaxNumBoundaries',1,'MaxSamplingAttempts',100);    currentPosition = v.Position;    forward = 10;    ref_yaw = [0,atan2(boundaries.computeBoundaryModel(forward),forward)];    options = simset('SrcWorkspace','Current');    stoptime = s.SampleTime;    simout = sim('unicycle',[],options);    yaw = simout.yaw;    dx = vel.*cos(yaw(end)).*stoptime;    dy = vel.*sin(yaw(end)).*stoptime;    currentPosition = v.Position;    v.Position = [currentPosition(1)+dx(end),currentPosition(2)+dy(end),0];    v.Yaw = rad2deg(yaw(end));


来简单看下小车的运行效果。这个小车并不能完整的跑完整个弯道,原因有很多,比如相机的参数标定有问题,比如小车PID控制参数有问题等。要解决这些问题,又是另一个深入的课题了。



以下贴上完整的所有代码,供自己回看,供诸君参考。










































































%%setup driving scenario;s = drivingScenario;R = 50;theta = 0:90;%degreeRoadCenter = [R*sind(theta)',R*cosd(theta)'];RoadWidth = 5 ;vel = 200 ;road(s,RoadCenter,RoadWidth);plot(s);%% add a vehicle;v = vehicle(s);initPosition = [-2,50,0];sensorLocation = [v.Length - v.FrontOverhang,0];v.Position = initPosition;s.updatePlots();%% add a plot for debug;f = figure(1);ax = gca;height = 2;chasePlot(v,'Centerline','on','Viewlocation',sensorLocation,'ViewHeight',height,'Parent',ax);drawnow();%% camera calibration;focalLength = [309,344];imageSize =  [640,480];principalPoint = fliplr(imageSize)/2;f.Position = [1,1,fliplr(imageSize)];c = getframe(gcf);pitch = 0;camIntrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);sensor = monoCamera(camIntrinsics,height,'Pitch',pitch,'sensorLocation',sensorLocation);distAheadOfSensor = 20 ; SpaceToOneSide = 6;bottomOffset = sensorLocation(1);outView = [bottomOffset, distAheadOfSensor, -SpaceToOneSide,SpaceToOneSide];outImageSize = [640,NaN];birdsEyeConfigure = birdsEyeView(sensor,outView,outImageSize);%%load_system('unicycle');set_param('unicycle','FastRestart','on');plot(s);while advance(s)    % force update plots    updatePlots(s);%    % set figure location    f = figure(1);    ax = f.CurrentAxes;    ax.Position = [0,0,1,1];    c = getframe(gcf);    % Resize the image to fit sensor configuration;    I = imresize(c.cdata,birdsEyeConfigure.Sensor.Intrinsics.ImageSize);    birdsEyeImage = transformImage(birdsEyeConfigure,I);    %Lane extraction.    approxBoundaryWidth = 0.25;    birdsEyeBW = segmentLaneMarkerRidge(rgb2gray(birdsEyeImage),birdsEyeConfigure,approxBoundaryWidth);    [imageX,imageY] = find(birdsEyeBW);    xyBoundaryPoints = imageToVehicle(birdsEyeConfigure,[imageY,imageX]);    boundaries = findParabolicLaneBoundaries(xyBoundaryPoints,approxBoundaryWidth,'MaxNumBoundaries',1,'MaxSamplingAttempts',100);    currentPosition = v.Position;    forward = 10;    ref_yaw = [0,atan2(boundaries.computeBoundaryModel(forward),forward)];    options = simset('SrcWorkspace','Current');    stoptime = s.SampleTime;    simout = sim('unicycle',[],options);    yaw = simout.yaw;    dx = vel.*cos(yaw(end)).*stoptime;    dy = vel.*sin(yaw(end)).*stoptime;    currentPosition = v.Position;    v.Position = [currentPosition(1)+dx(end),currentPosition(2)+dy(end),0];    v.Yaw = rad2deg(yaw(end));end
set_param('unicycle','FastRestart','off');unicycle([],[],[],'term');

本文完。


来源:车路慢慢
汽车Simulink自动驾驶控制
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2023-06-21
最近编辑:1年前
李慢慢
硕士 自动驾驶仿真工程师一枚
获赞 11粉丝 70文章 122课程 0
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈