working algorithm in large room

This commit is contained in:
MaximZaitsev
2016-08-31 18:19:35 +03:00
parent af1ee06ec6
commit 13ddf0ebf5
5 changed files with 101 additions and 41 deletions
+13 -6
View File
@@ -1,5 +1,6 @@
import Exceptions.InactiveCarException import Exceptions.InactiveCarException
import algorithm.AbstractAlgorithm import algorithm.AbstractAlgorithm
import algorithm.AlgorithmThread
import algorithm.RoomBypassingAlgorithm import algorithm.RoomBypassingAlgorithm
import algorithm.RoomModel import algorithm.RoomModel
import car.client.CarClient import car.client.CarClient
@@ -15,6 +16,7 @@ object DebugClInterface {
val exchanger = Exchanger<IntArray>() val exchanger = Exchanger<IntArray>()
var algorithmImpl: AbstractAlgorithm? = null var algorithmImpl: AbstractAlgorithm? = null
var algorithmThread: AlgorithmThread? = null
private val routeRegex = Regex("route [0-9]{1,10}") private val routeRegex = Regex("route [0-9]{1,10}")
private val sonarRegex = Regex("sonar [0-9]{1,10}") private val sonarRegex = Regex("sonar [0-9]{1,10}")
@@ -101,20 +103,25 @@ object DebugClInterface {
private fun executeAlg(readString: String) { private fun executeAlg(readString: String) {
val params = readString.split(" ") val params = readString.split(" ")
var count = val count =
if (params.size == 2) try { if (params.size == 2) try {
params[1].toInt() params[1].toInt()
} catch (e: Exception) { } catch (e: Exception) {
1 1
} else 1 } else 1
if (algorithmImpl == null) { var alg = algorithmImpl
algorithmImpl = RoomBypassingAlgorithm(Environment.map.values.last(), exchanger) if (alg == null) {
alg = RoomBypassingAlgorithm(Environment.map.values.last(), exchanger)
} }
while (count > 0) { var algThread = algorithmThread
count-- if (algThread == null) {
algorithmImpl!!.iterate() algThread = AlgorithmThread(alg)
algThread.start()
} }
algorithmImpl = alg
algThread.setCount(count)
algorithmThread = algThread
} }
private fun executeDebugInfoCommand(readString: String) { private fun executeDebugInfoCommand(readString: String) {
@@ -15,6 +15,7 @@ import java.util.*
import java.util.concurrent.Exchanger import java.util.concurrent.Exchanger
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
import kotlin.concurrent.thread
abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntArray>) { abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntArray>) {
@@ -63,8 +64,6 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
try { try {
val distances = exchanger.exchange(IntArray(0), 300, TimeUnit.SECONDS) val distances = exchanger.exchange(IntArray(0), 300, TimeUnit.SECONDS)
return distances return distances
} catch (e: InterruptedException) {
println("don't have response from car!")
} catch (e: TimeoutException) { } catch (e: TimeoutException) {
println("don't have response from car. Timeout!") println("don't have response from car. Timeout!")
} }
@@ -77,6 +76,8 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
moveCar(requestBytes) moveCar(requestBytes)
} }
private fun moveCar(messageBytes: ByteArray) { private fun moveCar(messageBytes: ByteArray) {
val request = getDefaultHttpRequest(thisCar.host, setRouteMetricUrl, messageBytes) val request = getDefaultHttpRequest(thisCar.host, setRouteMetricUrl, messageBytes)
try { try {
@@ -87,8 +88,6 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
try { try {
exchanger.exchange(IntArray(0), 60, TimeUnit.SECONDS) exchanger.exchange(IntArray(0), 60, TimeUnit.SECONDS)
return return
} catch (e: InterruptedException) {
println("don't have response from car!")
} catch (e: TimeoutException) { } catch (e: TimeoutException) {
println("don't have response from car. Timeout!") println("don't have response from car. Timeout!")
} }
@@ -0,0 +1,31 @@
package algorithm
import kotlin.concurrent.thread
class AlgorithmThread(val algorithmImpl: AbstractAlgorithm) : Thread() {
private var count = 0
override fun run() {
while (true) {//todo while !alrightmImpl.isDone(), but need check it
try {
if (count > 0) {
algorithmImpl.iterate()
count--
} else {
Thread.sleep(1000)
}
} catch (e: InterruptedException) {
}
}
}
fun setCount(count: Int) {
this.count = count
}
fun cancel() {
count = 0
}
}
@@ -1,5 +1,6 @@
package algorithm package algorithm
import Logger.log
import RouteMetricRequest import RouteMetricRequest
import SonarRequest import SonarRequest
import algorithm.geometry.Angle import algorithm.geometry.Angle
@@ -8,7 +9,6 @@ import algorithm.geometry.Point
import algorithm.geometry.Wall import algorithm.geometry.Wall
import objects.Car import objects.Car
import java.util.concurrent.Exchanger import java.util.concurrent.Exchanger
import Logger.log
class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : AbstractAlgorithm(thisCar, exchanger) { class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : AbstractAlgorithm(thisCar, exchanger) {
@@ -19,14 +19,14 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
override val WINDOW_SIZE = 3 override val WINDOW_SIZE = 3
//SHOULD BE CALIBRATED BEFORE RUNNING!!!!!!!!!!! //SHOULD BE CALIBRATED BEFORE RUNNING!!!!!!!!!!!
private val CHARGE_CORRECTION = 0.85 private val CHARGE_CORRECTION = 1.02//on full charge ok is 0.83 - 0.86
private val MAX_DISTANCE_TO_WALL_AHEAD = 30 // reached the corner and should turn left private val MAX_DISTANCE_TO_WALL_AHEAD = 55 // reached the corner and should turn left
private val OUTER_CORNER_DISTANCE_THRESHOLD = 60 // reached outer corner private val OUTER_CORNER_DISTANCE_THRESHOLD = 90 // reached outer corner
private val ISOSCALENESS_MIN_DIFF = 5 // have to correct alignment to the wall private val ISOSCALENESS_MIN_DIFF = 5 // have to correct alignment to the wall
private val ISOSCALENESS_MAX_DIFF = 50 // almost reached outer corner but not yet, and 120 meas. founds far wall private val ISOSCALENESS_MAX_DIFF = 50 // almost reached outer corner but not yet, and 120 meas. founds far wall
private val DISTANCE_TO_WALL_UPPER_BOUND = 50 // have to move closer to the parallel wall private val DISTANCE_TO_WALL_UPPER_BOUND = 60 // have to move closer to the parallel wall
private val DISTANCE_TO_WALL_LOWER_BOUND = 25 // have to move farther to the parallel wall private val DISTANCE_TO_WALL_LOWER_BOUND = 40 // have to move farther to the parallel wall
private val SPURIOUS_REFLECTION_DIFF = 70 // we're approaching corner and get spurious reflection from two walls on 60 meas. ! Should be before outer corner case ! private val SPURIOUS_REFLECTION_DIFF = 70 // we're approaching corner and get spurious reflection from two walls on 60 meas. ! Should be before outer corner case !
private var calibrateAfterRotate = false private var calibrateAfterRotate = false
@@ -70,7 +70,12 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
for (i in 0..15 step 5) { for (i in 0..15 step 5) {
val distRightForward = anglesDistances[Angle(70 + i)]!! val distRightForward = anglesDistances[Angle(70 + i)]!!
val distRightBackward = anglesDistances[Angle(110 - i)]!! val distRightBackward = anglesDistances[Angle(110 - i)]!!
if (distRightBackward.distance > (average * 1.5) || distRightForward.distance > (average * 1.5)) { if (distRightBackward.distance == -1 || distRightForward.distance == -1) {
log("Found -1 in angle distances, passing")
continue
}
if (distRightBackward.distance > (average * 1.5) || distRightForward.distance > (average * 1.5) ||
distRightBackward.distance < (average / 2) || distRightForward.distance < (average / 2)) {
continue continue
} }
@@ -93,16 +98,20 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0)) val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0))
val rotationDirection = if (anglesDistances[Angle(90)]!!.distance > 50) RIGHT else LEFT val rotationDirection = if (anglesDistances[Angle(90)]!!.distance > 50) RIGHT else LEFT
val backRotationDirection = if (rotationDirection == RIGHT) LEFT else RIGHT
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD)) resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD, backRotationDirection))
resultBuilder.setDistances(getIntArray(10, 10)) resultBuilder.setDistances(getIntArray(15, 20, 5))
return resultBuilder.build() return resultBuilder.build()
} }
private fun moveForward(): RouteMetricRequest { private fun moveForward(distToWall: Int): RouteMetricRequest {
val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0)) val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0))
resultBuilder.setDirections(getIntArray(FORWARD)) resultBuilder.setDirections(getIntArray(FORWARD))
resultBuilder.setDistances(getIntArray(20)) if (distToWall == -1 || distToWall > 200) {
resultBuilder.setDistances(getIntArray(50))
} else {
resultBuilder.setDistances(getIntArray(Math.max(distToWall / 4, 20)))
}
return resultBuilder.build() return resultBuilder.build()
} }
@@ -126,12 +135,19 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
override fun getCommand(anglesDistances: Map<Angle, AngleData>, state: CarState): RouteMetricRequest? { override fun getCommand(anglesDistances: Map<Angle, AngleData>, state: CarState): RouteMetricRequest? {
val dist0 = anglesDistances[Angle(0)]!! val dist0 = anglesDistances[Angle(0)]!!
val dist70 = anglesDistances[Angle(70)]!! val dist70 = anglesDistances[Angle(70)]!!
val dist80 = anglesDistances[Angle(80)]!!
val dist90 = anglesDistances[Angle(90)]!! val dist90 = anglesDistances[Angle(90)]!!
val dist100 = anglesDistances[Angle(100)]!!
val dist110 = anglesDistances[Angle(110)]!! val dist110 = anglesDistances[Angle(110)]!!
val sonarAngle = carAngle - 90 val sonarAngle = carAngle - 90
if (anglesDistances.filter { it.value.angle.degs() >= 60 && it.value.angle.degs() <= 120 && it.value.distance == -1 }.size != 0) { if (anglesDistances.filter {
log("Found -1 in angle distances, passing") it.value.angle.degs() >= 60
&& it.value.angle.degs() <= 120
&& it.value.distance == -1
}.size > anglesDistances.size / 2) {
log("Found to many -1 in angle distances, passing")
//todo Теоретически такая ситуация может быть валидной, если сразу после внутреннего угла идёт внешний
return null return null
} }
@@ -182,20 +198,20 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
// Big fail too // Big fail too
if (dist110.distance == -1) { if (dist110.distance == -1) {
log("No back measurement found, wtf") log("No back measurement found, wtf")
return moveForward() return moveForward(dist0.distance)
} }
// Approaching inner corner and getting spurious reflection from 2 walls on 60 - just move forward to get closer to corner // Approaching inner corner and getting spurious reflection from 2 walls on 60 - just move forward to get closer to corner
if (dist70.distance - dist0.distance > SPURIOUS_REFLECTION_DIFF) { // if (dist70.distance - dist0.distance > SPURIOUS_REFLECTION_DIFF) {
log("Spurious reflection detected, moving forward") // log("Spurious reflection detected, moving forward")
return moveForward() // return moveForward()
} // }
//
// Approaching outer corner (parallel wall is ending soon, but not yet) - just move forward to get to the end of the wall // // Approaching outer corner (parallel wall is ending soon, but not yet) - just move forward to get to the end of the wall
if (dist70.distance == -1 || Math.abs(dist110.distance - dist70.distance) > ISOSCALENESS_MAX_DIFF) { // if (dist80.distance == -1 || Math.abs(dist100.distance - dist80.distance) > ISOSCALENESS_MAX_DIFF) {
log("Aprroaching outer corner, moving forward") // log("Aprroaching outer corner, moving forward")
return moveForward() // return moveForward()
} // }
for (i in 70..110 step 10) { for (i in 70..110 step 10) {
if (i == 90) { if (i == 90) {
@@ -203,7 +219,7 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
} }
val curDist = anglesDistances[Angle(i)]!!.distance val curDist = anglesDistances[Angle(i)]!!.distance
if (curDist > (average * 1.5)) { if (curDist > (average * 1.5) || curDist < (average / 2)) {
continue continue
} }
val point = Point( val point = Point(
@@ -228,7 +244,7 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
// default case: everything is ok, just move forward // default case: everything is ok, just move forward
log("Default case: moving forward") log("Default case: moving forward")
return moveForward() return moveForward(dist0.distance)
} }
private fun calculateAngle(anglesDistances: Map<Angle, AngleData>, state: CarState): Angle { private fun calculateAngle(anglesDistances: Map<Angle, AngleData>, state: CarState): Angle {
@@ -252,12 +268,12 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
carY -= (Math.sin(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt() carY -= (Math.sin(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt()
} }
LEFT -> { LEFT -> {
route.distances[idx] = (CHARGE_CORRECTION * route.distances[idx]).toInt() // route.distances[idx] = (CHARGE_CORRECTION * route.distances[idx]).toInt()
carAngle += route.distances[idx] // carAngle += route.distances[idx]
} }
RIGHT -> { RIGHT -> {
route.distances[idx] = (CHARGE_CORRECTION * route.distances[idx]).toInt() // route.distances[idx] = (CHARGE_CORRECTION * route.distances[idx]).toInt()
carAngle -= route.distances[idx] // carAngle -= route.distances[idx]
} }
} }
} }
@@ -85,6 +85,13 @@ class ClientHandler : SimpleChannelInboundHandler<Any>() {
private fun handlerSonarResponse(message: SonarResponse, angles: IntArray) { private fun handlerSonarResponse(message: SonarResponse, angles: IntArray) {
println("request angles: ${Arrays.toString(angles)}") println("request angles: ${Arrays.toString(angles)}")
println("distances from sonar: ${Arrays.toString(message.distances)}") println("distances from sonar: ${Arrays.toString(message.distances)}")
val algThread = DebugClInterface.algorithmThread
if (algThread == null) {
return
}
if (!algThread.isAlive) {
return
}
try { try {
DebugClInterface.exchanger.exchange(message.distances, 20, TimeUnit.SECONDS) DebugClInterface.exchanger.exchange(message.distances, 20, TimeUnit.SECONDS)
} catch (e: InterruptedException) { } catch (e: InterruptedException) {