SmartWheels self-driving race car. Designed for NXP Cup. Uses FRDM-KL25Z, area-scan camera, and simple image processing to detect and navigate any NXP spec track.

Dependencies:   TSI USBDevice mbed-dev

Fork of SmartWheels by haofan Zheng

Files at this revision

API Documentation at this revision

Comitter:
hazheng
Date:
Thu Apr 20 21:04:10 2017 +0000
Parent:
99:c6665262fd3d
Commit message:
Better version of Intersection detection.

Changed in this revision

Hardwares/ArduCAM.cpp Show annotated file Show diff for this revision Revisions of this file
Hardwares/ArduCAM.h Show annotated file Show diff for this revision Revisions of this file
Hardwares/Motor.h Show annotated file Show diff for this revision Revisions of this file
StateMachine/RunningState.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r c6665262fd3d -r ffbeefc9e218 Hardwares/ArduCAM.cpp
--- a/Hardwares/ArduCAM.cpp	Thu Apr 20 16:23:19 2017 +0000
+++ b/Hardwares/ArduCAM.cpp	Thu Apr 20 21:04:10 2017 +0000
@@ -1,6 +1,6 @@
 #include "ArduCAM.h"
 
-//#define SW_DEBUG
+#define SW_DEBUG
 #include "GlobalVariable.h"
 #include "SWCommon.h"
 
@@ -25,16 +25,18 @@
 
 const static uint8_t CAM_BLK_CAL_LEFT  = ((RESOLUTION_WIDTH / 2) - 1);
 const static uint8_t CAM_BLK_CAL_RIGHT = ((RESOLUTION_WIDTH / 2) + 1);
-const static uint8_t TERMINATE_WIDTH = static_cast<uint8_t>(RESOLUTION_WIDTH * 0.28f);
+const static uint8_t TERMINATE_WIDTH = static_cast<uint8_t>(RESOLUTION_WIDTH * 0.29f);
 
 static DigitalOut cam_cs(PIN_ACC_CS, 1);
 
 static uint8_t temp_mid_pos = RESOLUTION_WIDTH / 2;
 static uint8_t black_calibrate = 70;
-static volatile uint8_t centerLine[CAM_ROI_UPPER_LIMIT * 2];
-static volatile uint8_t is_encounter_terminate = 0;
-//static volatile uint8_t is_border_find = BOTH_NOT_FOUND;
-static volatile uint8_t is_intersection_detected = 0;
+static uint8_t centerLine[CAM_ROI_UPPER_LIMIT * 2];
+static uint8_t leftLine[CAM_ROI_UPPER_LIMIT];
+static uint8_t rightLine[CAM_ROI_UPPER_LIMIT];
+static const uint8_t lineArrayEnd = CAM_ROI_UPPER_LIMIT - 1;
+static uint8_t is_encounter_terminate = 0;
+static uint8_t intersection_info = INTERSECTION_NULL;
 
 void cal_black_calibrate();
 
@@ -220,14 +222,21 @@
 
 }
 
-volatile const uint8_t* ardu_cam_get_center_array()
+ const uint8_t* ardu_cam_get_center_array()
 {
     return centerLine;
 }
 
 void image_processing()
 {
+    static uint8_t leftPos = 0;
+    static uint8_t rightPos = 0;
+    static uint8_t isBorderFound = BOTH_NOT_FOUND;
     
+    static uint8_t leftNearCenter1 = lineArrayEnd;
+    static uint8_t leftNearPos = 0;
+    static uint8_t rightNearCenter1 = leftNearCenter1;
+    static uint8_t rightNearPos = RESOLUTION_WIDTH;
     //while(true)
     {
         ardu_cam_start_capture();
@@ -240,7 +249,8 @@
         static float calTemp = 0.0f;
         calTemp = 0.0f;
         static uint16_t greenPixel = 0x00;
-        uint8_t isValid = 1;
+        static uint8_t isValid = 1;
+        isValid = 1;
         for (uint8_t j = 0; j < RESOLUTION_WIDTH; ++j)
         {
             if(CAM_BLK_CAL_LEFT < j && j <= CAM_BLK_CAL_RIGHT)
@@ -268,15 +278,16 @@
         }
 #endif
         //cal_black_calibrate();
-        uint8_t leftPos = 0;
-        uint8_t rightPos = 0;
-        uint8_t isBorderFound = BOTH_NOT_FOUND;
+        intersection_info = INTERSECTION_NULL;
         
-        is_intersection_detected = 0;
-        uint8_t leftNearCenter1 = 0;
-        uint8_t leftNearCenter2 = 0;
-        uint8_t rightNearCenter1 = 0;
-        uint8_t rightNearCenter2 = 0;
+        leftPos = 0;
+        rightPos = 0;
+        isBorderFound = BOTH_NOT_FOUND;
+        
+        leftNearCenter1 = lineArrayEnd;
+        leftNearPos = 0;
+        rightNearCenter1 = leftNearCenter1;
+        rightNearPos = RESOLUTION_WIDTH;
         
         is_encounter_terminate = 0;
         for (uint8_t i = 0; i < CAM_ROI_UPPER_LIMIT; ++i)
@@ -286,7 +297,8 @@
 #endif
             get_img_row_info(i, &leftPos, &rightPos, &isBorderFound);
             temp_mid_pos = (leftPos + rightPos) / 2;
-            uint8_t dis_btw_left_right = rightPos - leftPos - 1;
+    static uint8_t dis_btw_left_right;
+            dis_btw_left_right = rightPos - leftPos - 1;
             if(dis_btw_left_right < TERMINATE_WIDTH)
             {
                 is_encounter_terminate = 1;
@@ -296,27 +308,47 @@
             ardu_utft_set_camimg_rowcol(CAM_ROI_UPPER_LIMIT - i, temp_mid_pos);
             ardu_utft_write_DATA(0xF8, 0x00);
 #endif
-
-            centerLine[CAM_ROI_UPPER_LIMIT - i - 1] = temp_mid_pos;
-            centerLine[(2 * CAM_ROI_UPPER_LIMIT) - i - 1] = isBorderFound;
+    static uint8_t array_pos;
+            array_pos = lineArrayEnd - i;
+            centerLine[array_pos] = temp_mid_pos;
+            leftLine[array_pos] = leftPos;
+            rightLine[array_pos] = rightPos;
             
-            if(leftPos > leftNearCenter1)
+            centerLine[(2 * CAM_ROI_UPPER_LIMIT) - 1 - i] = isBorderFound;
+            
+            if(leftPos >= leftNearPos)
             {
-                leftNearCenter2 = leftNearCenter1; 
-                leftNearCenter1 = CAM_ROI_UPPER_LIMIT - i - 1;
+                leftNearCenter1 = lineArrayEnd - i;
+                leftNearPos = leftPos;
             }
-            if(rightPos < rightNearCenter1)
+            if(rightPos <= rightNearPos)
             {
-                rightNearCenter2 = rightNearCenter1;
-                rightNearCenter1 = CAM_ROI_UPPER_LIMIT - i - 1;
+                rightNearCenter1 = lineArrayEnd - i;
+                rightNearPos = rightPos;
             }
         }
+        if( (0 < rightNearCenter1 && rightNearCenter1 < lineArrayEnd) 
+            && ((rightLine[0] - rightLine[rightNearCenter1]) >= 4)
+            )
+        {
+            intersection_info = INTERSECTION_IN_R;
+        }
         
-        if( ((1 < rightNearCenter1 && rightNearCenter1 < (CAM_ROI_UPPER_LIMIT - 2)) && (abs(rightNearCenter1 - rightNearCenter2) == 1)) ||
-            ((1 < leftNearCenter1 && leftNearCenter1 < (CAM_ROI_UPPER_LIMIT - 2)) && (abs(leftNearCenter1 - leftNearCenter1) == 1)) )
+        if( (0 < leftNearCenter1 && leftNearCenter1 < lineArrayEnd) 
+            && ((leftLine[leftNearCenter1] - leftLine[0]) >= 4)
+            )
         {
-            is_intersection_detected = 1;
+            switch(intersection_info)
+            {
+            case INTERSECTION_IN_R:
+                intersection_info = INTERSECTION_IN;
+                break;
+            default:
+                intersection_info = INTERSECTION_IN_L;
+                break;
+            }
         }
+        //LOGI("#%d,%d,%d#", rightNearCenter1, abs(rightLine[0] - rightLine[rightNearCenter1]), abs(rightLine[lineArrayEnd] - rightLine[rightNearCenter1]));
     }
 }
 
@@ -432,9 +464,9 @@
     return ardu_cam_spi_read_8(ARDUCHIP_VER);
 }
 
-uint8_t ardu_cam_get_is_intersection_detected()
+uint8_t ardu_cam_get_intersection_info()
 {
-    return is_intersection_detected;
+    return intersection_info;
 }
 
 #ifdef __cplusplus
diff -r c6665262fd3d -r ffbeefc9e218 Hardwares/ArduCAM.h
--- a/Hardwares/ArduCAM.h	Thu Apr 20 16:23:19 2017 +0000
+++ b/Hardwares/ArduCAM.h	Thu Apr 20 21:04:10 2017 +0000
@@ -14,7 +14,7 @@
 #define RESOLUTION_WIDTH  80   /*!< @brief The resolution width we are using. */
 #define RESOLUTION_HEIGHT 60   /*!< @brief The resolution height we are using. */
 //#define MANUAL_REDUCE_RESULOTION_BY2
-#define CAM_ROI_UPPER_LIMIT 6  /*!< @brief The number of lines we actually using for the image processing. */
+#define CAM_ROI_UPPER_LIMIT 7  /*!< @brief The number of lines we actually using for the image processing. */
 
 
 #define BOTH_NOT_FOUND   0     /*!< @brief ENUM for whether the border is found. Both sides of the border is not found. */
@@ -22,6 +22,12 @@
 #define RIGHT_FOUND      2     /*!< @brief ENUM for whether the border is found. Right side of the border is found. */
 #define BOTH_FOUND       3     /*!< @brief ENUM for whether the border is found. Both sides of the border is found. */
 
+#define INTERSECTION_NULL 0
+#define INTERSECTION_IN_L   1
+#define INTERSECTION_IN_R   2
+#define INTERSECTION_IN     3
+#define INTERSECTION_OUT  5
+
 //=====Must pick one and only one here!=====
 //#define ARDUCAM_SHIELD_OV2640     /*!< @brief Use ArduCam Shield V2 with OV2640 camera module. */
 //#define ARDUCAM_SHIELD_OV7725     /*!< @brief Use ArduCam Shield V2 with OV7725 camera module. */
@@ -114,9 +120,9 @@
 
 /**
 * @brief Get the array that describe the center line that detected by the image processing.
-* @return A volatile pointer points to the array.
+* @return A  pointer points to the array.
 */
-volatile const uint8_t* ardu_cam_get_center_array();
+ const uint8_t* ardu_cam_get_center_array();
 
 /**
 * @brief Check if the capture is finished.
@@ -152,7 +158,7 @@
 */
 uint8_t ardu_cam_get_ver_num();
 
-uint8_t ardu_cam_get_is_intersection_detected();
+uint8_t ardu_cam_get_intersection_info();
 
 #ifdef __cplusplus
 }
diff -r c6665262fd3d -r ffbeefc9e218 Hardwares/Motor.h
--- a/Hardwares/Motor.h	Thu Apr 20 16:23:19 2017 +0000
+++ b/Hardwares/Motor.h	Thu Apr 20 21:04:10 2017 +0000
@@ -15,7 +15,7 @@
 #define MDIR_Backward 1  /*!< @brief Move backward is high voltage level. */
 
 
-#define MOTOR_MAX_SPEED_LIMIT 0.65f /*!< @brief The percentage of the max speed (power) level for the motor driver. (This will be multiply to the speed that finally set to the motor driver) */
+#define MOTOR_MAX_SPEED_LIMIT 0.55f /*!< @brief The percentage of the max speed (power) level for the motor driver. (This will be multiply to the speed that finally set to the motor driver) */
 
 #define MOTOR_DIFF_MIN_SPEED  0.55f /*!< @brief The percentage of the digital rear differential. (It should be used outside of these functions.) */
 
diff -r c6665262fd3d -r ffbeefc9e218 StateMachine/RunningState.cpp
--- a/StateMachine/RunningState.cpp	Thu Apr 20 16:23:19 2017 +0000
+++ b/StateMachine/RunningState.cpp	Thu Apr 20 21:04:10 2017 +0000
@@ -1,6 +1,6 @@
 #include "RunningState.h"
 
-#define SW_DEBUG
+//#define SW_DEBUG
 #include "SWCommon.h"
 
 #include "StateManager.h"
@@ -13,6 +13,8 @@
 #define PI 3.14159265f
 #include <math.h>
 
+//static DigitalOut led_g(LED_GREEN, 1);
+
 RunningState::RunningState() : 
     m_speedRatio(1.0f),
     m_lastAngle(0.0f),
@@ -73,21 +75,38 @@
     //const uint8_t lineFoundRefTop = ((2 * CAM_ROI_UPPER_LIMIT) - 1);
     //const uint8_t lineFoundRefBut = (CAM_ROI_UPPER_LIMIT);
     //const uint8_t isBorderFound = ardu_cam_get_is_border_found();
-    const uint8_t isIntersectionDetected = ardu_cam_get_is_intersection_detected();
-    
-    LOGI("%d", isIntersectionDetected);
+    const uint8_t intersectionInfo = ardu_cam_get_intersection_info();
 
-    float totalAngleDegrees = (angleDegrees * 0.52f) + (offsetDegrees * (centerLine[lineFoundRefRow] != BOTH_FOUND ? 0.90f : 0.35f));
+    float totalAngleDegrees = (angleDegrees * 0.55f) + (offsetDegrees * (centerLine[lineFoundRefRow] != BOTH_FOUND ? 0.90f : 0.35f));
     
     if(totalAngleDegrees > SERVO_MAX_ANGLE)
         totalAngleDegrees = SERVO_MAX_ANGLE;
     else if(totalAngleDegrees < -SERVO_MAX_ANGLE)
         totalAngleDegrees = -SERVO_MAX_ANGLE;
     
+    switch(intersectionInfo)
+    {
+    case INTERSECTION_IN_R:
+        totalAngleDegrees = -9.0f;
+        //led_g = 0;
+        break;
+    case INTERSECTION_IN_L:
+        totalAngleDegrees = 9.0f;
+        //led_g = 0;
+        break;
+    case INTERSECTION_IN:
+        //led_g = 0;
+        break;
+    default:
+        //led_g = 1;
+        break;
+    }
+    /*
     if(isIntersectionDetected)
     {
         totalAngleDegrees = ((-0.2f) * totalAngleDegrees);// + ((0.2f) * m_lastAngle);
     }
+    */
     //LOGI("%d %5.3f ", centerLine[lineFoundRefRow], totalAngleDegrees);
     servo_set_angle(totalAngleDegrees);