Form1.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. using snap7Enc;
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14. using System.Windows.Forms.DataVisualization.Charting;
  15. namespace Test
  16. {
  17. public partial class Form1 : Form
  18. {
  19. private TcpClient tcpClient;
  20. NetworkStream stream;
  21. private int bufferSize = 16384;
  22. private string startCmd = "02 73 52 4E 20 4C 4D 44 73 63 61 6E 64 61 74 61 03";
  23. private string endCmd = "02 73 45 4E 20 4C 4D 44 73 63 61 6E 64 61 74 61 20 30 03";
  24. int flag = 0;
  25. static int left_range = 385;//325;//231;//271;//386;//366;
  26. static int right_range = 425;//485;//581;//541;//426;//446;
  27. static int ground_truth_height = 1700;//2200;//2300;//标准高度
  28. static int min_num_point_of_hinder = 30;//20;//判定为障碍物的最少点的数目
  29. static int min_obstacle_height = 500;//最小障碍物高度
  30. static int max_axis_Y = 2000;//2250;//画图时Y轴最大量程
  31. private bool isok = false;
  32. private static readonly object Lock = new object();
  33. List<string> validdatalist;
  34. static List<int> errorIndex;
  35. static List<double> dis;
  36. List<List<double>> tempSeries_x, tempSeries_y, tempSeries_tempy;
  37. List<double> x_update, y_update, templisty_update;
  38. List<double> monitor_y;
  39. //List<double> templistx, templisty;
  40. int indexN = 0;
  41. //卡尔曼滤波参数
  42. static List<double> prevData, p, q, r, kGain;
  43. //************** plc相关参数 *************
  44. /// <summary>
  45. /// PLC 连接状态flag
  46. /// </summary>
  47. public bool isConnected = false;
  48. /// <summary>
  49. /// plc中cpu类型
  50. /// </summary>
  51. private const CpuType cpu = CpuType.S71200;
  52. /// <summary>
  53. /// PLC的IP地址
  54. /// </summary>
  55. private const string ip = "192.168.0.1";
  56. /// <summary>
  57. /// PLC的端口号
  58. /// </summary>
  59. private const Int16 rack = 0;
  60. /// <summary>
  61. /// 工作站号
  62. /// </summary>
  63. private const Int16 slot = 1;
  64. /// <summary>
  65. /// PLC S7连接对象
  66. /// </summary>
  67. protected static Plc plc = null;
  68. /// <summary>
  69. /// 用于将写PLC指令排队的阻塞队列
  70. /// </summary>
  71. private BlockingCollection<MsgNode> writingBlockingCollection = new BlockingCollection<MsgNode>();
  72. /// <summary>
  73. /// 写线程,控制PLC写入频率
  74. /// </summary>
  75. private Thread writeThread;
  76. /// <summary>
  77. /// 系统关闭
  78. /// </summary>
  79. private bool closed;
  80. /// <summary>
  81. /// 读写锁
  82. /// </summary>
  83. private object readWriteLock = new object();
  84. //写入频率
  85. private const int writeFreq = 25;
  86. private const short DB = 30;
  87. private const short ZPosition = 8;
  88. private const short ZThreshold = 200;
  89. private const short ZStart = 10;
  90. private const short ZStop = 12;
  91. private const short ZPause = 14;
  92. private short ZPositionValue = 0;
  93. private short ZStartValue = 0;
  94. private short ZStopValue = 0;
  95. private short ZPauseValue = 0;
  96. private bool startGoingDown = false;
  97. private bool laserWorking = false;
  98. //流程控制
  99. private void Start()
  100. {
  101. bool isObstacle = false;
  102. isok = false;
  103. List<string> datalist = new List<string>();
  104. //开辟线程存储雷达原始数据字符串
  105. Task.Factory.StartNew(() =>
  106. {
  107. while (!isok)
  108. {
  109. lock (Lock)
  110. {
  111. datalist.Clear();
  112. flag = sendCmd(startCmd);
  113. byte[] buffer = new byte[bufferSize];
  114. stream.Read(buffer, 0, buffer.Length);
  115. string str = HexStringToASCII(buffer);
  116. datalist.Add(str);
  117. }
  118. Thread.Sleep(1);
  119. }
  120. });
  121. //string testimg = "";
  122. Task.Factory.StartNew(() =>
  123. {
  124. while (!isok)
  125. {
  126. lock (Lock)
  127. {
  128. for (int i = 0; i < datalist.Count; i++)
  129. {
  130. string ss = validStr(datalist[i], "sRA LMDscandata 1 ", " not defined 0 0 0");
  131. string[] data = ss.Split(' ');
  132. string number = data[22];
  133. int a = Convert.ToInt32(number, 16);
  134. int[] validNum = new int[a];
  135. string aws = "";
  136. for (int j = 0; j < a; j++)
  137. {
  138. validNum[j] = Convert.ToInt32(data[23 + j], 16);
  139. aws = aws + validNum[j] + " ";
  140. }
  141. validdatalist.Add(aws);
  142. this.Invoke(new Action(() =>
  143. {
  144. System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
  145. sw.Start();
  146. aws.TrimEnd(' ');
  147. List<double> listy = new List<double>();
  148. List<double> listx = new List<double>();
  149. string[] origindata = aws.Split(' ');
  150. origindata = origindata.Where(s => !string.IsNullOrEmpty(s)).ToArray();
  151. int[] origindataTransformed = Array.ConvertAll<string, int>(origindata, int.Parse);
  152. int startDegree = (Convert.ToInt32(this.textBox1.Text) + 45) * 3;
  153. int endDegree = (Convert.ToInt32(this.textBox2.Text) + 45) * 3 + 1;
  154. for (int k = startDegree; k < endDegree; k++)
  155. {
  156. double x = origindataTransformed[k] * Math.Cos((-45 + 0.333 * k) * Math.PI / 180);
  157. double y = origindataTransformed[k] * Math.Sin((-45 + 0.333 * k) * Math.PI / 180);
  158. listy.Add(y);
  159. listx.Add(x);
  160. }
  161. this.chart1.Series[0].Points.Clear();
  162. //tempSeries_x.Add(listx);
  163. List<double> templisty = new List<double>();
  164. for (int j = 0; j < listy.Count; j++)
  165. {
  166. templisty.Add(listy[j]);
  167. }
  168. tempSeries_tempy.Add(templisty);
  169. listy = kalmanFilter(listy);
  170. tempSeries_y.Add(listy);
  171. if (tempSeries_y.Count >= 4)
  172. {
  173. tempSeries_y.RemoveAt(0);
  174. tempSeries_tempy.RemoveAt(0);
  175. }
  176. if (tempSeries_y.Count == 3)
  177. {
  178. y_update = dataFilter(tempSeries_y, out isObstacle);
  179. templisty_update = dataFilter(tempSeries_tempy, out isObstacle);
  180. this.label4.Text = isObstacle.ToString();
  181. InitChart(listx, y_update, templisty_update);
  182. }
  183. else
  184. {
  185. //InitChart(listx, listy,templisty);//
  186. }
  187. //List<double> dis = lineFit(listx, listy);
  188. //List<double> dis = lineFit2(listy);
  189. double difference = Convert.ToDouble(this.textBox3.Text);
  190. //bool isHinder = IsHinder(dis, difference);
  191. sw.Stop();
  192. Console.WriteLine(sw.ElapsedMilliseconds + "ms");
  193. //if (isHinder)
  194. //{
  195. // Console.WriteLine("结果:" + isHinder);
  196. // Console.WriteLine(sw.ElapsedMilliseconds + "ms");
  197. // for (int j = 0; j < listx.Count; j++)
  198. // {
  199. // Log.WriteData("ordata" + indexN, origindataTransformed[startDegree + j].ToString());
  200. // if (errorIndex.Exists(o => o == j + 1))
  201. // {
  202. // Log.WriteData("data" + indexN, origindataTransformed[startDegree + j] + " " + 1);
  203. // }
  204. // else
  205. // {
  206. // Log.WriteData("data" + indexN, origindataTransformed[startDegree + j] + " " + 0);
  207. // }
  208. // }
  209. // indexN++;
  210. //}
  211. }));
  212. }
  213. }
  214. Thread.Sleep(1);
  215. }
  216. });
  217. }
  218. private void Pause(bool ctrl)
  219. {
  220. isok = ctrl;
  221. }
  222. private void Stop()
  223. {
  224. isok = true;
  225. flag = sendCmd(endCmd);
  226. }
  227. public Form1()
  228. {
  229. InitializeComponent();
  230. validdatalist = new List<string>();
  231. tempSeries_x = new List<List<double>>();
  232. tempSeries_y = new List<List<double>>();
  233. tempSeries_tempy = new List<List<double>>();
  234. monitor_y = new List<double>();
  235. errorIndex = new List<int>();
  236. prevData = new List<double>();
  237. p = new List<double>();
  238. q = new List<double>();
  239. r = new List<double>();
  240. kGain = new List<double>();
  241. tcpClient = new TcpClient();
  242. tcpClient.Connect(IPAddress.Parse("192.168.0.77"), 2111);
  243. Console.WriteLine("连接成功");
  244. stream = tcpClient.GetStream();
  245. //templisty = new List<double>();
  246. for (int i=0;i < right_range-left_range;i++)
  247. {
  248. prevData.Add(0);
  249. p.Add(450);
  250. q.Add(0.0001);
  251. r.Add(0.005);
  252. kGain.Add(0);
  253. }
  254. //bool result = PLCConnect();
  255. //if (!result)
  256. // Environment.Exit(0);
  257. //else
  258. //{
  259. // MsgNode msg = new MsgNode();
  260. // msg.db = DB;
  261. // msg.length = 2;
  262. // Task.Factory.StartNew(() => {
  263. // while (!closed)
  264. // {
  265. // if (plc == null)
  266. // {
  267. // Thread.Sleep(1000);
  268. // continue;
  269. // }
  270. // msg.start = ZPosition;
  271. // ReadFromPLC(ref msg);
  272. // ZPositionValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  273. // msg.start = ZStart;
  274. // ReadFromPLC(ref msg);
  275. // ZStartValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  276. // msg.start = ZStop;
  277. // ReadFromPLC(ref msg);
  278. // ZStopValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  279. // msg.start = ZPause;
  280. // ReadFromPLC(ref msg);
  281. // ZPauseValue = BitConverter.ToInt16(msg.value.ToArray(), 0);
  282. // Console.WriteLine("position, start, stop, pause: "+ZPositionValue+", "+ZStartValue+", "+ZStopValue+", "+ZPauseValue);
  283. // if (ZPauseValue == 1)
  284. // {
  285. // Pause(true);
  286. // Console.WriteLine("暂停");
  287. // }
  288. // else
  289. // {
  290. // Pause(false);
  291. // //Console.WriteLine("恢复");
  292. // }
  293. // //收到开始下降信号
  294. // if (ZStartValue == 1 && ZStopValue!=1)
  295. // {
  296. // startGoingDown = true;
  297. // Console.WriteLine("下降过程");
  298. // }
  299. // else
  300. // {
  301. // startGoingDown = false;
  302. // Console.WriteLine("非下降过程");
  303. // }
  304. // //进入下降阶段
  305. // if (startGoingDown && ZPositionValue > ZThreshold)
  306. // {
  307. // if (!laserWorking)
  308. // {
  309. // Console.WriteLine("启动雷达");
  310. // //Start();
  311. // laserWorking = true;
  312. // }
  313. // }
  314. // //下降结束复位工作状态
  315. // if(laserWorking && ZStopValue == 1)
  316. // {
  317. // Console.WriteLine("雷达工作结束");
  318. // laserWorking = false;
  319. // }
  320. // Thread.Sleep(50);
  321. // }
  322. // });
  323. //}
  324. }
  325. //界面按钮
  326. private void button1_Click(object sender, EventArgs e)
  327. {
  328. Start();
  329. }
  330. private void button3_Click(object sender, EventArgs e)
  331. {
  332. isok = true;
  333. }
  334. private void button2_Click(object sender, EventArgs e)
  335. {
  336. isok = true;
  337. //for (int i = 0; i < validdatalist.Count; i++)
  338. //{
  339. // string temp = validdatalist[i];
  340. // string[] tempdata = temp.Split(' ');
  341. // for (int j = 0; j < tempdata.Length; j++)
  342. // {
  343. // Log.WriteData("data" + i, tempdata[j]);
  344. // }
  345. //}
  346. //datalist.Clear();
  347. flag = sendCmd(endCmd);
  348. //Environment.Exit(0);
  349. //this.Close();
  350. }
  351. /// <summary>
  352. /// 向雷达发送指令
  353. /// </summary>
  354. /// <param name="cmd"></param>
  355. /// <returns></returns>
  356. private int sendCmd(string cmd)
  357. {
  358. if (cmd.Equals(startCmd))
  359. {
  360. byte[] byteStartCmd = HexStringToBinary(startCmd);
  361. string result = HexStringToASCII(byteStartCmd);
  362. byte[] b = Encoding.UTF8.GetBytes(result);
  363. stream.Write(b, 0, b.Length);
  364. return 1;
  365. }
  366. if (cmd.Equals(endCmd))
  367. {
  368. byte[] byteStartCmd = HexStringToBinary(endCmd);
  369. string result = HexStringToASCII(byteStartCmd);
  370. byte[] b = Encoding.UTF8.GetBytes(result);
  371. stream.Write(b, 0, b.Length);
  372. return 2;
  373. }
  374. return 0;
  375. }
  376. /// <summary>
  377. /// 将一条十六进制字符串转换为ASCII
  378. /// </summary>
  379. /// <param name="hexstring">一条十六进制字符串</param>
  380. /// <returns>返回一条ASCII码</returns>
  381. private static string HexStringToASCII(byte[] bt)
  382. {
  383. //byte[] bt = HexStringToBinary(hexstring);
  384. string lin = "";
  385. for (int i = 0; i < bt.Length; i++)
  386. {
  387. lin = lin + bt[i] + " ";
  388. }
  389. string[] ss = lin.Trim().Split(new char[] { ' ' });
  390. char[] c = new char[ss.Length];
  391. int a;
  392. for (int i = 0; i < c.Length; i++)
  393. {
  394. a = Convert.ToInt32(ss[i]);
  395. c[i] = Convert.ToChar(a);
  396. }
  397. string b = new string(c);
  398. return b;
  399. }
  400. /// <summary>
  401. /// 16进制字符串转换为二进制数组
  402. /// </summary>
  403. /// <param name="hexstring">用空格切割字符串</param>
  404. /// <returns>返回一个二进制字符串</returns>
  405. private static byte[] HexStringToBinary(string hexstring)
  406. {
  407. string[] tmpary = hexstring.Trim().Split(' ');
  408. byte[] buff = new byte[tmpary.Length];
  409. for (int i = 0; i < buff.Length; i++)
  410. {
  411. buff[i] = Convert.ToByte(tmpary[i], 16);
  412. }
  413. return buff;
  414. }
  415. /// <summary>
  416. /// 截取数据段
  417. /// </summary>
  418. /// <param name="sourse"></param>
  419. /// <param name="startstr"></param>
  420. /// <param name="endstr"></param>
  421. /// <returns></returns>
  422. private static string validStr(string sourse, string startstr, string endstr)
  423. {
  424. string result = string.Empty;
  425. int startindex, endindex;
  426. try
  427. {
  428. startindex = sourse.IndexOf(startstr);
  429. if (startindex == -1)
  430. {
  431. return result;
  432. }
  433. string tmpstr = sourse.Substring(startindex + startstr.Length);
  434. endindex = tmpstr.IndexOf(endstr);
  435. if (endindex == -1)
  436. {
  437. return result;
  438. }
  439. result = tmpstr.Remove(endindex);
  440. }
  441. catch (Exception) { }
  442. return result;
  443. }
  444. /// <summary>
  445. /// 初始化图表
  446. /// </summary>
  447. private void InitChart(List<double> listx, List<double> listy, List<double> templisty)
  448. {
  449. //定义图表区域
  450. this.chart1.ChartAreas.Clear();
  451. ChartArea chartArea1 = new ChartArea("C1");
  452. this.chart1.ChartAreas.Add(chartArea1);
  453. //定义存储和显示点的容器
  454. this.chart1.Series.Clear();
  455. Series series1 = new Series("S1");
  456. series1.ChartArea = "C1";
  457. Series series2 = new Series("S2");
  458. series2.ChartArea = "C1";
  459. this.chart1.Series.Add(series1);
  460. this.chart1.Series.Add(series2);
  461. //this.chart1.
  462. //设置图表显示样式
  463. this.chart1.ChartAreas[0].AxisY.Minimum = 0;
  464. this.chart1.ChartAreas[0].AxisY.Maximum = max_axis_Y;
  465. this.chart1.ChartAreas[0].AxisY.Interval = 100;
  466. this.chart1.ChartAreas[0].AxisX.Minimum = -2300;// -200;
  467. this.chart1.ChartAreas[0].AxisX.Maximum = 2300;// 200;
  468. this.chart1.ChartAreas[0].AxisX.Interval = 100;// 100;
  469. this.chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
  470. this.chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
  471. this.chart1.ChartAreas[0].AxisY.Title = "Y";
  472. this.chart1.ChartAreas[0].AxisX.Title = "X";
  473. //this.chart1.ChartAreas[0].AxisX.ArrowStyle = AxisArrowStyle.Triangle;
  474. //this.chart1.ChartAreas[0].AxisY.ArrowStyle = AxisArrowStyle.Triangle;
  475. //设置标题
  476. this.chart1.Titles.Clear();
  477. this.chart1.Titles.Add("S01");
  478. this.chart1.Titles[0].Text = "雷达显示";
  479. this.chart1.Titles[0].ForeColor = Color.RoyalBlue;
  480. this.chart1.Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
  481. //设置图表显示样式
  482. this.chart1.Series[0].Color = Color.Red;
  483. this.chart1.Series[0].ChartType = SeriesChartType.Line;
  484. this.chart1.Series[1].Color = Color.Blue;
  485. this.chart1.Series[1].ChartType = SeriesChartType.Line;
  486. //List<double> dis = lineFit3(listy);
  487. for (int i = left_range; i < right_range; i++)
  488. {
  489. //this.chart1.Series[0].Points.AddXY(listx[i], max_axis_Y - listy[i - left_range]);//listy[i - left_range]
  490. //this.chart1.Series[1].Points.AddXY(listx[i], max_axis_Y - templisty[i - left_range]);
  491. this.chart1.Series[0].Points.AddXY(listx[i], listy[i - left_range]);//listy[i - left_range]
  492. this.chart1.Series[1].Points.AddXY(listx[i], templisty[i - left_range]);
  493. }
  494. }
  495. /// <summary>
  496. /// 线性拟合
  497. /// </summary>
  498. /// <param name="x"></param>
  499. /// <param name="y"></param>
  500. /// <returns></returns>
  501. private static List<double> lineFit(List<double> x, List<double> y)
  502. {
  503. double a, b, c;
  504. int size = x.Count;
  505. if (size < 2)
  506. {
  507. a = 0;
  508. b = 0;
  509. c = 0;
  510. return null;
  511. }
  512. double x_mean = 0;
  513. double y_mean = 0;
  514. for (int i = 0; i < size; i++)
  515. {
  516. x_mean += x[i];
  517. y_mean += y[i];
  518. }
  519. x_mean /= size;
  520. y_mean /= size; //至此,计算出了 x y 的均值
  521. double Dxx = 0, Dxy = 0, Dyy = 0;
  522. for (int i = 0; i < size; i++)
  523. {
  524. Dxx += (x[i] - x_mean) * (x[i] - x_mean);
  525. Dxy += (x[i] - x_mean) * (y[i] - y_mean);
  526. Dyy += (y[i] - y_mean) * (y[i] - y_mean);
  527. }
  528. double lambda = ((Dxx + Dyy) - Math.Sqrt((Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy)) / 2.0;
  529. double den = Math.Sqrt(Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx));
  530. a = Dxy / den;
  531. b = (lambda - Dxx) / den;
  532. c = -a * x_mean - b * y_mean;
  533. Console.WriteLine(a + " " + b + " " + c);
  534. dis = new List<double>();
  535. errorIndex.Clear();
  536. for (int i = 0; i < size; i++)
  537. {
  538. if (y[i] < (-a * x[i] - c) / b)
  539. {
  540. double d = Math.Abs(a * x[i] + b * y[i] + c) / Math.Sqrt(a * a + b * b);
  541. if (d > 40)
  542. {
  543. dis.Add(d);
  544. errorIndex.Add(i);
  545. }
  546. //Log.WriteLog(LogType.PROCESS, d + "");
  547. }
  548. }
  549. return dis;
  550. }
  551. private static List<double> lineFit2(List<double> y)
  552. {
  553. double b;
  554. int size = y.Count;
  555. if (size < 2)
  556. {
  557. b = 0;
  558. return null;
  559. }
  560. double sum = 0;
  561. for(int i = 0; i < size; i++)
  562. {
  563. sum += y[i];
  564. }
  565. b = sum / size;
  566. dis = new List<double>();
  567. errorIndex.Clear();
  568. for (int i = 0; i < size; i++)
  569. {
  570. if (y[i] < b)
  571. {
  572. double d = Math.Abs(y[i] - b);
  573. if (d > 40)
  574. {
  575. dis.Add(d);
  576. errorIndex.Add(i);
  577. }
  578. }
  579. }
  580. return dis;
  581. }
  582. /// <summary>
  583. /// 是否有障碍物
  584. /// </summary>
  585. /// <param name="testdata"></param>
  586. /// <param name="deviation"></param>
  587. /// <returns></returns>
  588. private static List<double> lineFit3(List<double> y)
  589. {
  590. double b;
  591. int size = y.Count;
  592. if (size < 2)
  593. {
  594. b = 0;
  595. return null;
  596. }
  597. double sum = 0;
  598. for (int i = left_range; i < right_range; i++)
  599. {
  600. sum += y[i];
  601. }
  602. b = sum / (right_range - left_range);
  603. dis = new List<double>();
  604. errorIndex.Clear();
  605. for (int i = left_range; i < right_range; i++)
  606. {
  607. double d = Math.Abs(y[i] - b);
  608. if (d > 20)
  609. {
  610. double y_update = 0;
  611. dis.Add(y_update);
  612. errorIndex.Add(i);
  613. }
  614. else
  615. {
  616. dis.Add(y[i]);
  617. }
  618. }
  619. return dis;
  620. }
  621. private static List<double> dataFilter(List<List<double>> y, out bool isObstacle)
  622. {
  623. List<double> y_udt = new List<double>();
  624. isObstacle = false;
  625. int hinder_point_count = 0;
  626. for (int i = left_range; i < right_range; i++)
  627. {
  628. int hinder_frame_count = 0;
  629. for(int j = 0; j < y.Count; j++)
  630. {
  631. if(i!=left_range && i!= right_range-1)
  632. {
  633. y[j][i] = (y[j][i - 1] + y[j][i] + y[j][i + 1]) / 3;//每个点的y为其和相邻两个点和的平均值
  634. }
  635. double d = Math.Abs(y[j][i] - ground_truth_height);
  636. if (d > min_obstacle_height)//300
  637. hinder_frame_count = hinder_frame_count + 1;
  638. }
  639. if (hinder_frame_count == y.Count)
  640. hinder_point_count = hinder_point_count + 1;
  641. y_udt.Add(y[y.Count - 1][i]);
  642. }
  643. if (hinder_point_count >= min_num_point_of_hinder)
  644. isObstacle = true;
  645. return y_udt;
  646. }
  647. private List<double> kalmanFilter(List<double> data_in)
  648. {
  649. for (int i = left_range; i < right_range; i++)
  650. {
  651. p[i - left_range] = p[i - left_range] + q[i - left_range];
  652. kGain[i - left_range] = p[i - left_range] / (p[i - left_range] + r[i - left_range]);
  653. data_in[i] = prevData[i - left_range] + (kGain[i - left_range] * (data_in[i] - prevData[i - left_range]));
  654. p[i - left_range] = (1 - kGain[i - left_range]) * p[i - left_range];
  655. prevData[i - left_range] = data_in[i];
  656. }
  657. return data_in;
  658. }
  659. private static bool IsHinder(List<double> testdata, double deviation)
  660. {
  661. bool isHinder = true;
  662. //Data errordata = new Data();
  663. List<int> recorddata = new List<int>();
  664. for (int i = 0; i < testdata.Count; i++)
  665. {
  666. if (testdata[i] > deviation)
  667. {
  668. //errordata.key = i;
  669. //errordata.value = testdata[i];
  670. //Console.WriteLine(i + " " + testdata[i]);
  671. recorddata.Add(i);
  672. }
  673. }
  674. if (recorddata.Count <= 5 || IsBorderUpon(recorddata, 10) < 1)
  675. {
  676. isHinder = false;
  677. }
  678. return isHinder;
  679. }
  680. /// <summary>
  681. /// 连续判断
  682. /// </summary>
  683. /// <param name="arr"></param>
  684. /// <param name="num"></param>
  685. /// <returns></returns>
  686. private static int IsBorderUpon(List<int> arr, int num)
  687. {
  688. var query = arr.OrderBy(p => p).Aggregate<int, List<List<int>>>(null, (m, n) =>
  689. {
  690. if (m == null) return new List<List<int>>() { new List<int>() { n } };
  691. if (m.Last().Last() != n - 1)
  692. {
  693. m.Add(new List<int>() { n });
  694. }
  695. else
  696. {
  697. m.Last().Add(n);
  698. }
  699. return m;
  700. });
  701. int flag = 0;
  702. for (int i = 0; i < query.Count; i++)
  703. {
  704. if (query[i].Count > 5)
  705. {
  706. flag++;
  707. }
  708. }
  709. return flag;
  710. }
  711. //********************** PLC ****************************
  712. /// <summary>
  713. /// 连接PLC
  714. /// </summary>
  715. /// <returns></returns>
  716. private bool PLCConnect()
  717. {
  718. closed = false;
  719. writeThread = new Thread(() =>
  720. {
  721. //Stopwatch stopwatch = new Stopwatch();
  722. while (!closed)
  723. {
  724. //stopwatch.Restart();
  725. bool result = WriteAccordingly();
  726. if (!result)
  727. Console.WriteLine("写PLC操作异常");
  728. Thread.Sleep(1000/writeFreq);
  729. //stopwatch.Stop();
  730. //Console.WriteLine(stopwatch.ElapsedMilliseconds / 1000.0f);
  731. }
  732. });
  733. writeThread.IsBackground = true;
  734. writeThread.Priority = ThreadPriority.AboveNormal;
  735. writeThread.Start();
  736. if (plc == null)
  737. {
  738. plc = new Plc(cpu, ip, rack, slot);
  739. }
  740. if (plc != null)
  741. {
  742. ErrorCode err = plc.Open();
  743. if (err != ErrorCode.NoError) { Console.WriteLine("connection error"); isConnected = false; }
  744. else { Console.WriteLine("connected"); isConnected = true; }
  745. }
  746. else { isConnected = false; }
  747. return isConnected;
  748. }
  749. /// <summary>
  750. /// 关闭PLC连接
  751. /// </summary>
  752. private void PLCDisconnect()
  753. {
  754. //try
  755. //{
  756. // if (writeThread != null)
  757. // writeThread.Abort();
  758. //}
  759. //catch (Exception ex) { Console.WriteLine("强制终止写PLC线程," + ex.Message); }
  760. closed = true;
  761. if (plc != null)
  762. {
  763. plc.Close();
  764. }
  765. }
  766. /// <summary>
  767. /// 从阻塞队列获取需写入PLC数据并写入PLC,时间间隔在线程中控制
  768. /// </summary>
  769. /// <returns></returns>
  770. private bool WriteAccordingly()
  771. {
  772. MsgNode msg = null;
  773. try
  774. {
  775. msg = writingBlockingCollection.Take();
  776. //Console.WriteLine("取出后," + writingBlockingCollection.Count);
  777. }
  778. catch (Exception ex) { Console.WriteLine("获取PLC写对象异常," + ex.Message); }
  779. if (msg == null || !msg.valid)
  780. {
  781. Console.WriteLine("msg is null or invalid");
  782. return false;
  783. }
  784. //更新设备状态
  785. isConnected = plc.IsConnected;
  786. if (isConnected)
  787. {
  788. lock (readWriteLock)
  789. {
  790. plc.WriteBytes(DataType.DataBlock, msg.db, msg.start, msg.value.ToArray());
  791. }
  792. }
  793. else { Console.WriteLine("掉线"); return false; }
  794. return true;
  795. }
  796. /// <summary>
  797. /// 读取PLC数据块
  798. /// </summary>
  799. /// <param name="whichToRead"></param>
  800. /// <param name="index"></param>
  801. /// <returns></returns>
  802. private void ReadFromPLC(ref MsgNode msg)
  803. {
  804. //更新设备状态
  805. isConnected = plc.IsConnected;
  806. List<object> result = new List<object>();
  807. if (!isConnected)
  808. {
  809. PLCConnect();
  810. }
  811. if (isConnected)
  812. {
  813. lock (readWriteLock)
  814. {
  815. msg.value = plc.ReadBytes(DataType.DataBlock, msg.db, msg.start, msg.length).ToList();
  816. if (msg.value.Count != msg.length)
  817. {
  818. msg.valid = false;
  819. }
  820. msg.value.Reverse();
  821. }
  822. }
  823. }
  824. /// <summary>
  825. /// 写入PLC,只支持1,2或4字节
  826. /// </summary>
  827. /// <param name="abstractPLCMsg"></param>
  828. /// <param name="whoami"></param>
  829. /// <returns></returns>
  830. private bool WriteToPLC(MsgNode msg)
  831. {
  832. //更新设备状态
  833. isConnected = plc.IsConnected;
  834. if (msg != null && isConnected)
  835. {
  836. msg.value.Reverse();
  837. writingBlockingCollection.Add(msg);
  838. //Console.WriteLine("加入后," + writingBlockingCollection.Count);
  839. return true;
  840. }
  841. else
  842. return false;
  843. }
  844. public class MsgNode : ICloneable
  845. {
  846. public int db;
  847. public int start;
  848. public int length;
  849. public List<byte> value;
  850. public bool valid;
  851. public MsgNode(int db, int start, int length, List<byte> value)
  852. {
  853. this.db = db;
  854. this.start = start;
  855. this.length = length;
  856. if(value!=null && value.Count != length)
  857. {
  858. valid = false;
  859. }
  860. else
  861. {
  862. valid = true;
  863. }
  864. this.value = value;
  865. }
  866. public MsgNode():this(0,0,0, new List<byte>())
  867. {
  868. }
  869. public object Clone()
  870. {
  871. MsgNode obj = new MsgNode();
  872. obj.db = db;
  873. obj.start = start;
  874. obj.length = length;
  875. obj.value = new List<byte>(value);
  876. obj.valid = valid;
  877. return obj;
  878. }
  879. }
  880. }
  881. }