From 02845303adc0f15dd44793a64990afa5b3bd153b Mon Sep 17 00:00:00 2001 From: 12345qiupeng Date: Mon, 17 Mar 2025 14:28:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 99-benz-serial.rules | 4 ++-- BenzObstacleDetect/DataType/RectRoi.cs | 16 ++++++++++++++++ BenzObstacleDetect/Detection.cs | 18 ++++++++++-------- BenzObstacleDetect/Program.cs | 6 ++++++ BenzObstacleDetect/Worker.cs | 23 ++++++++++++----------- BenzObstacleDetect/appsettings.json | 18 ++++++++++++++++++ Release/BenzObstacleDetect.exe | Bin 11264 -> 13824 bytes Release/BenzObstacleDetect.pdb | Bin 13492 -> 14112 bytes Release/appsettings.json | 18 ++++++++++++++++++ detection.sh | 2 +- 10 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 BenzObstacleDetect/DataType/RectRoi.cs diff --git a/99-benz-serial.rules b/99-benz-serial.rules index d9c0cda..7b2feb5 100644 --- a/99-benz-serial.rules +++ b/99-benz-serial.rules @@ -1,4 +1,4 @@ # 串口继电器 -KERNEL=="ttyUSB*", SUBSYSTEM=="tty", ENV{ID_PATH}=="platform-xhci-hcd.4.auto-usb-0:1:1.0-port0", SYMLINK+="autolabor_relay", MODE="0777" +KERNEL=="ttyUSB*", SUBSYSTEM=="tty", ENV{ID_PATH}=="platform-xhci-hcd.4.auto-usb-0:1:1.0", SYMLINK+="autolabor_relay", MODE="0777" # 雷达 -KERNEL=="ttyUSB*", SUBSYSTEM=="tty", ENV{ID_PATH}=="platform-fc840000.usb-usb-0:1:1.0-port0", SYMLINK+="autolabor_ld19", MODE="0777" \ No newline at end of file +KERNEL=="ttyUSB*", SUBSYSTEM=="tty", ENV{ID_PATH}=="platform-fc840000.usb-usb-0:1:1.0", SYMLINK+="autolabor_ld19", MODE="0777" \ No newline at end of file diff --git a/BenzObstacleDetect/DataType/RectRoi.cs b/BenzObstacleDetect/DataType/RectRoi.cs new file mode 100644 index 0000000..76bba96 --- /dev/null +++ b/BenzObstacleDetect/DataType/RectRoi.cs @@ -0,0 +1,16 @@ +namespace Autolabor.Benz.ObstacleDetection.DataType +{ + + public class RectRoiSettings + { + public RectRoi[] RectRois { get; set; } + } + + public struct RectRoi + { + public double LeftUpX { get; set; } + public double LeftUpY { get; set; } + public double RightDownX { get; set; } + public double RightDownY { get; set; } + } +} \ No newline at end of file diff --git a/BenzObstacleDetect/Detection.cs b/BenzObstacleDetect/Detection.cs index 0f97de6..f6da589 100644 --- a/BenzObstacleDetect/Detection.cs +++ b/BenzObstacleDetect/Detection.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Net; +using Autolabor.Benz.ObstacleDetection.DataType; using Autolabor.Robobase; using Autolabor.Robobase.Component.Algorithm.LidarDetection; using Autolabor.Robobase.Component.Algorithm.LidarDetection.DataType; @@ -36,8 +39,12 @@ namespace Autolabor.Benz.ObstacleDetection // 配置过滤区域 private LidarRoi[] _lidarRois; - public Detection() + public Detection(RectRoiSettings roiSettings) { + // 1. 获取感兴趣区域 + var rois = roiSettings.RectRois.Select(roi => LidarRoiFactory.Make(roi.LeftUpX, roi.LeftUpY, roi.RightDownX, roi.RightDownY)).ToList(); + _lidarRois = rois.ToArray(); + // 2. 创建各个功能组件 // 驱动组件 _lidarDriver = new Ld19DriverNew(); @@ -79,11 +86,6 @@ namespace Autolabor.Benz.ObstacleDetection // 串口继电器配置 _serialRelay.SetProperty("serial.relay.port", "/dev/autolabor_relay"); - // 创建感兴趣区 - _lidarRois = new[] - { - LidarRoiFactory.Make(0.6, 0.5, 0.1, -0.5), - }; // 配置过滤器 _lidarRoiFilter.SetProperty("roiArray", _lidarRois); // 障碍物检测器配置 @@ -92,8 +94,8 @@ namespace Autolabor.Benz.ObstacleDetection _obstacleDetector.SetProperty("MaxPrjDistance", 0.05); _obstacleDetector.SetProperty("GuessDistance", 1.0); // 配置发现和丢失次数 - _benzObstacleController.SetProperty("FoundObstacleThreshold", 3); - _benzObstacleController.SetProperty("LostObstacleThreshold", 5); + _benzObstacleController.SetProperty("FoundObstacleThreshold", 2); + _benzObstacleController.SetProperty("LostObstacleThreshold", 3); // 5. 连接组件 // 雷达数据流向避障检测 diff --git a/BenzObstacleDetect/Program.cs b/BenzObstacleDetect/Program.cs index 466e3f2..c21e313 100644 --- a/BenzObstacleDetect/Program.cs +++ b/BenzObstacleDetect/Program.cs @@ -1,9 +1,15 @@ using Autolabor.Benz.ObstacleDetection; +using Autolabor.Benz.ObstacleDetection.DataType; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; + var builder = Host.CreateApplicationBuilder(args); builder.Services.AddHostedService(); +// 注册配置绑定到 RectRoiSettings 类 +builder.Services.Configure(builder.Configuration.GetSection("RectRoiSettings")); + + var host = builder.Build(); host.Run(); \ No newline at end of file diff --git a/BenzObstacleDetect/Worker.cs b/BenzObstacleDetect/Worker.cs index d7a7f68..277da2a 100644 --- a/BenzObstacleDetect/Worker.cs +++ b/BenzObstacleDetect/Worker.cs @@ -1,23 +1,32 @@ using System; using System.Threading; using System.Threading.Tasks; +using Autolabor.Benz.ObstacleDetection.DataType; using Autolabor.Robobase; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; namespace Autolabor.Benz.ObstacleDetection { public class Worker : BackgroundService { private readonly ILogger _logger; + private readonly RectRoiSettings _roiSettings; - public Worker(ILogger logger) + public Worker(ILogger logger, IOptions roiSettings) { _logger = logger; + _roiSettings = roiSettings.Value; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + foreach (var roi in _roiSettings.RectRois) + { + _logger.LogInformation("RectRoi: leftUp({0},{1}) - rightDown({2},{3})", + roi.LeftUpX, roi.LeftUpY, roi.RightDownX, roi.RightDownY); + } // 创建用户配置文件 var app = Kits.GetAutolaborDataPath(); @@ -26,18 +35,10 @@ namespace Autolabor.Benz.ObstacleDetection // 输出日志 TestKit.Logger.Trace("BenzObstacleDetection start"); + // 启动顶层组件 - var detection = new Detection(); + var detection = new Detection(_roiSettings); detection.Enable = true; - // while (!stoppingToken.IsCancellationRequested) - // { - // if (_logger.IsEnabled(LogLevel.Information)) - // { - // _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); - // } - // - // await Task.Delay(1000, stoppingToken); - // } } } } \ No newline at end of file diff --git a/BenzObstacleDetect/appsettings.json b/BenzObstacleDetect/appsettings.json index b2dcdb6..8b78f12 100644 --- a/BenzObstacleDetect/appsettings.json +++ b/BenzObstacleDetect/appsettings.json @@ -4,5 +4,23 @@ "Default": "Information", "Microsoft.Hosting.Lifetime": "Information" } + }, + + "RectRoiSettings": { + "RectRois": [ + { + "leftUpX": 1.5, + "leftUpY": 0.3, + "rightDownX": 0.55, + "rightDownY": -0.3 + }, + { + "leftUpX": -0.55, + "leftUpY": 0.3, + "rightDownX": -1.5, + "rightDownY": -0.3 + } + ] } + } diff --git a/Release/BenzObstacleDetect.exe b/Release/BenzObstacleDetect.exe index 65438f4a258a62371b8dcb4aaf357bbbf62bfff0..d7d2da11eb4957a3a6bbb054831a3c7b19410f42 100644 GIT binary patch literal 13824 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 delta 4307 zcmaJ_3vg8B6+ZvJckk}rC7az%vUw6V55kg|5Rw=Y2*IGKAj6Ci86F*r$tGwNSlmDr zmSh+4l}@nLt8GE4gBF>fGui?U(YB(|Y6i!uZ5@~nN(Pt##F0(~8?D&y{JROeFykHb z-E+=&UjOqh#@57^|LQT{2j}*FN{QzJ6_Zm|6O}&kyPeioTZnEqw^lWon?$zpK{1^C z_$xJciV9I?{#DG^KblH(BHwh$xzS7_qx@$wz;Bto{W>Bs)n|FOR}g9CvlDj9)v9Ec zD5F|X5pu)XBLi7TVdx zec1u@UD0d5V$MeW3A=;sGQt%CC5VU2CB|jWHZF6$ahVH_%ba>#=5%pcr3_E!KIQ>J zrJOu&jNSzUip8ISTFhlKegBWLk8;Mrt1=$pkete!ZvU=mY~D2q&t732hrvcu>)FIa zaPAG)1WyI)KZE%hsJp7qB^(zYL-)0D*gflIgqJdTY z0Ts@doY$ZGsJ9sf-WRyj7E6-g#USUN@cZJXnlTiAxym% znWp;W_9Fp^A?z!oEIytH4i|P7k0DZ##HlzOZE&18QpsEupe&m3o^gf5Jz|7rGMVtM zQ5;Wx1pCtnVeu!p>#uP2%*~2(%DF*ts$e5?v*TRSAne$GT4WBBiBYK5n^d5K3tr*) zGMdYTrPl?f9G8eBv`skE9xnx&!S%YqcqywlUA?!&)c`71cu8r28{k$>`G~y-u@;)C#Ew1JctR*`c36`7Ad>lT$9MdQuhe zXn~uV$VfE@7Ql$r5on3XM)h+k7ef|CeLTz(SZEeH%A@Bo0VRDz%TeV5_J7He4dL!} zclB`8f()W(F_x00OXw7CSx!}Q^U{UrkG_U}9Y3+pbjTMt8pExF<~dl(>M_(f(9%{Z909U@L{>vmQMfW z38LdNq#2Yh4?1-E%(Ba>(^`ctg%t{4R``-+w#)jpU8iW9g!pNfn+evF4J*4oQ_O8=M9(qjo zQ4ei*7Sc|~?eKX+nLyJ27hd8zcm`C?I=LjEdf!#-S z#OR7yKM|6%_r4pTj%nP%U0Sg8N zTdqtlx3^AcJ1{)fcz?L*T`XNIWZnhtDAnU)X(J0+N%-BAuD@-)1DXx)Zu%bD!{ox| zu^Ki@spFD93XJIIOl(=pz|Dcbo`!t+R!OIRfRPpR+F3*^Bi+%T2NQSlE0P0`_mRwx3Aqq6{~ zNzf%6T|upwKS5Q(PP?(5efXeyfI8&@4Vn&g(@cep3R@H|RMtZ3GTEx6mLg57Hk5%WqMT25^inJD#CQ z)My-neAY35JZyQ3w$m_;((ATQC{wY=$Y=iw7MuMCDo~bDDzO%d5%O50m7+9ZTIsw6 zrdymV#C6ItLhool7o${UJS^&zrHMW?_K9OuW*;Dj8hxAiUi?|Ki5nHSNR@v<5ySX#e_9(>mXk_8sbq`bq<*mtH`krw8OU~AyP0wZ9TJ~n z`(>g@J8p-mv=5V=E}F#M;wkaG&|sN89w%KtNx5oYa0Z~uzOD%FmQX$CE( zRtlkY{AlE-X>oh^y5>^TmRV%hX6EE9T(_aNhMHO*=n8J!(ACnjXRcpFC+r#E(g;DeG zQ})8I$UNhJ&V0P+mu6}4o#sIC$o`EbRTlGyvbFB!%vUBC6)j)<_LDCVMx(Q45vi~ zCC7PVXOrU4*V&{nXz3|6VqYpfUIaB_U%HZuK#jXcRZpJSzms!AP0Bq^Ci?fpE~ffk zO!1AA6TV}qzGErAW45fhm_VKZ?k3S}2EJp$^$rEf+PWqjFU??fZP) z4eHnefl1Vd+@&iDvR9*Hn#=0ty$W-YtmD1>n}{dY<^Jrls{oS zIBrC$=;{}DT^K%lqU*tz&G+_it(q_PyQ)`O7I#o5b>SCF7d1etqghl>HTXURAvFS- gtELWG4P=e^M&;K4o$VcTJ-&erh^gCuuy&FBKO6EGuK)l5 diff --git a/Release/BenzObstacleDetect.pdb b/Release/BenzObstacleDetect.pdb index b59790f93e27197c049e95f73900fd1342f7caf9..07dea61ffa9dc8a2546a4f591fcf43abbcfef00e 100644 GIT binary patch delta 1541 zcmZ8hZ%kWN6hHU%?X|Bh#R|2B;VcDK$J(-1f+Wa-NQR9IG{6MilvSuuWo_3MkOXXt zCL|^^Gtan$umoj(azYD=X7f*oIG5~$y6KXcG-`mw1o^NznVK!}oY&TL-sHUB`Q3Bw zx%ZrV?)%6;8#q}R3jsidr~d^6_#LI6L;fm&M*(0XTW2)v4-7=eK8|xd%^m85IO-nK zTMxNg5Wge-2=eBkAO)KYZ1ud;{paJ$(_8W z1;opUcM(O#!8l`Z67dJb-w^*l6mZ%>a~wQf!-K^|I)fz_gL7GZC5Gf8%C{(2QPL>u zD4QrZWv5Jlzg?IS7K$?BFbL%V(1@Z00TfwYiB36gMcZA>LWL>uS$iqYiFy1{h-EU) zIZy?tv^lOqyoywPQFU;d)zb}u|dVL-z`~7)bh5O5;&jloh;(Q0xjhJE1Zb5F! z%V0Z?)4|SXxe_xrqy8KU4HF83Dp@zrQE%5+ z$fxe`^+h{^en($KQv*z?F0QiMo80EdhR@z;d&U1n@9@oA)5W8$QT6zxuX;C{Mz4g_ z;@q}f+v1DjN`EkL&&qhhys@f3oNhk8Z)kZY`Rv38*Q84)zPT~5cO}VPSZ>fo+tr?M zuy!EqJ$CQH^X4-@8`n;i|FpTe>y7!Bth%|6Z+~c9@A-Od?%g&1?9^nD)ig&Vymkof1Pn{|H4!oMqlff>H5pl4>hw}&(BCxiX-Yob;6OTOEf0j(w3ra?|(F9 z9(&&+)mKzsY$(!C3|{~I$hlt&cbOuV2UfVU;M9+GCDM!h2&-F4^AFk#rFbPSB~yZp z11)$3D1)7Xq;^`_9!c*si;i3sC8zU1t(MJy%I2@J1qEBM#qZ!Fv{r~3sOGSbo%FG* z@m}Lof@&X>QNRinNT;2zDWF!69(MIuOFPFRQQtAg6TzXOOl>2MR$ssu_V;PBri1># z@uj$Hm^D_jWEV>wX2}tjoTP1&Cs=ZpC9krSfu)*Qs-LCaW~onD>WTr|x$mm9=hGCOJhztUW}R7%@?}#d@~r&c<4>vBjfoae_LL7pgK)ErX^!1G{C=W|%g^ z3M%Evf;}?mGE674HhV)Wb+HZ%CFS@uIs8GqykEn{`Oyyiu>vf-z_>ANeTqZlUohej_y7O^ delta 1006 zcmZ8fZAg<*6h7zO_HKKpvqUlRgNa{T>16W*wSGv=OmH$AqDWBcL|3-0Ijt4wQhyZv zD0`!bC1?r7~G6{^T4Wwu%?SV*@py`r|#L^w!1&Pe=d zyR(V-*yWn$zV_Pkhf#N?_#xf4f7$U%2Ef?2W;u;A>Vk|cFU zmk?5HkneEiu6fQ{YGd=42+Vo?QD0ZxT)t&JdO$f*Cm&ARH$Ae{s;D zXEuZndI?-KFkJ#G5tNZX(#KXBKo8xDr^7!64P9SBSJ>rh`boKm=Mfk7@Uwe3dtDI; zTX7@^$&sB^hNWazV2@-c^Lm6@1AC&C6^y+bVb;Jxuwt?T3AAUE%M4~yQ5DiMl!2PM zL(A3ZX#-n}r={6rcRHZa<$|V8d%La04QW(ZujX(~%(Pd!Jg;B; zH2hk(`c?93YCQLy`tgW&Ze)B*98=ag-RD}|{o;YYza}hhN>2&CFTQo(58vihUOXeKKJ=G5G`1VhmqsV*XLY9D zA+@=ysHCvQ*XEzT`^KKCUAdG9;-ahz3r8({N=`yN71=05IplB<1xZqBt%?JU=r?Lm zD`K=(+%l$QDKX%}zyJm&eH&EFY>iR{2RWKS1KVN+YErsFA)5316cQ;9#ZVxKbNTh7 zCkr|;FAal>7+k^NItI5fRDhul3_Zfo6o$TII3B|W*6vKTl860Lg