using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Test { class SickTimEnc { //状态指示变量 /// /// 指示初始化是否成功 /// public bool initialized { get; set; } /// /// 指示是否工作中 /// public bool working { get; set; } /// /// 指示是否检测到障碍物 /// public bool obstacleDetected { get; set; } /// /// 发送指令返回值 /// private int flag = 0; //通信参数 private static readonly object Lock = new object(); private IPAddress ipa; private int port; private TcpClient tcpClient; private NetworkStream stream; private int bufferSize = 16384; private const string startCmd = "02 73 52 4E 20 4C 4D 44 73 63 61 6E 64 61 74 61 03"; private const string endCmd = "02 73 45 4E 20 4C 4D 44 73 63 61 6E 64 61 74 61 20 30 03"; //防撞参数 public int maxDataCount { get; set; }//最大保留历史数据个数 public int left_range { get; set; } = 385;//325;//231;//271;//386;//366; public int right_range { get; set; } = 425;//485;//581;//541;//426;//446; private int ground_truth_height = 1700;//2200;//2300;//标准高度 private int min_num_point_of_hinder = 30;//20;//判定为障碍物的最少点的数目 private int min_obstacle_height = 500;//最小障碍物高度 private int max_axis_Y = 2000;//2250;//画图时Y轴最大量程 private List originDatalist;//原始数据数组 private List validNum;//811个整型值 private List> validNumBuffer;//保存历史点云数据 private List> validNumBufferKalman;//保存经过kalman滤波的历史点云数据 private List listy; private List listx; public List yFiltered { get; set; } public List yFilteredKalman { get; set; } //卡尔曼滤波参数 private List prevData, p, q, r, kGain; public SickTimEnc(string ip, int port) { initialized = false; maxDataCount = 3; originDatalist = new List(); validNum = new List(); validNumBuffer = new List>(); validNumBufferKalman = new List>(); prevData = new List(); p = new List(); q = new List(); r = new List(); kGain = new List(); for (int i = 0; i < right_range - left_range; i++) { prevData.Add(0); p.Add(450); q.Add(0.0001); r.Add(0.005); kGain.Add(0); } listy = new List(); listx = new List(); tcpClient = new TcpClient(); if(!IPAddress.TryParse(ip, out ipa)) { ipa = null; return; } try { tcpClient.Connect(ipa, port); stream = tcpClient.GetStream(); } catch { return; } initialized = true; } /// /// 启动雷达处理数据 /// public void work() { Task.Factory.StartNew(()=> { while (initialized) { try { if (working) { //开辟线程存储雷达原始数据字符串 lock (Lock) { originDatalist.Clear(); flag = sendCmd(startCmd); if (flag == 1) { byte[] buffer = new byte[bufferSize]; stream.Read(buffer, 0, buffer.Length); string str = HexStringToASCII(buffer); originDatalist.Add(str); } if (originDatalist.Count != 0) { for (int i = 0; i < originDatalist.Count; i++) { string ss = trimDataStr(originDatalist[i], "sRA LMDscandata 1 ", " not defined 0 0 0"); string[] data = ss.Split(' '); string number = data[22]; int length = Convert.ToInt32(number, 16); int temp = 0; //int[] validNum = new int[length]; //string aws = ""; //获取所有距离数值 validNum.Clear(); listy.Clear(); listx.Clear(); for (int j = 0; j < length; j++) { try { temp = Convert.ToInt32(data[23 + j], 16); } catch { temp = ground_truth_height; Console.WriteLine("数据转换异常"); } validNum.Add(temp); } for (int j = 0; j < length; j++) { double x = validNum[j] * Math.Cos((-45 + 0.333 * j) * Math.PI / 180); double y = validNum[j] * Math.Sin((-45 + 0.333 * j) * Math.PI / 180); listy.Add(y); listx.Add(x); } validNumBuffer.Add(listy); validNumBufferKalman.Add(kalmanFilter(listy)); while (validNumBufferKalman.Count > maxDataCount) { validNumBufferKalman.RemoveAt(0); validNumBuffer.RemoveAt(0); } if(validNumBufferKalman.Count == maxDataCount) { bool obstacle = false; yFiltered = dataFilter(validNumBuffer, out obstacle); yFilteredKalman = dataFilter(validNumBufferKalman, out obstacle); obstacleDetected = obstacle; } } } } Thread.Sleep(1); } else { //空闲状态 Thread.Sleep(1000); } } catch (Exception e) { Thread.Sleep(500); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } } }); } /// /// 暂停工作 /// /// public void Pause(bool ctrl) { working = !ctrl; } /// /// 停止工作 /// public void Stop() { working = false; flag = sendCmd(endCmd); if (stream != null) { stream.Close(); } if (tcpClient != null) { tcpClient.Close(); } } /// /// 向雷达发送指令 /// /// /// private int sendCmd(string cmd) { try { if (cmd.Equals(startCmd)) { byte[] byteStartCmd = HexStringToBinary(startCmd); string result = HexStringToASCII(byteStartCmd); byte[] b = Encoding.UTF8.GetBytes(result); stream.Write(b, 0, b.Length); return 1; } if (cmd.Equals(endCmd)) { byte[] byteStartCmd = HexStringToBinary(endCmd); string result = HexStringToASCII(byteStartCmd); byte[] b = Encoding.UTF8.GetBytes(result); stream.Write(b, 0, b.Length); return 2; } } catch { return 0; } return 0; } /// /// 将一条十六进制字符串转换为ASCII /// /// 一条十六进制字符串 /// 返回一条ASCII码 private static string HexStringToASCII(byte[] bt) { //byte[] bt = HexStringToBinary(hexstring); string lin = ""; for (int i = 0; i < bt.Length; i++) { lin = lin + bt[i] + " "; } string[] ss = lin.Trim().Split(new char[] { ' ' }); char[] c = new char[ss.Length]; int a; for (int i = 0; i < c.Length; i++) { a = Convert.ToInt32(ss[i]); c[i] = Convert.ToChar(a); } string b = new string(c); return b; } /// /// 16进制字符串转换为二进制数组 /// /// 用空格切割字符串 /// 返回一个二进制字符串 private static byte[] HexStringToBinary(string hexstring) { string[] tmpary = hexstring.Trim().Split(' '); byte[] buff = new byte[tmpary.Length]; for (int i = 0; i < buff.Length; i++) { buff[i] = Convert.ToByte(tmpary[i], 16); } return buff; } /// /// 截取数据段 /// /// /// /// /// private static string trimDataStr(string sourse, string startstr, string endstr) { string result = string.Empty; int startindex, endindex; try { startindex = sourse.IndexOf(startstr); if (startindex == -1) { return result; } string tmpstr = sourse.Substring(startindex + startstr.Length); endindex = tmpstr.IndexOf(endstr); if (endindex == -1) { return result; } result = tmpstr.Remove(endindex); } catch (Exception) { } return result; } /// /// 平滑数据,识别障碍物 /// /// /// /// private List dataFilter(List> y, out bool isObstacle) { List y_udt = new List(); isObstacle = false; int hinder_point_count = 0; for (int i = left_range; i < right_range; i++) { int hinder_frame_count = 0; for (int j = 0; j < y.Count; j++) { if (i != left_range && i != right_range - 1) { y[j][i] = (y[j][i - 1] + y[j][i] + y[j][i + 1]) / 3;//每个点的y为其和相邻两个点和的平均值 } double d = Math.Abs(y[j][i] - ground_truth_height); if (d > min_obstacle_height)//300 hinder_frame_count = hinder_frame_count + 1; } if (hinder_frame_count == y.Count) hinder_point_count = hinder_point_count + 1; y_udt.Add(y[y.Count - 1][i]); } if (hinder_point_count >= min_num_point_of_hinder) isObstacle = true; return y_udt; } /// /// 卡尔曼滤波 /// /// /// private List kalmanFilter(List data_in) { for (int i = left_range; i < right_range; i++) { p[i - left_range] = p[i - left_range] + q[i - left_range]; kGain[i - left_range] = p[i - left_range] / (p[i - left_range] + r[i - left_range]); data_in[i] = prevData[i - left_range] + (kGain[i - left_range] * (data_in[i] - prevData[i - left_range])); p[i - left_range] = (1 - kGain[i - left_range]) * p[i - left_range]; prevData[i - left_range] = data_in[i]; } return data_in; } } }