Labyrint Problemlösaren Robot, med artificiell intelligens med Arduino (7 / 10 steg)
Steg 7: Förenkla (optimera) sökvägen
Låt oss återvända till vårt exempel. Ser den första gruppen av korsningar, insåg vi att den första vänster förgrena sig är i själva verket en "återvändsgränd" och så, om roboten i stället för en "vänster Back-vänster" bara gått rakt på den första korsningen, mycket energi och tid skulle sparas! Med andra ord, skulle en sekvens "LBL" i själva verket vara samma som "S". Det är precis hur den fullständiga sökvägen kan optimeras. Om du analise alla möjligheter där en "U-sväng" används, uppsättningen 3 korsningar där denna "kovändning" ("B") visas ("xBx") kan minskas till en enda.
Ovanstående är endast ett exempel, nedan hittar du den kompletta listan av möjligheter (prova det):
- LBR = B
- LBS = R
- RBL = B
- SBL = R
- SBS = B
- LBL = S
Tar den fullständiga sökvägen eller vår exempel, kan vi minska det:
Stig = [LBLLLBSBLLBSLL] == > LBL = S
Stig = [SLLBSBLLBSLL] == > LBS = R
Stig = [SLRBLLBSLL] == > RBL = B
Stig = [SLBLBSLL] == > LBL = S
Stig = [SSBSLL] == > SBS = B
Stig = [SBLL] == > SBL = R
Stig = [RL]
Fantastiskt! Titta på exemplet det är mycket tydligt att om roboten tar höger vid första korsningen och efter det, en vänster, kommer det nå slutet av labyrinten i den kortaste vägen!
Första banan av labyrint Problemlösaren totala koden kommer att konsolideras i funktionen mazeSolve(). Denna funktion är i själva verket funktionen loop() använt tidigare, men med alla dessa åtgärder för optimering av lagring och sökvägen.
När den första banan slutade, måste Stig [] matrisen optimerad sökvägen. En ny variabel införs
unsigned int status = 0; lösa = 0; kommer labyrint slutet = 1
Nedan funktionen första banan:
void mazeSolve(void)
{
medan (! status)
{
readLFSsensors();
Switch (läge)
{
fall NO_LINE:
motorStop();
goAndTurn (vänster, 180);
recIntersection('B');
bryta;
fall CONT_LINE:
runExtraInch();
readLFSsensors();
om (läge! = CONT_LINE) {goAndTurn (vänster, 90); recIntersection('L');}
annat mazeEnd();
bryta;
fall RIGHT_TURN:
runExtraInch();
readLFSsensors();
om (läge == NO_LINE) {goAndTurn (rätt, 90). recIntersection('R');}
annat recIntersection('S');
bryta;
fall LEFT_TURN:
goAndTurn (vänster, 90);
recIntersection('L');
bryta;
fall FOLLOWING_LINE:
followingLine();
bryta;
}
}
}
Här introducerades en ny funktion: recIntersection (riktning)
Denna funktion används för butiken i korsningen och även att ringa en annan funktion simplifyPath(), som kommer att minska gruppen av 3 korsningar som innebär en "kovändning" som vi såg innan.
void recIntersection(char direction)
{
sökväg [pathLength] = riktning; Lagra korsningen i path-variabeln.
pathLength ++;
simplifyPath(); Förenkla den lärda vägen.
}
ÄRAN för den simplifyPath () funktion är att Patrick McCabe för sökvägen Solving kod (för detaljer, vänligen besök https://patrickmccabemakes.com! Strategin att sökvägen förenkling är att varje gång vi möter en sekvens xBx, vi kan förenkla det genom att skära ut återvändsgränd. Till exempel LBL == > S som vi såg i exemplet.
void simplifyPath()
{
om (pathLength < 3 || sökväg [pathLength-2]! = 'B') återvända; bara förenkla vägen om det näst sista tur var en "B"
int totalAngle = 0;
int i;
för (jag = 1; jag < = 3; i ++)
{
Switch(Path[pathLength-i])
{
fallet "R":
totalAngle += 90.
bryta;
fallet "L":
totalAngle += 270;
bryta;
fallet "B":
totalAngle += 180;
bryta;
}
}
totalAngle = totalAngle % 360; Få vinkeln som ett tal mellan 0 och 360 grader.
Switch(totalAngle) / / byta ut alla dessa varv med en.
{
fall 0:
sökväg [pathLength - 3] = s ';
bryta;
fall 90:
sökväg [pathLength - 3] = 'R';
bryta;
fall 180:
sökväg [pathLength - 3] = "B";
bryta;
fall 270:
sökväg [pathLength - 3] = 'L';
bryta;
}
pathLength-= 2. Sökvägen är nu två steg kortare.
}