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

Committer:
hazheng
Date:
Tue Apr 18 19:42:15 2017 +0000
Branch:
Drift
Revision:
81:32bd7a25a699
Parent:
80:c85cb93713b3
Child:
82:992ba6f31e24
Added user interface for running state.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hazheng 80:c85cb93713b3 1 #include "RunningState.h"
hazheng 80:c85cb93713b3 2
hazheng 80:c85cb93713b3 3 #include "StateManager.h"
hazheng 80:c85cb93713b3 4
hazheng 80:c85cb93713b3 5 #include "ArduCAM.h"
hazheng 80:c85cb93713b3 6 #include "ArduUTFT.h"
hazheng 80:c85cb93713b3 7 #include "Motor.h"
hazheng 80:c85cb93713b3 8 #include "Servo.h"
hazheng 80:c85cb93713b3 9
hazheng 80:c85cb93713b3 10 #define PI 3.14159265f
hazheng 80:c85cb93713b3 11
hazheng 80:c85cb93713b3 12 RunningState::RunningState() :
hazheng 80:c85cb93713b3 13 m_speedRatio(1.0f),
hazheng 80:c85cb93713b3 14 m_lastAngle(0.0f),
hazheng 80:c85cb93713b3 15 m_lastAngleAbs(0.0f),
hazheng 80:c85cb93713b3 16 m_cornerRatio(1.0f),
hazheng 80:c85cb93713b3 17 m_lastLineFound(BOTH_FOUND)
hazheng 80:c85cb93713b3 18 {}
hazheng 80:c85cb93713b3 19
hazheng 80:c85cb93713b3 20 RunningState::~RunningState()
hazheng 80:c85cb93713b3 21 {}
hazheng 80:c85cb93713b3 22
hazheng 80:c85cb93713b3 23 void RunningState::DrawUserInterface()
hazheng 80:c85cb93713b3 24 {
hazheng 81:32bd7a25a699 25 ardu_utft_clr_scr();
hazheng 80:c85cb93713b3 26
hazheng 81:32bd7a25a699 27 ardu_utft_set_color(255, 0, 0);
hazheng 81:32bd7a25a699 28 ardu_utft_fill_rect(10, 10, 310, 230);
hazheng 81:32bd7a25a699 29 ardu_utft_set_color(255, 255, 255);
hazheng 81:32bd7a25a699 30 ardu_utft_print("STOP", 170, 120);
hazheng 80:c85cb93713b3 31 }
hazheng 80:c85cb93713b3 32
hazheng 80:c85cb93713b3 33 void RunningState::Update(float deltaTime)
hazheng 80:c85cb93713b3 34 {
hazheng 80:c85cb93713b3 35 image_processing();
hazheng 80:c85cb93713b3 36 uint8_t shouldTerminate = ardu_cam_get_is_encounter_terminate();
hazheng 80:c85cb93713b3 37
hazheng 80:c85cb93713b3 38 if(shouldTerminate)
hazheng 80:c85cb93713b3 39 {
hazheng 80:c85cb93713b3 40 TerminateProcess();
hazheng 80:c85cb93713b3 41 return;
hazheng 80:c85cb93713b3 42 }
hazheng 80:c85cb93713b3 43 //else
hazheng 80:c85cb93713b3 44 //{
hazheng 80:c85cb93713b3 45 // ardu_utft_print(" ", 230, 100);
hazheng 80:c85cb93713b3 46 //}
hazheng 80:c85cb93713b3 47
hazheng 80:c85cb93713b3 48 const volatile uint8_t* centerLine = ardu_cam_get_center_array();
hazheng 80:c85cb93713b3 49
hazheng 80:c85cb93713b3 50 /////////////Calculate the curvature:
hazheng 80:c85cb93713b3 51 float srcY = (0.0f + 1.0f) / 2.0f;
hazheng 80:c85cb93713b3 52 float srcX = static_cast<float>(centerLine[0] + centerLine[1]) / 2.0f;
hazheng 80:c85cb93713b3 53
hazheng 80:c85cb93713b3 54 float destY = static_cast<float>(CAM_ROI_UPPER_LIMIT - 1 + (CAM_ROI_UPPER_LIMIT - 2)) / 2.0f;
hazheng 80:c85cb93713b3 55 float destX = static_cast<float>(centerLine[CAM_ROI_UPPER_LIMIT - 1] + centerLine[CAM_ROI_UPPER_LIMIT - 2]) / 2.0f;
hazheng 80:c85cb93713b3 56
hazheng 80:c85cb93713b3 57 float disY = destY - srcY;
hazheng 80:c85cb93713b3 58 float disX = destX - srcX;
hazheng 80:c85cb93713b3 59
hazheng 80:c85cb93713b3 60 float angleRadians = -1.0f * static_cast<float>(atan(static_cast<double>(disX / disY)));
hazheng 80:c85cb93713b3 61 float angleDegrees = (angleRadians * (180.0f / PI));
hazheng 80:c85cb93713b3 62
hazheng 80:c85cb93713b3 63 ///////////////////////////////////////
hazheng 80:c85cb93713b3 64
hazheng 80:c85cb93713b3 65 /////////////Calculate the offset:
hazheng 80:c85cb93713b3 66 float centerPos = static_cast<float>(RESOLUTION_WIDTH / 2);
hazheng 80:c85cb93713b3 67 float offsetDegrees = ((srcX - centerPos) / centerPos) * SERVO_MAX_ANGLE;
hazheng 80:c85cb93713b3 68 //////////////////////////////////////
hazheng 80:c85cb93713b3 69
hazheng 80:c85cb93713b3 70 const uint8_t lineFoundRefRow = ((2 * CAM_ROI_UPPER_LIMIT) - 1) - (CAM_ROI_UPPER_LIMIT / 2);
hazheng 80:c85cb93713b3 71 //const uint8_t lineFoundRefTop = ((2 * CAM_ROI_UPPER_LIMIT) - 1);
hazheng 80:c85cb93713b3 72 //const uint8_t lineFoundRefBut = (CAM_ROI_UPPER_LIMIT);
hazheng 80:c85cb93713b3 73 const uint8_t isBorderFound = ardu_cam_get_is_border_found();
hazheng 80:c85cb93713b3 74
hazheng 80:c85cb93713b3 75 float totalAngleDegrees = (angleDegrees * 0.52f) + (offsetDegrees * (centerLine[lineFoundRefRow] != BOTH_FOUND ? 0.90f : 0.35f));
hazheng 80:c85cb93713b3 76
hazheng 80:c85cb93713b3 77 if(totalAngleDegrees > SERVO_MAX_ANGLE)
hazheng 80:c85cb93713b3 78 totalAngleDegrees = SERVO_MAX_ANGLE;
hazheng 80:c85cb93713b3 79 else if(totalAngleDegrees < -SERVO_MAX_ANGLE)
hazheng 80:c85cb93713b3 80 totalAngleDegrees = -SERVO_MAX_ANGLE;
hazheng 80:c85cb93713b3 81
hazheng 80:c85cb93713b3 82 if((totalAngleDegrees < 0.0f && (isBorderFound == LEFT_FOUND)) ||
hazheng 80:c85cb93713b3 83 (totalAngleDegrees > 0.0f && (isBorderFound == RIGHT_FOUND)))
hazheng 80:c85cb93713b3 84 {
hazheng 80:c85cb93713b3 85 totalAngleDegrees = ((-1.0f) * totalAngleDegrees);// + ((0.2f) * m_lastAngle);
hazheng 80:c85cb93713b3 86 }
hazheng 80:c85cb93713b3 87 //LOGI("%d %5.3f ", centerLine[lineFoundRefRow], totalAngleDegrees);
hazheng 80:c85cb93713b3 88 servo_set_angle(totalAngleDegrees);
hazheng 80:c85cb93713b3 89
hazheng 80:c85cb93713b3 90
hazheng 80:c85cb93713b3 91 float totalAngleDegreesAbs = abs(totalAngleDegrees);
hazheng 80:c85cb93713b3 92
hazheng 80:c85cb93713b3 93 if(totalAngleDegreesAbs > m_lastAngleAbs)
hazheng 80:c85cb93713b3 94 {
hazheng 80:c85cb93713b3 95 m_cornerRatio = 0.4;//(m_lastAngle / totalAngleDegrees);
hazheng 80:c85cb93713b3 96 }
hazheng 80:c85cb93713b3 97 else if(totalAngleDegreesAbs < m_lastAngleAbs)
hazheng 80:c85cb93713b3 98 {
hazheng 80:c85cb93713b3 99 m_cornerRatio = 0.8;//(m_lastAngle / totalAngleDegrees);
hazheng 80:c85cb93713b3 100 }
hazheng 80:c85cb93713b3 101 else
hazheng 80:c85cb93713b3 102 {
hazheng 80:c85cb93713b3 103 m_cornerRatio = 1.0f;
hazheng 80:c85cb93713b3 104 }
hazheng 80:c85cb93713b3 105
hazheng 80:c85cb93713b3 106 if(totalAngleDegreesAbs > 20.0f)
hazheng 80:c85cb93713b3 107 {
hazheng 80:c85cb93713b3 108 m_speedRatio = 0.350f;
hazheng 80:c85cb93713b3 109 }
hazheng 80:c85cb93713b3 110 else if(totalAngleDegreesAbs > 18.0f)
hazheng 80:c85cb93713b3 111 {
hazheng 80:c85cb93713b3 112 m_speedRatio = 0.80f;
hazheng 80:c85cb93713b3 113 }
hazheng 80:c85cb93713b3 114 else if(totalAngleDegreesAbs > 15.0f)
hazheng 80:c85cb93713b3 115 {
hazheng 80:c85cb93713b3 116 m_speedRatio = 0.90f;
hazheng 80:c85cb93713b3 117 }
hazheng 80:c85cb93713b3 118 else if(totalAngleDegreesAbs > 12.0f)
hazheng 80:c85cb93713b3 119 {
hazheng 80:c85cb93713b3 120 m_speedRatio = 0.92f;
hazheng 80:c85cb93713b3 121 }
hazheng 80:c85cb93713b3 122 else
hazheng 80:c85cb93713b3 123 {
hazheng 80:c85cb93713b3 124 m_speedRatio = 1.0f;
hazheng 80:c85cb93713b3 125 }
hazheng 80:c85cb93713b3 126
hazheng 80:c85cb93713b3 127
hazheng 80:c85cb93713b3 128 if(totalAngleDegrees < 0.0f)
hazheng 80:c85cb93713b3 129 {
hazheng 80:c85cb93713b3 130 motor_set_left_speed(m_speedRatio * m_cornerRatio * ((MOTOR_DIFF_MIN_SPEED) + ((1.0f - MOTOR_DIFF_MIN_SPEED) * ((SERVO_MAX_ANGLE - abs(totalAngleDegrees)) / SERVO_MAX_ANGLE))));
hazheng 80:c85cb93713b3 131 motor_set_right_speed(m_speedRatio * m_cornerRatio * 1.0f);
hazheng 80:c85cb93713b3 132 }
hazheng 80:c85cb93713b3 133 else
hazheng 80:c85cb93713b3 134 {
hazheng 80:c85cb93713b3 135 motor_set_right_speed(m_speedRatio * m_cornerRatio * ((MOTOR_DIFF_MIN_SPEED) + ((1.0f - MOTOR_DIFF_MIN_SPEED) * ((SERVO_MAX_ANGLE - abs(totalAngleDegrees)) / SERVO_MAX_ANGLE))));
hazheng 80:c85cb93713b3 136 motor_set_left_speed(m_speedRatio * m_cornerRatio * 1.0f);
hazheng 80:c85cb93713b3 137 }
hazheng 80:c85cb93713b3 138
hazheng 80:c85cb93713b3 139 m_lastAngle = totalAngleDegrees;
hazheng 80:c85cb93713b3 140 m_lastAngleAbs = totalAngleDegreesAbs;
hazheng 80:c85cb93713b3 141 m_lastLineFound = centerLine[lineFoundRefRow];
hazheng 80:c85cb93713b3 142 }
hazheng 80:c85cb93713b3 143
hazheng 80:c85cb93713b3 144 uint8_t RunningState::HasTouchPosFunction() const
hazheng 80:c85cb93713b3 145 {
hazheng 80:c85cb93713b3 146 return 0;
hazheng 80:c85cb93713b3 147 }
hazheng 80:c85cb93713b3 148
hazheng 80:c85cb93713b3 149 uint8_t RunningState::HasTouchIrqFunction() const
hazheng 80:c85cb93713b3 150 {
hazheng 80:c85cb93713b3 151 return 1;
hazheng 80:c85cb93713b3 152 }
hazheng 80:c85cb93713b3 153
hazheng 80:c85cb93713b3 154 void RunningState::TouchPosCallback(int16_t x, int16_t y)
hazheng 80:c85cb93713b3 155 {
hazheng 80:c85cb93713b3 156
hazheng 80:c85cb93713b3 157 }
hazheng 80:c85cb93713b3 158
hazheng 80:c85cb93713b3 159 void RunningState::TouchIrqCallback()
hazheng 80:c85cb93713b3 160 {
hazheng 80:c85cb93713b3 161 TerminateProcess();
hazheng 80:c85cb93713b3 162 }
hazheng 80:c85cb93713b3 163
hazheng 80:c85cb93713b3 164 void RunningState::TerminateProcess()
hazheng 80:c85cb93713b3 165 {
hazheng 80:c85cb93713b3 166 ardu_utft_print("F", 230, 100);
hazheng 80:c85cb93713b3 167 servo_set_angle(0.0f);
hazheng 80:c85cb93713b3 168 motor_set_right_speed(-1.0f);
hazheng 80:c85cb93713b3 169 motor_set_left_speed(-1.0f);
hazheng 80:c85cb93713b3 170 wait(0.4f);
hazheng 80:c85cb93713b3 171 motor_set_right_speed(0.0f);
hazheng 80:c85cb93713b3 172 motor_set_left_speed(0.0f);
hazheng 80:c85cb93713b3 173 state_manager_clear_current_state();
hazheng 80:c85cb93713b3 174 }