<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      基于C#的機器學習--模糊邏輯-穿越障礙

       

      模糊邏輯-穿越障礙

      模糊邏輯。另一個我們經常聽到的術語。但它的真正含義是什么?它是否意味著不止一件事?我們馬上就會知道答案。

      我們將使用模糊邏輯來幫助引導一輛自動駕駛汽車繞過障礙,如果我們做得正確,我們將避開沿途的障礙。我們的自動導航車輛(AGV)將在障礙物周圍導航,感知其路徑上的障礙物。它將使用一個推理系統來幫助引導它前進。你或者用戶將能夠創造障礙或通過的方式,AGV必須避開或通過。你可以觀察跟蹤光束的工作,以及跟蹤AGV的路徑沿其路線。AGV所采取的每一步都將在用戶界面上進行更新,這樣您就可以看到發生了什么。

      在布爾邏輯中,事物或真或假,或黑或白。許多人不知道的是,還有一種被稱為多值邏輯的東西,它的真實值介于10之間。模糊邏輯是處理部分真理的多值邏輯的概念實現。例如很多人也不知道的著名的sigmoid函數,它是一種模糊化的方法。

      維基百科(建議大家多使用這個百科,百度百科真的只能用呵呵來形容)對此有很好的描述,如下:

      維基百科:

      "In this image, the meanings of the expressions cold, warm, and hot are represented by functions mapping a temperature scale. A point on that scale has three "truth values"-one for each of the three functions. The vertical line in the image represents a particular temperature that the three arrows (truth values) gauge. Since the red arrow points to zero,this temperature may be interpreted as "not hot". The orange arrow (pointing at 0.2) may describe it as "slightly warm" and the blue arrow (pointing at 0.8) "fairly cold"."

             在這幅圖中,cold(冷)、warm(暖)和hot(熱)表達式的含義由映射一個溫標的函數表示。這個尺度上的一個點有三個“真值”,三個函數各有一個。圖像中的垂直線表示三個箭頭(真值)測量的特定溫度。由于紅色箭頭指向零,這個溫度可以解釋為不熱 橙色的箭頭(指向0.2)可以描述為輕微溫暖,藍色的箭頭(指向0.8)可以描述為輕微溫暖很冷

             我們為什么要展示這個?因為,這個圖表和描述非常準確地描述了什么是模糊邏輯。我們將使用AForge.NET開源機器學習框架。這是一個很好的框架,它展示了使用推理引擎完成任務是多么容易。

             在這一章中,我們將討論:

      1. 模糊邏輯

      2. 避障與識別

      3. AGV

      模糊邏輯

      我們的應用程序將有兩個簡單的按鈕,一個用于運行模糊集測試,另一個用于運行語言變量測試。下面是示例應用程序的快速快照:

      創建此示例的代碼相對較小且簡單。這是當我們點擊Run Fuzzy Set Test按鈕時的樣子。我們將創建兩個模糊集(一個用于涼爽,一個用于溫暖),并為每個模糊集添加一些成員數據值,然后繪制它們: 

          #region 創建兩個模糊集來表示涼和暖的溫度
                  #region
                  TrapezoidalFunction function1 = new TrapezoidalFunction(13, 18, 23, 28);
                  FuzzySet fsCool = new FuzzySet("", function1);
                  double[,] coolValues = new double[20, 2];
                  for (int i = 10; i < 30; i++)
                  {
                      coolValues[i - 10, 0] = i;
                      coolValues[i - 10, 1] = fsCool.GetMembership(i);
                  }
                  chart?.UpdateDataSeries("", coolValues);
                  #endregion#region
                  TrapezoidalFunction function2 = new TrapezoidalFunction(23, 28, 33, 38);
                  FuzzySet fsWarm = new FuzzySet("", function2);
                  double[,] warmValues = new double[20, 2];
                  for (int i = 20; i < 40; i++)
                  {
                      warmValues[i - 20, 0] = i;
                      warmValues[i - 20, 1] = fsWarm.GetMembership(i);
                  }
                  chart?.UpdateDataSeries("", warmValues);
                  #endregion 暖 
          #endregion 創建兩個模糊集來表示涼和暖的溫度

      運行語言變量測試的代碼如下。同樣,我們創建模糊集,但這次我們創建4個而不是2個。與我們的第一個測試一樣,我們首先添加成員數據,然后繪圖: 

             LinguisticVariable lvTemperature = new LinguisticVariable("溫度", 0, 80);
                  TrapezoidalFunction function1 = new TrapezoidalFunction(10, 15, TrapezoidalFunction.EdgeType.Right);
                  FuzzySet fsCold = new FuzzySet("", function1);
                  lvTemperature.AddLabel(fsCold);
                  TrapezoidalFunction function2 = new TrapezoidalFunction(10, 15, 20, 25);
                  FuzzySet fsCool = new FuzzySet("", function2);
                  lvTemperature.AddLabel(fsCool);
                  TrapezoidalFunction function3 = new TrapezoidalFunction(20, 25, 30, 35);
                  FuzzySet fsWarm = new FuzzySet("", function3);
                  lvTemperature.AddLabel(fsWarm);
                  TrapezoidalFunction function4 = new TrapezoidalFunction(30, 35, TrapezoidalFunction.EdgeType.Left);
                  FuzzySet fsHot = new FuzzySet("", function4);
                  lvTemperature.AddLabel(fsHot);
                  double[][,] chartValues = new double[4][,];
                  for (int i = 0; i < 4; i++)
                      chartValues[i] = new double[160, 2]; 

      最后我們畫出這些值: 

              #region 語言變量的形狀——它的標簽從開始到結束的形狀
                  int j = 0;
                  for (float x = 0; x < 80; x += 0.5f, j++)
                  {
                      double y1 = lvTemperature.GetLabelMembership("", x);
                      double y2 = lvTemperature.GetLabelMembership("", x);
                      double y3 = lvTemperature.GetLabelMembership("", x);
                      double y4 = lvTemperature.GetLabelMembership("", x);
      
                      chartValues[0][j, 0] = x;
                      chartValues[0][j, 1] = y1;
                      chartValues[1][j, 0] = x;
                      chartValues[1][j, 1] = y2;
                      chartValues[2][j, 0] = x;
                      chartValues[2][j, 1] = y3;
                      chartValues[3][j, 0] = x;
                      chartValues[3][j, 1] = y4;
                  }
                  chart.UpdateDataSeries("", chartValues[0]);
                  chart.UpdateDataSeries("", chartValues[1]);
                  chart.UpdateDataSeries("", chartValues[2]);
                  chart.UpdateDataSeries("", chartValues[3]);
               #endregion 語言變量的形狀——它的標簽從開始到結束的形狀 

      語言變量的形狀:

      正如所看到的,我們能夠很容易地展示出維基百科定義所展示的視覺定義。

      模糊的自主移動小車

      在我們繼續之前,先看一下我們的應用程序將是什么樣子的,然后對推理引擎進行簡要的解釋:

      盡管AForge.NET使得我們很容易和透明的創建一個InferenceSystem推理系統)對象。

             讓我先來解釋下什么是模糊推理系統。模糊推理系統是一種能夠進行模糊計算的模型。這是使用數據庫、語言變量和規則庫完成的,所有這些都可以存儲在內存中。

             模糊推理系統的典型操作如下:

      1. 獲取數字輸入
      2. 結合激活規則的結果得到一個模糊輸出
      3. 驗證輸入激活了來自規則庫的哪些規則
      4. 利用帶有語言變量的數據庫獲取每個數字輸入的語言意義

      對于我們來講,大部分工作將在初始化我們的模糊邏輯系統時進行。讓我們將其分解為前面概述的各個步驟。

      首先,我們需要準備語言標簽(模糊集)組成的距離。他們分別是Near()Medium()Far()

                  #region 構成這些距離的語言標簽(模糊集)
      
                  FuzzySet fsNear = new FuzzySet("Near", new TrapezoidalFunction(15, 50, TrapezoidalFunction.EdgeType.Right));
      
                  FuzzySet fsMedium = new FuzzySet("Medium", new TrapezoidalFunction(15, 50, 60, 100));
      
                  FuzzySet fsFar = new FuzzySet("Far", new TrapezoidalFunction(60, 100, TrapezoidalFunction.EdgeType.Left));
      
                  #endregion 構成這些距離的語言標簽(模糊集)        

      接下來,我們初始化所需的語言變量。第一個是lvRight,它將是右側測量距離的變量:

                  #region 右側測量距離(輸入)
      
                  LinguisticVariable lvRight = new LinguisticVariable("RightDistance", 0, 120);
      
                  lvRight.AddLabel(fsNear);
      
                  lvRight.AddLabel(fsMedium);
      
                  lvRight.AddLabel(fsFar);
      
                  #endregion 右側測量距離(輸入)     

      現在,我們對左側測量距離的變量做同樣的操作:           

              #region 左側測量距離(輸入)
      
                  LinguisticVariable lvLeft = new LinguisticVariable("LeftDistance", 0, 120);
      
                  lvLeft.AddLabel(fsNear);
      
                  lvLeft.AddLabel(fsMedium);
      
                  lvLeft.AddLabel(fsFar);
      
              #endregion 左側測量距離(輸入)

      最后一個語言變量是前方測量距離:

              #region 前方測量距離(輸入)
      
                  LinguisticVariable lvFront = new LinguisticVariable("FrontalDistance", 0, 120);
      
                  lvFront.AddLabel(fsNear);
      
                  lvFront.AddLabel(fsMedium);
      
                  lvFront.AddLabel(fsFar);
      
              #endregion 前方測量距離(輸入) 

      現在我們關注組成這個角度的語言標簽(模糊集)。我們需要完成這一步,這樣才能創建最終的語言變量:

            #region 組成角度的語言標簽(模糊集)
      
                  FuzzySet fsVN = new FuzzySet("VeryNegative", new TrapezoidalFunction(-40, -35, TrapezoidalFunction.EdgeType.Right));
      
                  FuzzySet fsN = new FuzzySet("Negative", new TrapezoidalFunction(-40, -35, -25, -20));
      
                  FuzzySet fsLN = new FuzzySet("LittleNegative", new TrapezoidalFunction(-25, -20, -10, -5));
      
                  FuzzySet fsZero = new FuzzySet("Zero", new TrapezoidalFunction(-10, 5, 5, 10));
      
                  FuzzySet fsLP = new FuzzySet("LittlePositive", new TrapezoidalFunction(5, 10, 20, 25));
      
                  FuzzySet fsP = new FuzzySet("Positive", new TrapezoidalFunction(20, 25, 35, 40));
      
                  FuzzySet fsVP = new FuzzySet("VeryPositive", new TrapezoidalFunction(35, 40, TrapezoidalFunction.EdgeType.Left));
      
              #endregion 組成角度的語言標簽(模糊集) 

      現在我們可以創建角度的最終語言變量:

              #region
      
                  LinguisticVariable lvAngle = new LinguisticVariable("Angle", -50, 50);
      
                  lvAngle.AddLabel(fsVN);
      
                  lvAngle.AddLabel(fsN);
      
                  lvAngle.AddLabel(fsLN);
      
                  lvAngle.AddLabel(fsZero);
      
                  lvAngle.AddLabel(fsLP);
      
                  lvAngle.AddLabel(fsP);
      
                  lvAngle.AddLabel(fsVP);
      
              #endregion 角 

      現在我們可以繼續創建我們的模糊數據庫。對于我們的應用程序,這是一個語言變量的內存字典,如果您愿意的話可以將其實現為SQLNoSQL或任何其他類型的具體數據庫。

              #region 數據庫
      
                  Database fuzzyDB = new Database();
      
                  fuzzyDB.AddVariable(lvFront);
      
                  fuzzyDB.AddVariable(lvLeft);
      
                  fuzzyDB.AddVariable(lvRight);
      
                  fuzzyDB.AddVariable(lvAngle);
      
              #endregion 數據庫 

      接下來,我們將創建主推理引擎。下一行代碼中最有趣的是CentroidDifuzzifier。在推理過程的最后,我們需要一個數值來控制過程的其他部分。為了得到這個數字,我們采用了一種去模糊化的方法。

      我們的模糊推理系統的輸出是一組點火強度大于零的規則。這種點火強度對隨后的模糊規則集施加了約束。當我們把這些模糊集合放在一起時,它們會形成一個形狀,這就是語言輸出的意義。重心法將計算我們的形狀面積的中心,以獲得輸出的數值表示。它使用近似數,所以會選擇幾個區間進行計算。隨著時間間隔的增加,輸出的精度也會增加:     

      // 創建推理系統
      IS = new InferenceSystem(fuzzyDB, new CentroidDefuzzifier(1000));

      接下來,我們可以開始向我們的推理系統添加規則: 

                  // 直走
                  IS.NewRule("規則 1", "IF FrontalDistance IS Far THEN Angle IS Zero");
      
                  // 直走(如果可以走到任何地方)
                  IS.NewRule("規則 2", "IF FrontalDistance IS Far AND RightDistance IS Far AND LeftDistance IS Far THEN Angle IS Zero");
      
                  // 右側有墻
                  IS.NewRule("規則 3", "IF RightDistance IS Near AND LeftDistance IS Not Near THEN Angle IS LittleNegative");
      
                  // 左側有墻
                  IS.NewRule("規則 4", "IF RightDistance IS Not Near AND LeftDistance IS Near THEN Angle IS LittlePositive");
      
                  // 前方有墻 - 房間在右側
                  IS.NewRule("規則 5", "IF RightDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive");
      
                  // 前方有墻 - 房間在左側
                  IS.NewRule("規則 6", "IF LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Negative");
      
                  // 前方有墻 -兩邊都是房間 - 向右走
                  IS.NewRule("規則 7", "IF RightDistance IS Far AND LeftDistance IS Far AND FrontalDistance IS Near THEN Angle IS Positive");

      經過所有這些工作,我們的推理系統就已經準備好了!

                  if (FirstInference)
                      GetMeasures();
      
                  try
                  {
                      DoInference();
      
                      MoveAGV();
      
                      GetMeasures();
                  }
      
                  catch (Exception ex)
                  {
                      Debug.WriteLine(ex);
                  } 

      應用程序的主代碼循環如下所示。我們將詳細描述每個功能:

      讓我們快速看一下GetMeasures函數。獲取當前地圖以及AGV的位置后,調用HandleAGVOnWall函數,用于處理AGV碰到墻壁無法移動的情況。在這之后,DrawAGV在地圖中繪制AGV。最后,RefreshTerrain 刷新地圖:

              /// <summary>
              /// 得到傳感器的測量結果
              /// </summary>
              private void GetMeasures()
      
              {
                  #region 獲得自主移動小車的位置
      
                  pbTerrain.Image = CopyImage(OriginalMap);
      
                  Bitmap b = (Bitmap)pbTerrain.Image;
      
                  Point pPos = new Point(pbRobot.Left - pbTerrain.Left + 5, pbRobot.Top - pbTerrain.Top + 5);
      
                  #endregion 獲得自主移動小車的位置
      
                  HandleAGVOnWall(b, pPos);
      
                  DrawAGV(pPos, b);
      
                  RefreshTerrain();
              } 

      DrawAGV向左和向右遇到任何障礙時,如果選中Show beam復選框,就會看到前面、左邊和右邊的避束檢測器顯示:

              /// <summary>
              /// 繪制AGV
              /// </summary>
              /// <param name="pPos">坐標</param>
              /// <param name="b">位圖</param>
              private void DrawAGV(Point pPos, Bitmap b)
              {
                  Point pFrontObstacle = GetObstacle(pPos, b, -1, 0);
      
                  Point pLeftObstacle = GetObstacle(pPos, b, 1, 90);
      
                  Point pRightObstacle = GetObstacle(pPos, b, 1, -90);
      
      
                  #region 顯示線束
      
                  Graphics g = Graphics.FromImage(b);
      
                  if (cbLasers.Checked)
                  {
                      g.DrawLine(new Pen(Color.Red, 1), pFrontObstacle, pPos);
      
                      g.DrawLine(new Pen(Color.Red, 1), pLeftObstacle, pPos);
      
                      g.DrawLine(new Pen(Color.Red, 1), pRightObstacle, pPos);
                  }
      
                  #endregion 顯示線束
      
      
                  #region 繪制AGV
      
                  if (btnRun.Text != RunLabel)
                  {
                      g.FillEllipse(new SolidBrush(Color.Blue), pPos.X - 5, pPos.Y - 5, 10, 10);
                  }
      
                  g.DrawImage(b, 0, 0);
      
                  g.Dispose();
      
                  #endregion 繪制AGV
      
      
                  #region 更新顯示的距離
      
                  txtFront.Text = GetDistance(pPos, pFrontObstacle).ToString();
      
                  txtLeft.Text = GetDistance(pPos, pLeftObstacle).ToString();
      
                  txtRight.Text = GetDistance(pPos, pRightObstacle).ToString();
      
                  #endregion 更新顯示的距離
          } 

      DoInference函數運行我們的模糊推理系統的一個歷元(實例、生成等等)。最終,它負責確定AGV的下一個角度。

              /// <summary>
              /// 運行模糊推理系統的一個紀元
              /// </summary>
              private void DoInference()
              {
                  // 輸入設置
                  IS?.SetInput("RightDistance", Convert.ToSingle(txtRight.Text));
      
                  IS?.SetInput("LeftDistance", Convert.ToSingle(txtLeft.Text));
      
                  IS?.SetInput("FrontalDistance", Convert.ToSingle(txtFront.Text));
      
                  // 輸出設置
                  try
                  {
                      double NewAngle = IS.Evaluate("Angle");
      
                      txtAngle.Text = NewAngle.ToString("##0.#0");
      
                      Angle += NewAngle;
                  }
                  catch (Exception)
                  {
                  }
             } 

      MoveAGV函數負責將AGV移動一步。如果您檢查了跟蹤路徑的話,會發現這個函數中大約50%的代碼時用于繪制AGV的歷史軌跡的。

              /// <summary>
              /// 移動AGV
              /// </summary>
              private void MoveAGV()
              {
                  double rad = ((Angle + 90) * Math.PI) / 180;
      
                  int Offset = 0;
      
                  int Inc = -4;
      
      
                  Offset += Inc;
      
                  int IncX = Convert.ToInt32(Offset * Math.Cos(rad));
      
                  int IncY = Convert.ToInt32(Offset * Math.Sin(rad));
      
                  if (cbTrajeto.Checked)
                  {
                      Graphics g = Graphics.FromImage(OriginalMap);
      
                      Point p1 = new Point(pbRobot.Left - pbTerrain.Left + pbRobot.Width / 2, pbRobot.Top - pbTerrain.Top + pbRobot.Height / 2);
      
                      Point p2 = new Point(p1.X + IncX, p1.Y + IncY);
      
                      g.DrawLine(new Pen(new SolidBrush(Color.Green)), p1, p2);
      
                      g.DrawImage(OriginalMap, 0, 0);
      
                      g.Dispose();
                  }
      
                  pbRobot.Top = pbRobot.Top + IncY;
      
                  pbRobot.Left = pbRobot.Left + IncX;
             } 

      主要應用與顯示光束的選擇:

      隨著應用程序的運行,AGV成功導航障礙物,顯示路徑和光束。角度是AGV當前所面對的角度,傳感器讀數與前、左、右波束傳感器有關:

      我們的AGV成功地完成了穿越障礙,并繼續運行:

      軌跡路徑和顯示光束可單獨選擇:

      總結

             在這一章中,我們學習了各種類型的模糊邏輯實現,并看到了使用AForge.NET將這種邏輯添加到我們的應用程序中是多么的容易。在我們的下一章中,我們將開始深入研究自組織地圖,將我們的機器學習技能提升到一個新的層次。如果你還記得小學時上的美術課,這一章一定會給你帶來回憶。

      posted @ 2019-01-13 18:04  王振耀  閱讀(1911)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲精中文字幕二区三区| 国产日韩AV免费无码一区二区三区 | 国产草草影院ccyycom| 亚洲国产无套无码av电影| 国产精品久久自在自线不卡| 国产伦精品一区二区三区妓女| 中文日产乱幕九区无线码| 亚洲产在线精品亚洲第一站一 | 亚洲成在人线AV品善网好看| 欧美丰满熟妇xxxx性ppx人交| 中文字幕结果国产精品| 成人欧美日韩一区二区三区| 丁香婷婷在线观看| 东京热大乱系列无码| 亚洲AV永久无码一区| 兴文县| 国产精品久久久久无码av色戒| 色综合久久天天综线观看| 99久久免费精品色老| 日本一道一区二区视频| 国产在线观看免费观看| 大香伊蕉在人线国产免费| 蜜桃无码一区二区三区| 亚洲最大天堂在线看视频| 重口SM一区二区三区视频| 中文字幕在线日韩一区| 99精品久久久中文字幕| 临洮县| 精品国产午夜理论片不卡| 91麻豆亚洲国产成人久久| japanese人妻中文字幕| mm1313亚洲国产精品| 久久99精品久久久久久| 日产无人区一线二码三码2021| 亚洲理论在线A中文字幕| 中文字幕一区二区人妻| 国产成人午夜精品永久免费| 草草浮力影院| 欧美日韩一线| 水蜜桃视频在线观看免费18| 国产精品福利一区二区久久|