Deleted old version of algorithm from RoomBypassingAlgorithm; Refactored new algo from RoomTest into RoomBypassingAlgorithm
This commit is contained in:
@@ -6,7 +6,6 @@ import io.netty.buffer.Unpooled
|
|||||||
import io.netty.handler.codec.http.*
|
import io.netty.handler.codec.http.*
|
||||||
import objects.Car
|
import objects.Car
|
||||||
import java.util.concurrent.Exchanger
|
import java.util.concurrent.Exchanger
|
||||||
import algorithm.RoomTest
|
|
||||||
|
|
||||||
object DebugClInterface {
|
object DebugClInterface {
|
||||||
|
|
||||||
@@ -63,9 +62,6 @@ object DebugClInterface {
|
|||||||
"pos" -> {
|
"pos" -> {
|
||||||
val tmp = algorithmImpl
|
val tmp = algorithmImpl
|
||||||
if (tmp is RoomBypassingAlgorithm) {
|
if (tmp is RoomBypassingAlgorithm) {
|
||||||
println("length: ${tmp.wallLength} angleOX: ${tmp.wallAngleWithOX}")
|
|
||||||
println("x: ${tmp.carX} y: ${tmp.carY} angle:${tmp.carAngle}")
|
|
||||||
} else if (tmp is RoomTest) {
|
|
||||||
println("points: ${tmp.points}")
|
println("points: ${tmp.points}")
|
||||||
println("x: ${tmp.carX} y: ${tmp.carY} angle:${tmp.carAngle}")
|
println("x: ${tmp.carX} y: ${tmp.carY} angle:${tmp.carAngle}")
|
||||||
}
|
}
|
||||||
@@ -85,8 +81,7 @@ object DebugClInterface {
|
|||||||
} else 1
|
} else 1
|
||||||
|
|
||||||
if (algorithmImpl == null) {
|
if (algorithmImpl == null) {
|
||||||
algorithmImpl = RoomTest(environment.map.values.last(), exchanger)
|
algorithmImpl = RoomBypassingAlgorithm(environment.map.values.last(), exchanger)
|
||||||
// algorithmImpl = RoomBypassingAlgorithm(environment.map.values.last(), exchanger)
|
|
||||||
}
|
}
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
count--
|
count--
|
||||||
|
|||||||
@@ -1,37 +1,67 @@
|
|||||||
package algorithm
|
package algorithm
|
||||||
|
|
||||||
import objects.Car
|
import objects.Car
|
||||||
import RouteMetricRequest
|
|
||||||
import algorithm.geometry.*
|
|
||||||
import java.util.concurrent.Exchanger
|
import java.util.concurrent.Exchanger
|
||||||
|
import RouteMetricRequest
|
||||||
|
import algorithm.geometry.AngleData
|
||||||
|
import algorithm.geometry.Point
|
||||||
|
|
||||||
class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : AbstractAlgorithm(thisCar, exchanger) {
|
class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : AbstractAlgorithm(thisCar, exchanger) {
|
||||||
|
|
||||||
var wallAngleWithOX = 0.0//in radian
|
val points = arrayListOf<Point>()
|
||||||
var wallLength = 0.0//sm
|
private val DISTANCE_TO_WALL_THRESHOLD = 60
|
||||||
var errorCount = 0
|
|
||||||
|
|
||||||
var carX = 0
|
var carX = 0
|
||||||
var carY = 0
|
var carY = 0
|
||||||
var carAngle = 0
|
var carAngle = 0
|
||||||
|
|
||||||
private var prevPoint = Pair(0.0, 0.0)
|
override fun getCarState(anglesDistances: Map<Int, AngleData>): CarState {
|
||||||
|
return CarState.WALL
|
||||||
|
}
|
||||||
|
|
||||||
override fun getCarState(anglesDistances: Map<Int, AngleData>): CarState? {
|
override fun getCommand(anglesDistances: Map<Int, AngleData>, state: CarState): RouteMetricRequest {
|
||||||
val angleData0 = anglesDistances[0]
|
val dist0 = anglesDistances[0]
|
||||||
val angleData90 = anglesDistances[90]
|
val dist60 = anglesDistances[60]
|
||||||
if (angleData90 == null || angleData90.distance > 85) {
|
val dist90 = anglesDistances[90]
|
||||||
requiredAngles = getIntArray(0, 60, 90, 120, 180)
|
val dist120 = anglesDistances[120]
|
||||||
return CarState.OUTER
|
val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0))
|
||||||
|
if (dist90 == null) {
|
||||||
|
resultBuilder.setDirections(getIntArray(RIGHT))
|
||||||
|
resultBuilder.setDistances(getIntArray(10))
|
||||||
|
return resultBuilder.build()
|
||||||
}
|
}
|
||||||
val dist90 = angleData90.distance
|
val sonarAngle = carAngle - 90
|
||||||
if (dist90 < 20) {
|
points.add(Point(
|
||||||
return CarState.WALL
|
x = carX + dist90.distance * Math.cos(degreesToRadian(sonarAngle)),
|
||||||
|
y = carY + dist90.distance * Math.sin(degreesToRadian(sonarAngle))
|
||||||
|
))
|
||||||
|
if (dist120 == null || dist60 == null) {
|
||||||
|
resultBuilder.setDirections(getIntArray(FORWARD))
|
||||||
|
resultBuilder.setDistances(getIntArray(10))
|
||||||
|
return resultBuilder.build()
|
||||||
}
|
}
|
||||||
if (angleData0 == null || angleData0.distance > 70) {
|
if (dist0 != null && dist0.distance < DISTANCE_TO_WALL_THRESHOLD) {
|
||||||
return CarState.WALL
|
resultBuilder.setDirections(getIntArray(LEFT, FORWARD))
|
||||||
|
resultBuilder.setDistances(getIntArray(20, 10))
|
||||||
|
return resultBuilder.build()
|
||||||
}
|
}
|
||||||
return CarState.INNER
|
val abs = Math.abs(dist120.distance - dist60.distance)
|
||||||
|
if (abs > 10) {
|
||||||
|
val rotationDirection = if (dist120.distance > dist60.distance) LEFT else RIGHT
|
||||||
|
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD))
|
||||||
|
resultBuilder.setDistances(getIntArray(10, 7))//todo calibrate
|
||||||
|
return resultBuilder.build()
|
||||||
|
}
|
||||||
|
if (dist90.distance > 50 || dist90.distance < 25) {
|
||||||
|
val rotationDirection = if (dist90.distance > 50) RIGHT else LEFT
|
||||||
|
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD))
|
||||||
|
resultBuilder.setDistances(getIntArray(10, 10))
|
||||||
|
return resultBuilder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
resultBuilder.setDirections(getIntArray(FORWARD))
|
||||||
|
resultBuilder.setDistances(getIntArray(20))
|
||||||
|
return resultBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getIntArray(vararg args: Int): IntArray {
|
private fun getIntArray(vararg args: Int): IntArray {
|
||||||
@@ -59,165 +89,8 @@ class RoomBypassingAlgorithm(thisCar: Car, exchanger: Exchanger<IntArray>) : Abs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCommand(anglesDistances: Map<Int, AngleData>, state: CarState): RouteMetricRequest {
|
|
||||||
val angleData0 = anglesDistances[0]
|
|
||||||
val angleData60 = anglesDistances[60]
|
|
||||||
val angleData90 = anglesDistances[90]
|
|
||||||
val angleData120 = anglesDistances[120]
|
|
||||||
val angleData180 = anglesDistances[180]
|
|
||||||
val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0))
|
|
||||||
if (angleData120 == null || angleData90 == null || angleData60 == null) {
|
|
||||||
println("null distance!")
|
|
||||||
if (errorCount >= 3) {
|
|
||||||
errorCount = 0
|
|
||||||
resultBuilder.setDirections(getIntArray(BACKWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(15))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
errorCount++
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
if (getPrevState() == null) {
|
|
||||||
//its first run, save right wall
|
|
||||||
RoomModel.lines.add(Line(0.0, 1.0, angleData90.distance.toDouble()))
|
|
||||||
prevPoint = Pair(0.0, -angleData90.distance.toDouble())
|
|
||||||
if (angleData0 != null) {
|
|
||||||
wallLength = angleData0.distance.toDouble()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
when (state) {
|
|
||||||
CarState.WALL -> {
|
|
||||||
if (wallLength.toInt() == 0 && (angleData0 != null && angleData180 != null)) {
|
|
||||||
wallLength = angleData0.distance.toDouble() + angleData180.distance.toDouble()
|
|
||||||
}
|
|
||||||
if (angleData90.distance > 40 || angleData90.distance < 20) {
|
|
||||||
val rotationDirection = if (angleData90.distance > 40) RIGHT else LEFT
|
|
||||||
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(10, 35))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(angleData120.distance - angleData60.distance) > 10) {
|
|
||||||
val rotationDirection = if (angleData120.distance > angleData60.distance) LEFT else RIGHT
|
|
||||||
resultBuilder.setDirections(getIntArray(rotationDirection))
|
|
||||||
resultBuilder.setDistances(getIntArray(15))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
resultBuilder.setDirections(getIntArray(FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(35))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
CarState.INNER -> {
|
|
||||||
|
|
||||||
//в угле первое действие - встать максимально паралельно стене.
|
|
||||||
if (Math.abs(angleData120.distance - angleData60.distance) > 10) {
|
|
||||||
val rotationDirection = if (angleData120.distance > angleData60.distance) LEFT else RIGHT
|
|
||||||
resultBuilder.setDirections(getIntArray(rotationDirection))
|
|
||||||
resultBuilder.setDistances(getIntArray(12))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
//если стоим паралельно - можно мерить угол
|
|
||||||
val pointsNextLine = arrayListOf<Point>()
|
|
||||||
for (angleData in anglesDistances.values) {
|
|
||||||
if (angleData.angle <= 15) {
|
|
||||||
pointsNextLine.add(angleData.toPoint(Util.radianToDegrees(wallAngleWithOX)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pointsNextLine.size < 3) {
|
|
||||||
requiredAngles = IntArray(37, { it * 5 })
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
val nextLine = approximatePointsByLine(pointsNextLine.toTypedArray())
|
|
||||||
val currentLine = RoomModel.lines.last()
|
|
||||||
|
|
||||||
val xIntersection = prevPoint.first + wallLength * Math.cos(wallAngleWithOX)
|
|
||||||
val yIntersection = prevPoint.second + wallLength * Math.sin(wallAngleWithOX)
|
|
||||||
nextLine.C = -nextLine.A * xIntersection - nextLine.B * yIntersection
|
|
||||||
|
|
||||||
var xOnNextLine = xIntersection + 1
|
|
||||||
var yOnNextLine = (-nextLine.C - nextLine.A * xOnNextLine) / nextLine.B
|
|
||||||
|
|
||||||
//точка должна находится слева от нашей правой стены
|
|
||||||
if (currentLine.A * xOnNextLine + currentLine.B * yOnNextLine + currentLine.C < 0) {
|
|
||||||
xOnNextLine = xIntersection - 1
|
|
||||||
yOnNextLine = (-nextLine.C - nextLine.A * xOnNextLine) / nextLine.B
|
|
||||||
}
|
|
||||||
|
|
||||||
val vectorNextLine = Vector(xIntersection, yIntersection, xOnNextLine, yOnNextLine)
|
|
||||||
val vectorCurrentLine = Vector(xIntersection, yIntersection, prevPoint.first, prevPoint.second)
|
|
||||||
|
|
||||||
val scalarProduct = vectorCurrentLine.scalarProduct(vectorNextLine)
|
|
||||||
// val angle = Math.acos(scalarProduct / (vectorCurrentLine.length() * vectorNextLine.length()))
|
|
||||||
//todo
|
|
||||||
val angle = Math.PI / 2
|
|
||||||
val wallsAngleInDegrees = radiansToDegrees(angle)
|
|
||||||
wallAngleWithOX += degreesToRadian(180 - wallsAngleInDegrees.toInt())
|
|
||||||
prevPoint = Pair(xIntersection, yIntersection)
|
|
||||||
wallLength = 0.0
|
|
||||||
RoomModel.lines.add(nextLine)
|
|
||||||
resultBuilder.setDirections(getIntArray(LEFT, FORWARD, LEFT))
|
|
||||||
resultBuilder.setDistances(getIntArray((angle / 2).toInt(), 15, (angle / 2).toInt()))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
CarState.OUTER -> {
|
|
||||||
//todo calculate target
|
|
||||||
resultBuilder.setDirections(getIntArray(RIGHT, FORWARD, RIGHT))
|
|
||||||
resultBuilder.setDistances(getIntArray(45, 40, 45))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun degreesToRadian(angle: Int): Double {
|
private fun degreesToRadian(angle: Int): Double {
|
||||||
return Math.PI * angle / 180
|
return Math.PI * angle / 180
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun radiansToDegrees(angle: Double): Double {
|
|
||||||
return angle * 180 / Math.PI
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun approximatePointsByLine(points: Array<Point>): Line {
|
|
||||||
|
|
||||||
// val p1 = points.first()
|
|
||||||
// val p2 = points[1]
|
|
||||||
// return Line(p2.second - p1.second, p1.first - p2.first, -p1.first * p2.second + p1.second * p2.first)
|
|
||||||
|
|
||||||
val sumX = points.sumByDouble { it.x }
|
|
||||||
val sumXQuad = points.sumByDouble { it.x * it.x }
|
|
||||||
val sumY = points.sumByDouble { it.y }
|
|
||||||
val sumXY = points.sumByDouble { it.y * it.x }
|
|
||||||
|
|
||||||
val pointsCount = points.size
|
|
||||||
val den = pointsCount * sumXQuad - sumX * sumX
|
|
||||||
if (Math.abs(den) < 0.001) {
|
|
||||||
return Line(1.0, 0.0, -points.first().x)
|
|
||||||
}
|
|
||||||
val k = (pointsCount * sumXY - sumX * sumY) / (pointsCount * sumXQuad - sumX * sumX)
|
|
||||||
val b = (sumY - sumX * k) / pointsCount
|
|
||||||
|
|
||||||
return Line(-k, 1.0, -b)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun calculateAngleWithWall(anglesDistances: MutableMap<Int, Double>): Double {
|
|
||||||
val dist60 = anglesDistances[60]
|
|
||||||
val dist120 = anglesDistances[120]
|
|
||||||
|
|
||||||
//Math.cos(60) = 1/2
|
|
||||||
// val wallLength = Math.sqrt(Math.pow(dist60, 2.0) + Math.pow(dist120, 2.0) - dist120 * dist60)//in triangle
|
|
||||||
//
|
|
||||||
// val hOnWall = getRangeToWall(wallLength, dist60, dist120)
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
//return height in triangle on side a
|
|
||||||
private fun getRangeToWall(a: Double, b: Double, c: Double): Double {
|
|
||||||
val halfPerimeter = (a + b + c) / 2
|
|
||||||
return Math.sqrt(halfPerimeter * (halfPerimeter - a) * (halfPerimeter - b) * (halfPerimeter - c)) * 2 / a
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ object RoomModel {
|
|||||||
fun getUpdate(): Waypoints {
|
fun getUpdate(): Waypoints {
|
||||||
|
|
||||||
val algorithm = DebugClInterface.algorithmImpl
|
val algorithm = DebugClInterface.algorithmImpl
|
||||||
if (algorithm == null || !(algorithm is RoomTest)) {
|
if (algorithm == null || !(algorithm is RoomBypassingAlgorithm)) {
|
||||||
val emptyArr = IntArray(0)
|
val emptyArr = IntArray(0)
|
||||||
return Waypoints.BuilderWaypoints(emptyArr, emptyArr, emptyArr, emptyArr, false).build()
|
return Waypoints.BuilderWaypoints(emptyArr, emptyArr, emptyArr, emptyArr, false).build()
|
||||||
|
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
package algorithm
|
|
||||||
|
|
||||||
import objects.Car
|
|
||||||
import java.util.concurrent.Exchanger
|
|
||||||
import RouteMetricRequest
|
|
||||||
import algorithm.geometry.AngleData
|
|
||||||
import algorithm.geometry.Point
|
|
||||||
|
|
||||||
class RoomTest(thisCar: Car, exchanger: Exchanger<IntArray>) : AbstractAlgorithm(thisCar, exchanger) {
|
|
||||||
|
|
||||||
val points = arrayListOf<Point>()
|
|
||||||
private val DISTANCE_TO_WALL_THRESHOLD = 60
|
|
||||||
|
|
||||||
var carX = 0
|
|
||||||
var carY = 0
|
|
||||||
var carAngle = 0
|
|
||||||
|
|
||||||
override fun getCarState(anglesDistances: Map<Int, AngleData>): CarState {
|
|
||||||
return CarState.WALL
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCommand(anglesDistances: Map<Int, AngleData>, state: CarState): RouteMetricRequest {
|
|
||||||
val dist0 = anglesDistances[0]
|
|
||||||
val dist60 = anglesDistances[60]
|
|
||||||
val dist90 = anglesDistances[90]
|
|
||||||
val dist120 = anglesDistances[120]
|
|
||||||
val resultBuilder = RouteMetricRequest.BuilderRouteMetricRequest(IntArray(0), IntArray(0))
|
|
||||||
if (dist90 == null) {
|
|
||||||
resultBuilder.setDirections(getIntArray(RIGHT))
|
|
||||||
resultBuilder.setDistances(getIntArray(10))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
val sonarAngle = carAngle - 90
|
|
||||||
points.add(Point(
|
|
||||||
x = carX + dist90.distance * Math.cos(degreesToRadian(sonarAngle)),
|
|
||||||
y = carY + dist90.distance * Math.sin(degreesToRadian(sonarAngle))
|
|
||||||
))
|
|
||||||
if (dist120 == null || dist60 == null) {
|
|
||||||
resultBuilder.setDirections(getIntArray(FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(10))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
if (dist0 != null && dist0.distance < DISTANCE_TO_WALL_THRESHOLD) {
|
|
||||||
resultBuilder.setDirections(getIntArray(LEFT, FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(20, 10))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
val abs = Math.abs(dist120.distance - dist60.distance)
|
|
||||||
if (abs > 10) {
|
|
||||||
val rotationDirection = if (dist120.distance > dist60.distance) LEFT else RIGHT
|
|
||||||
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(10, 7))//todo calibrate
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
if (dist90.distance > 50 || dist90.distance < 25) {
|
|
||||||
val rotationDirection = if (dist90.distance > 50) RIGHT else LEFT
|
|
||||||
resultBuilder.setDirections(getIntArray(rotationDirection, FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(10, 10))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
resultBuilder.setDirections(getIntArray(FORWARD))
|
|
||||||
resultBuilder.setDistances(getIntArray(20))
|
|
||||||
return resultBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getIntArray(vararg args: Int): IntArray {
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun afterGetCommand(route: RouteMetricRequest) {
|
|
||||||
route.directions.forEachIndexed { idx, direction ->
|
|
||||||
when (direction) {
|
|
||||||
FORWARD -> {
|
|
||||||
carX += (Math.cos(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt()
|
|
||||||
carY += (Math.sin(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt()
|
|
||||||
}
|
|
||||||
BACKWARD -> {
|
|
||||||
carX -= (Math.cos(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt()
|
|
||||||
carY -= (Math.sin(degreesToRadian(carAngle.toInt())) * route.distances[idx]).toInt()
|
|
||||||
}
|
|
||||||
LEFT -> {
|
|
||||||
carAngle += route.distances[idx]
|
|
||||||
}
|
|
||||||
RIGHT -> {
|
|
||||||
carAngle -= route.distances[idx]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun degreesToRadian(angle: Int): Double {
|
|
||||||
return Math.PI * angle / 180
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user