car_srv: room scanning algorithm, small cleanup
This commit is contained in:
@@ -71,11 +71,13 @@ object Control {
|
||||
val angles = request.angles
|
||||
val size = angles.size
|
||||
val attempts = request.attempts
|
||||
|
||||
val distances = IntArray(size)
|
||||
|
||||
for (i in 0..(size - 1)) {
|
||||
|
||||
var i = 0
|
||||
while (i < size) {
|
||||
distances[i] = sonarMeasure(request.smoothing, attempts[i], angles[i], request.windowSize)
|
||||
i++
|
||||
}
|
||||
|
||||
val response = SonarResponse.BuilderSonarResponse(distances).build()
|
||||
@@ -84,13 +86,15 @@ object Control {
|
||||
|
||||
private fun sonarMeasure(smoothing: SonarRequest.Smoothing, attempts: Int, angle: Int, windowSize: Int): Int {
|
||||
val data = IntArray(attempts)
|
||||
|
||||
for (i in 0..(attempts - 1)) {
|
||||
var i = 0
|
||||
while (i < attempts) {
|
||||
data[i] = Sonar.getSmoothDistance(angle, windowSize)
|
||||
|
||||
if (smoothing.id == SonarRequest.Smoothing.NONE.id && data[i] != -1) {
|
||||
return data[i]
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
return when (smoothing.id) {
|
||||
|
||||
@@ -21,7 +21,7 @@ object Reader {
|
||||
|
||||
fun readSonar(): SonarRequest {
|
||||
val stream = getInputStream()
|
||||
return SonarRequest.BuilderSonarRequest(IntArray(0), IntArray(0), 0, SonarRequest.Smoothing.NONE, 0).parseFrom(stream).build()
|
||||
return SonarRequest.BuilderSonarRequest(IntArray(0), IntArray(0), 0, SonarRequest.Smoothing.NONE).parseFrom(stream).build()
|
||||
}
|
||||
|
||||
private fun getInputStream(): CodedInputStream {
|
||||
|
||||
@@ -17,11 +17,13 @@ repositories {
|
||||
}
|
||||
|
||||
apply plugin: "kotlin2js"
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
sourceSets {
|
||||
main.kotlin.srcDirs += 'src'
|
||||
main.kotlin.srcDirs += '../../proto/compiler/build/sources'
|
||||
main.kotlin.srcDirs += '../../proto/protofiles_sources/out'
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
task copyKotlinLib(type: Copy) {
|
||||
@@ -38,4 +40,5 @@ compileKotlin2Js.kotlinOptions.outputPrefix = "${projectDir}/kotlinJsRequiredFil
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-js-library:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import mcTransport
|
||||
|
||||
class ControllerToUsb : Controller {
|
||||
override fun executeRoute(route: RouteRequest, callback: (ByteArray) -> Unit) {
|
||||
println("Execute Route:")
|
||||
println("Execute route:")
|
||||
|
||||
mcTransport.setCallBack { bytes ->
|
||||
callback.invoke(bytes)
|
||||
@@ -18,7 +18,7 @@ class ControllerToUsb : Controller {
|
||||
}
|
||||
|
||||
override fun executeMetricRoute(request: RouteMetricRequest, callback: (ByteArray) -> Unit) {
|
||||
println("Execute Route:")
|
||||
println("Execute metric route:")
|
||||
|
||||
mcTransport.setCallBack { bytes ->
|
||||
callback.invoke(bytes)
|
||||
|
||||
@@ -120,8 +120,10 @@ operator fun IntArray.plus(elements: IntArray): IntArray {
|
||||
|
||||
fun IntArray.max(from: Int = 0): Int {
|
||||
var result = from
|
||||
for (i in (from + 1)..(size - 1)) {
|
||||
var i = from
|
||||
while (i < size - 1) {
|
||||
result = if (get(i) > get(result)) i else result
|
||||
i++
|
||||
}
|
||||
|
||||
return get(result)
|
||||
@@ -129,8 +131,10 @@ fun IntArray.max(from: Int = 0): Int {
|
||||
|
||||
fun IntArray.min(from: Int = 0): Int {
|
||||
var result = from
|
||||
for (i in 1..(size - 1)) {
|
||||
var i = from
|
||||
while (i < size - 1) {
|
||||
result = if (this.get(i) < this.get(result)) i else result
|
||||
i++
|
||||
}
|
||||
|
||||
return this.get(result)
|
||||
@@ -138,8 +142,10 @@ fun IntArray.min(from: Int = 0): Int {
|
||||
|
||||
fun IntArray.sum(): Int {
|
||||
var result = 0
|
||||
for (i in 0..(size - 1)) {
|
||||
var i = 0
|
||||
while (i < size - 1) {
|
||||
result += this.get(i)
|
||||
i++
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -147,8 +153,10 @@ fun IntArray.sum(): Int {
|
||||
|
||||
fun IntArray.sort(): IntArray {
|
||||
val result = this.clone()
|
||||
for (i in 0..(size - 1)) {
|
||||
var i = 0
|
||||
while (i < size - 1) {
|
||||
result[i] = this.max(i)
|
||||
i++
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -159,3 +167,29 @@ fun IntArray.mean(): Int =
|
||||
|
||||
fun IntArray.median(): Int =
|
||||
this.sort()[this.size / 2]
|
||||
|
||||
fun IntArray.filter(predicate: (Int) -> Boolean): IntArray {
|
||||
var resultSize = 0
|
||||
var i = 0
|
||||
while (i < size - 1) {
|
||||
if (predicate(get(i))) {
|
||||
resultSize++
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
val result = IntArray(resultSize)
|
||||
var j = 0
|
||||
i = 0
|
||||
while (i < size - 1) {
|
||||
if (predicate(get(i))) {
|
||||
result[j] = get(i)
|
||||
j++
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ syntax = "proto3";
|
||||
message SonarRequest {
|
||||
repeated int32 angles = 1;
|
||||
repeated int32 attempts = 2;
|
||||
int32 threshold = 3;
|
||||
int32 windowSize = 3;
|
||||
Smoothing smoothing = 4;
|
||||
int32 windowSize = 5;
|
||||
|
||||
enum Smoothing {
|
||||
NONE = 0;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Gradle: io.netty:netty-all:4.1.2.Final">
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.netty/netty-all/4.1.2.Final/e82c56c2b1269d4c5e9d504463f6b388c819c897/netty-all-4.1.2.Final.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/io.netty/netty-all/4.1.2.Final/e17e0092b321fbe3b786cda64f3d5cc3392774d8/netty-all-4.1.2.Final-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -51,6 +51,9 @@ jar {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile "io.netty:netty-all:4.1.2.Final"
|
||||
compile group: 'org.asynchttpclient', name: 'async-http-client', version: '2.0.0-RC9'
|
||||
|
||||
compile files ("../proto/compiler/build/protokot-runtime.jar")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import car.client.Client
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.handler.codec.http.*
|
||||
import objects.Car
|
||||
import objects.Environment
|
||||
import java.util.concurrent.Exchanger
|
||||
|
||||
object DebugClInterface {
|
||||
@@ -14,7 +15,6 @@ object DebugClInterface {
|
||||
|
||||
private val routeRegex = Regex("route [0-9]{1,10}")
|
||||
private val sonarRegex = Regex("sonar [0-9]{1,10}")
|
||||
private val environment = objects.Environment.instance
|
||||
private val helpString = "available commands:\n" +
|
||||
"cars - get list of connected cars\n" +
|
||||
"route [car_id] - setting a route for car with car id.\n" +
|
||||
@@ -50,8 +50,8 @@ object DebugClInterface {
|
||||
val commandType = readString.split(" ")[0].toLowerCase()
|
||||
when (commandType) {
|
||||
"cars" -> {
|
||||
synchronized(environment, {
|
||||
println(environment.map.values)
|
||||
synchronized(Environment, {
|
||||
println(Environment.map.values)
|
||||
})
|
||||
}
|
||||
"route" -> executeRouteCommand(readString)
|
||||
@@ -81,7 +81,7 @@ object DebugClInterface {
|
||||
} else 1
|
||||
|
||||
if (algorithmImpl == null) {
|
||||
algorithmImpl = RoomBypassingAlgorithm(environment.map.values.last(), exchanger)
|
||||
algorithmImpl = RoomBypassingAlgorithm(Environment.map.values.last(), exchanger)
|
||||
}
|
||||
while (count > 0) {
|
||||
count--
|
||||
@@ -106,8 +106,8 @@ object DebugClInterface {
|
||||
return
|
||||
}
|
||||
val car: Car? =
|
||||
synchronized(environment, {
|
||||
environment.map[id]
|
||||
synchronized(Environment, {
|
||||
Environment.map[id]
|
||||
})
|
||||
if (car == null) {
|
||||
println("car with id=$id not found")
|
||||
@@ -154,10 +154,9 @@ object DebugClInterface {
|
||||
println(helpString)
|
||||
return
|
||||
}
|
||||
val car: Car? =
|
||||
synchronized(environment, {
|
||||
environment.map[id]
|
||||
})
|
||||
val car: Car? = synchronized(Environment, {
|
||||
Environment.map[id]
|
||||
})
|
||||
if (car == null) {
|
||||
println("car with id=$id not found")
|
||||
return
|
||||
@@ -169,8 +168,8 @@ object DebugClInterface {
|
||||
try {
|
||||
Client.sendRequest(request, car.host, car.port, mapOf(Pair("angles", requestMessage.angles)))
|
||||
} catch (e: InactiveCarException) {
|
||||
synchronized(environment, {
|
||||
environment.map.remove(id)
|
||||
synchronized(Environment, {
|
||||
Environment.map.remove(id)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -183,7 +182,7 @@ object DebugClInterface {
|
||||
when (command) {
|
||||
"reset" -> return null
|
||||
"done" -> {
|
||||
val sonarBuilder = SonarRequest.BuilderSonarRequest(angles.toIntArray(), IntArray(angles.size, {1}), 0, SonarRequest.Smoothing.NONE)
|
||||
val sonarBuilder = SonarRequest.BuilderSonarRequest(angles.toIntArray(), IntArray(angles.size, { 1 }), 0, SonarRequest.Smoothing.NONE)
|
||||
return sonarBuilder.build()
|
||||
}
|
||||
else -> {
|
||||
@@ -207,7 +206,7 @@ object DebugClInterface {
|
||||
}
|
||||
|
||||
private fun executeRefreshLocationCommand() {
|
||||
val cars = synchronized(environment, { environment.map.values })
|
||||
val cars = synchronized(Environment, { Environment.map.values })
|
||||
val inactiveCars = mutableListOf<Int>()
|
||||
for (car in cars) {
|
||||
val request = getDefaultHttpRequest(car.host, getLocationUrl, ByteArray(0))
|
||||
@@ -218,9 +217,9 @@ object DebugClInterface {
|
||||
}
|
||||
println("ref loc done")
|
||||
}
|
||||
synchronized(environment, {
|
||||
synchronized(Environment, {
|
||||
for (id in inactiveCars) {
|
||||
environment.map.remove(id)
|
||||
Environment.map.remove(id)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -241,8 +240,8 @@ object DebugClInterface {
|
||||
return
|
||||
}
|
||||
val car: Car? =
|
||||
synchronized(environment, {
|
||||
environment.map[id]
|
||||
synchronized(Environment, {
|
||||
Environment.map[id]
|
||||
})
|
||||
if (car == null) {
|
||||
println("car with id=$id not found")
|
||||
@@ -255,8 +254,8 @@ object DebugClInterface {
|
||||
try {
|
||||
Client.sendRequest(request, car.host, car.port, mapOf(Pair("uid", id)))
|
||||
} catch (e: InactiveCarException) {
|
||||
synchronized(environment, {
|
||||
environment.map.remove(id)
|
||||
synchronized(Environment, {
|
||||
Environment.map.remove(id)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -295,7 +294,6 @@ object DebugClInterface {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getDefaultHttpRequest(host: String, url: String, bytes: ByteArray): DefaultFullHttpRequest {
|
||||
val request = DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, url, Unpooled.copiedBuffer(bytes))
|
||||
request.headers().set(HttpHeaderNames.HOST, host)
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package RoomScanner
|
||||
|
||||
import CodedInputStream
|
||||
import CodedOutputStream
|
||||
import RouteMetricRequest
|
||||
import SonarRequest
|
||||
import SonarResponse
|
||||
import car.client.CarClient
|
||||
import objects.Car
|
||||
|
||||
class CarController(var car: Car) {
|
||||
@@ -30,21 +36,38 @@ class CarController(var car: Car) {
|
||||
val direction = if (rotateAngle > 0) Direction.RIGHT else Direction.LEFT
|
||||
drive(direction, rotateAngle.toInt())
|
||||
|
||||
angle = rotateAngle
|
||||
angle = target
|
||||
}
|
||||
|
||||
private fun drive(direction: Direction, distance: Int) {
|
||||
when (direction) {
|
||||
Direction.BACKWARD -> {}
|
||||
Direction.FORWARD -> {}
|
||||
Direction.LEFT -> {}
|
||||
Direction.RIGHT -> {}
|
||||
val request = RouteMetricRequest.BuilderRouteMetricRequest(intArrayOf(distance), intArrayOf(direction.id)).build()
|
||||
val data = serialize(request.getSizeNoTag(), { i -> request.writeTo(i) })
|
||||
CarClient.sendRequest(car, CarClient.Request.ROUTE_METRIC, data).get()
|
||||
}
|
||||
|
||||
fun scan(angles: IntArray): List<Pair<Double, Double>> {
|
||||
val request = SonarRequest.BuilderSonarRequest(angles, IntArray(angles.size, { 5 }), 0, SonarRequest.Smoothing.MEDIAN).build()
|
||||
val data = serialize(request.getSizeNoTag(), { i -> request.writeTo(i) })
|
||||
val response = CarClient.sendRequest(car, CarClient.Request.SONAR, data).get().responseBodyAsBytes
|
||||
|
||||
val distances = SonarResponse.BuilderSonarResponse(IntArray(0)).parseFrom(CodedInputStream(response)).build().distances
|
||||
|
||||
return distances.mapIndexed { i: Int, distance: Int -> convertToPoint(angles[i].toDouble(), distance.toDouble()) }
|
||||
}
|
||||
|
||||
fun convertToPoint(angle: Double, distance: Double): Pair<Double, Double> {
|
||||
if (distance <= 0) {
|
||||
return Pair(0.0, 0.0)
|
||||
}
|
||||
|
||||
val realAngle = Math.toRadians(angle + this.angle)
|
||||
return Pair(Math.cos(realAngle) * distance + position.first, Math.sin(realAngle) * distance + position.second)
|
||||
}
|
||||
|
||||
fun scan(angles: IntArray): MutableList<Pair<Double, Double>> {
|
||||
throw UnsupportedOperationException()
|
||||
inline fun serialize(size: Int, writeTo: (CodedOutputStream) -> Unit): ByteArray {
|
||||
val bytes = ByteArray(size)
|
||||
writeTo(CodedOutputStream(bytes))
|
||||
|
||||
return bytes
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package RoomScanner
|
||||
|
||||
class RoomScanner(val controller: CarController) {
|
||||
class RoomScanner(val controller: CarController): Thread() {
|
||||
private val points = mutableListOf<Pair<Double, Double>>()
|
||||
|
||||
fun run() {
|
||||
override fun run() {
|
||||
while (true) {
|
||||
scan()
|
||||
println("[${points.joinToString { "[${it.first}, ${it.second}]" }}}]")
|
||||
@@ -12,16 +12,16 @@ class RoomScanner(val controller: CarController) {
|
||||
|
||||
fun scan() {
|
||||
val horizon = IntArray(180 / 5, { it * 5 })
|
||||
val iterationPoints = mutableListOf<Pair<Double, Double>>()
|
||||
|
||||
controller.rotateOn(0.0)
|
||||
val iterationPoints = controller.scan(horizon)
|
||||
|
||||
iterationPoints.addAll(controller.scan(horizon))
|
||||
controller.rotateOn(180.0)
|
||||
iterationPoints.addAll(controller.scan(horizon))
|
||||
|
||||
points.addAll(iterationPoints)
|
||||
|
||||
val target = iterationPoints.maxBy { distance(controller.position, it) }
|
||||
val target = iterationPoints.filter { it.first > 0 && it.second > 0 }.maxBy { distance(controller.position, it) }
|
||||
target ?: return
|
||||
|
||||
controller.moveTo(target)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import RoomScanner.CarController
|
||||
import RoomScanner.RoomScanner
|
||||
import car.Dropper
|
||||
import car.client.Client
|
||||
import objects.Environment
|
||||
|
||||
val carServerPort: Int = 7925
|
||||
val webServerPort: Int = 7926
|
||||
@@ -11,7 +14,7 @@ val debugMemoryUrl = "/debug/memory"
|
||||
val sonarUrl = "/sonar"
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
var roomScanner: RoomScanner? = null
|
||||
val carServer = car.server.Server.getCarServerThread(carServerPort)
|
||||
val webServer = web.server.Server.getWebServerThread(webServerPort)
|
||||
val carsDestroy = Dropper.getCarsDestroyThread()
|
||||
@@ -19,6 +22,13 @@ fun main(args: Array<String>) {
|
||||
carsDestroy.start()
|
||||
webServer.start()
|
||||
|
||||
if (args.contains("--scan")) {
|
||||
Environment.onCarConnect { car ->
|
||||
roomScanner = RoomScanner(CarController(car))
|
||||
roomScanner!!.start()
|
||||
}
|
||||
}
|
||||
|
||||
//CL user interface
|
||||
DebugClInterface.run()
|
||||
|
||||
@@ -26,4 +36,6 @@ fun main(args: Array<String>) {
|
||||
carServer.interrupt()
|
||||
webServer.interrupt()
|
||||
Client.shutDownClient()
|
||||
|
||||
roomScanner?.interrupt()
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import io.netty.buffer.Unpooled
|
||||
import io.netty.handler.codec.http.*
|
||||
import objects.Car
|
||||
import setRouteMetricUrl
|
||||
import setRouteUrl
|
||||
import sonarUrl
|
||||
import java.util.*
|
||||
import java.util.concurrent.Exchanger
|
||||
@@ -44,7 +43,7 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
|
||||
val message = SonarRequest.BuilderSonarRequest(
|
||||
angles = angles,
|
||||
attempts = IntArray(angles.size, { attempts }),
|
||||
threshold = threshold,
|
||||
windowSize = 0,
|
||||
smoothing = smoothing)
|
||||
.build()
|
||||
val requestBytes = ByteArray(message.getSizeNoTag())
|
||||
@@ -107,10 +106,7 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
|
||||
|
||||
this.requiredAngles = defaultAngles
|
||||
|
||||
val state = getCarState(anglesDistances)
|
||||
if (state == null) {
|
||||
return
|
||||
}
|
||||
val state = getCarState(anglesDistances) ?: return
|
||||
val command = getCommand(anglesDistances, state)
|
||||
afterGetCommand(command)
|
||||
println(Arrays.toString(command.directions))
|
||||
@@ -123,14 +119,6 @@ abstract class AbstractAlgorithm(val thisCar: Car, val exchanger: Exchanger<IntA
|
||||
}
|
||||
|
||||
|
||||
protected fun getPrevState(): CarState? {
|
||||
return prevState
|
||||
}
|
||||
|
||||
protected fun getPrevSonarDistances(): Map<Int, AngleData> {
|
||||
return prevSonarDistances
|
||||
}
|
||||
|
||||
private fun getAngles(): IntArray {
|
||||
return requiredAngles
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ object RoomModel {
|
||||
fun getUpdate(): Waypoints {
|
||||
|
||||
val algorithm = DebugClInterface.algorithmImpl
|
||||
if (algorithm == null || !(algorithm is RoomBypassingAlgorithm)) {
|
||||
if (algorithm == null || algorithm !is RoomBypassingAlgorithm) {
|
||||
val emptyArr = IntArray(0)
|
||||
return Waypoints.BuilderWaypoints(emptyArr, emptyArr, emptyArr, emptyArr, false).build()
|
||||
|
||||
|
||||
@@ -20,16 +20,15 @@ object Dropper {
|
||||
return {
|
||||
var stopped = false
|
||||
while (!stopped) {
|
||||
val environment = Environment.instance
|
||||
synchronized(environment, {
|
||||
synchronized(Environment, {
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val keysToRemove = mutableListOf<Int>()
|
||||
for ((key, value) in environment.map) {
|
||||
for ((key, value) in Environment.map) {
|
||||
if ((value.lastAction + timeDeltaToDrop) < currentTime) {
|
||||
keysToRemove.add(key)
|
||||
}
|
||||
}
|
||||
dropInactiveCar(keysToRemove, environment)
|
||||
dropInactiveCar(keysToRemove, Environment)
|
||||
})
|
||||
try {
|
||||
Thread.sleep(60000)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package car.client
|
||||
|
||||
import objects.Car
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
|
||||
object CarClient {
|
||||
enum class Request(val url: String) {
|
||||
CONNECT("connect"),
|
||||
GET_LOCATION("getLocation"),
|
||||
ROUTE("route"),
|
||||
ROUTE_METRIC("routeMetric"),
|
||||
SONAR("sonar"),
|
||||
DEBUG_MEMORY("debug/memory");
|
||||
}
|
||||
|
||||
fun sendRequest(car: Car, request: Request, data: ByteArray): ListenableFuture<Response>
|
||||
= Client.makeRequest("http://${car.host}:${car.port}/${request.url}", data)
|
||||
}
|
||||
@@ -6,21 +6,16 @@ import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioSocketChannel
|
||||
import io.netty.handler.codec.http.HttpRequest
|
||||
import io.netty.util.AttributeKey
|
||||
import org.asynchttpclient.DefaultAsyncHttpClient
|
||||
import org.asynchttpclient.ListenableFuture
|
||||
import org.asynchttpclient.Response
|
||||
import java.net.ConnectException
|
||||
import java.rmi.UnexpectedException
|
||||
|
||||
object Client {
|
||||
|
||||
val group: NioEventLoopGroup = NioEventLoopGroup()
|
||||
val bootstrap: Bootstrap = makeBootstrap()
|
||||
|
||||
private fun makeBootstrap(): Bootstrap {
|
||||
val b = Bootstrap()
|
||||
b.group(group).channel(NioSocketChannel().javaClass).handler(ClientInitializer())
|
||||
.attr(AttributeKey.newInstance<String>("url"), "")
|
||||
.attr(AttributeKey.newInstance<Int>("uid"), 0)
|
||||
.attr(AttributeKey.newInstance<IntArray>("angles"), IntArray(0))
|
||||
return b
|
||||
}
|
||||
val group = NioEventLoopGroup()
|
||||
val bootstrap = makeBootstrap()
|
||||
val client = DefaultAsyncHttpClient()
|
||||
|
||||
fun shutDownClient() {
|
||||
group.shutdownGracefully()
|
||||
@@ -41,4 +36,16 @@ object Client {
|
||||
throw InactiveCarException()
|
||||
}
|
||||
}
|
||||
|
||||
fun makeRequest(request: String, data: ByteArray): ListenableFuture<Response> =
|
||||
client.preparePost(request).setBody(data).execute() ?: throw UnexpectedException(request)
|
||||
|
||||
private fun makeBootstrap(): Bootstrap {
|
||||
val b = Bootstrap()
|
||||
b.group(group).channel(NioSocketChannel().javaClass).handler(ClientInitializer())
|
||||
.attr(AttributeKey.newInstance<String>("url"), "")
|
||||
.attr(AttributeKey.newInstance<Int>("uid"), 0)
|
||||
.attr(AttributeKey.newInstance<IntArray>("angles"), IntArray(0))
|
||||
return b
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,7 @@ import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
class ClientHandler : SimpleChannelInboundHandler<Any> {
|
||||
|
||||
constructor()
|
||||
class ClientHandler : SimpleChannelInboundHandler<Any>() {
|
||||
|
||||
var contentBytes: ByteArray = ByteArray(0)
|
||||
|
||||
@@ -64,11 +62,10 @@ class ClientHandler : SimpleChannelInboundHandler<Any> {
|
||||
}
|
||||
|
||||
private fun handlerGetLocationResponse(message: LocationResponse, carUid: Int) {
|
||||
val environment = Environment.instance
|
||||
if (message.code == 0) {
|
||||
val data = message.locationResponseData
|
||||
synchronized(environment, {
|
||||
val car = environment.map[carUid]
|
||||
synchronized(Environment, {
|
||||
val car = Environment.map[carUid]
|
||||
if (car != null) {
|
||||
car.x = data.x
|
||||
car.y = data.y
|
||||
@@ -106,4 +103,4 @@ class ClientHandler : SimpleChannelInboundHandler<Any> {
|
||||
contentsBytes.readBytes(contentBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,10 @@ import io.netty.handler.codec.http.*
|
||||
import objects.Environment
|
||||
|
||||
class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
|
||||
var url: String = ""
|
||||
var contentBytes: ByteArray = ByteArray(0)
|
||||
|
||||
override fun channelReadComplete(ctx: ChannelHandlerContext) {
|
||||
|
||||
val environment = Environment.instance
|
||||
var success = true
|
||||
var answer = ByteArray(0)
|
||||
when (url) {
|
||||
@@ -27,7 +24,7 @@ class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
val data = ConnectionRequest.BuilderConnectionRequest(IntArray(0), 0).build()
|
||||
data.mergeFrom(CodedInputStream(contentBytes))
|
||||
val ipStr = data.ipValues.map { elem -> elem.toString() }.reduce { elem1, elem2 -> elem1 + "." + elem2 }
|
||||
val uid = environment.connectCar(ipStr, data.port)
|
||||
val uid = Environment.connectCar(ipStr, data.port)
|
||||
val responseObject = ConnectionResponse.BuilderConnectionResponse(uid, 0).build()
|
||||
answer = ByteArray(responseObject.getSizeNoTag())
|
||||
responseObject.writeTo(CodedOutputStream(answer))
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
package objects
|
||||
|
||||
class Environment private constructor() {
|
||||
|
||||
val map: MutableMap<Int, Car>
|
||||
object Environment {
|
||||
private var uid = 0
|
||||
|
||||
companion object {
|
||||
val instance = Environment()
|
||||
}
|
||||
|
||||
init {
|
||||
map = mutableMapOf()
|
||||
}
|
||||
private val onConnect = mutableListOf<(Car) -> Unit>()
|
||||
val map = mutableMapOf<Int, Car>()
|
||||
|
||||
@Synchronized
|
||||
fun connectCar(host: String, port: Int): Int {
|
||||
uid++
|
||||
map.put(uid, Car(uid, host, port))
|
||||
val car = Car(uid, host, port)
|
||||
onConnect.forEach { it(car) }
|
||||
map.put(uid, car)
|
||||
return uid
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun onCarConnect(callback: (Car) -> Unit) {
|
||||
onConnect.add(callback)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package web.server
|
||||
|
||||
import CodedInputStream
|
||||
import CodedOutputStream
|
||||
import DirectionRequest
|
||||
import GenericResponse
|
||||
import ModeChange
|
||||
import Result
|
||||
import algorithm.RoomModel
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.SimpleChannelInboundHandler
|
||||
import io.netty.handler.codec.http.*
|
||||
import io.netty.util.CharsetUtil
|
||||
import GenericResponse
|
||||
import CodedOutputStream
|
||||
import CodedInputStream
|
||||
import algorithm.RoomModel
|
||||
import java.util.*
|
||||
|
||||
class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
@@ -41,9 +44,9 @@ class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8)
|
||||
)
|
||||
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes())
|
||||
response.headers().add("Access-Control-Allow-Origin", "*");
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length");
|
||||
response.headers().add("Access-Control-Allow-Origin", "*")
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length")
|
||||
ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE)
|
||||
}
|
||||
Constants.getWaypointsURL -> {
|
||||
@@ -61,9 +64,9 @@ class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8)
|
||||
)
|
||||
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes())
|
||||
response.headers().add("Access-Control-Allow-Origin", "*");
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length");
|
||||
response.headers().add("Access-Control-Allow-Origin", "*")
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length")
|
||||
ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE)
|
||||
}
|
||||
Constants.directionOrderURL -> {
|
||||
@@ -92,9 +95,9 @@ class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8)
|
||||
)
|
||||
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes())
|
||||
response.headers().add("Access-Control-Allow-Origin", "*");
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length");
|
||||
response.headers().add("Access-Control-Allow-Origin", "*")
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length")
|
||||
ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE)
|
||||
}
|
||||
Constants.getDebug -> {
|
||||
@@ -108,9 +111,9 @@ class Handler : SimpleChannelInboundHandler<Any>() {
|
||||
Unpooled.copiedBuffer(Base64.getEncoder().encodeToString(outs.buffer), CharsetUtil.UTF_8)
|
||||
)
|
||||
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes())
|
||||
response.headers().add("Access-Control-Allow-Origin", "*");
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length");
|
||||
response.headers().add("Access-Control-Allow-Origin", "*")
|
||||
response.headers().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
|
||||
response.headers().add("Access-Control-Allow-Headers", "X-Requested-With, Content-Direction, Content-Length")
|
||||
ctx.writeAndFlush(response).addListener(io.netty.channel.ChannelFutureListener.CLOSE)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user