Change VirtualCar state and add controller

This commit is contained in:
Atos1337 2021-10-20 16:50:18 +03:00
parent 5322bf743b
commit 7c4d0a5f36
2 changed files with 143 additions and 14 deletions

View File

@ -11,28 +11,33 @@ import kotlin.time.Duration
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
class VirtualCar : DeviceBySpec<VirtualCar>(VirtualCar) { class VirtualCar : DeviceBySpec<VirtualCar>(VirtualCar) {
private var speedState: Pair<Double, Double> = Pair(0.0, 0.0) private var _speedState: Pair<Double, Double> = Pair(0.0, 0.0)
private val speedState: Pair<Double, Double>
get() { get() {
val previous_speed = field updateSpeedLocationTime()
val current_acceleration = this.accelerationState return this._speedState
val now = Instant.now().toEpochMilli().toDouble()
val time_difference = now - this.timeState
this.timeState = now
field = Pair(
previous_speed.first + time_difference * current_acceleration.first,
previous_speed.second + time_difference * current_acceleration.second
)
return field
} }
private var accelerationState: Pair<Double, Double> = Pair(0.0, 0.0) private var accelerationState: Pair<Double, Double> = Pair(0.0, 0.0)
set(value) { set(value) {
this.speedState updateSpeedLocationTime()
field = value field = value
} }
private var timeState = Instant.now().toEpochMilli().toDouble() private var timeState = Instant.now().toEpochMilli().toDouble()
private fun updateSpeedLocationTime() {
val previousSpeed = this._speedState
val currentAcceleration = this.accelerationState
val now = Instant.now().toEpochMilli().toDouble()
val timeDifference = now - this.timeState
this.timeState = now
this._speedState = Pair(
previousSpeed.first + timeDifference * currentAcceleration.first * 1e-3,
previousSpeed.second + timeDifference * currentAcceleration.second * 1e-3
)
}
object DoublePairMetaConverter : MetaConverter<Pair<Double, Double>> { object DoublePairMetaConverter : MetaConverter<Pair<Double, Double>> {
override fun metaToObject(meta: Meta): Pair<Double, Double> = Pair( override fun metaToObject(meta: Meta): Pair<Double, Double> = Pair(
meta["x"].double ?: 0.0, meta["x"].double ?: 0.0,
@ -43,7 +48,6 @@ class VirtualCar : DeviceBySpec<VirtualCar>(VirtualCar) {
"x" put obj.first "x" put obj.first
"y" put obj.second "y" put obj.second
} }
} }
companion object : DeviceSpec<VirtualCar>(::VirtualCar) { companion object : DeviceSpec<VirtualCar>(::VirtualCar) {
@ -66,7 +70,7 @@ class VirtualCar : DeviceBySpec<VirtualCar>(VirtualCar) {
speed.read() speed.read()
acceleration.read() acceleration.read()
} }
doRecurring(Duration.milliseconds(50)){ doRecurring(Duration.seconds(1)){
carProperties.read() carProperties.read()
} }
} }

View File

@ -0,0 +1,125 @@
package ru.mipt.npm.controls.demo.virtual_car
import io.ktor.server.engine.ApplicationEngine
import javafx.beans.property.DoubleProperty
import javafx.scene.Parent
import javafx.scene.control.TextField
import javafx.scene.layout.Priority
import javafx.stage.Stage
import kotlinx.coroutines.launch
import org.eclipse.milo.opcua.sdk.server.OpcUaServer
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText
import ru.mipt.npm.controls.api.DeviceMessage
import ru.mipt.npm.controls.client.connectToMagix
import ru.mipt.npm.controls.controllers.DeviceManager
import ru.mipt.npm.controls.controllers.install
import ru.mipt.npm.controls.demo.virtual_car.VirtualCar.Companion.acceleration
import ru.mipt.npm.controls.opcua.server.OpcUaServer
import ru.mipt.npm.controls.opcua.server.endpoint
import ru.mipt.npm.controls.opcua.server.serveDevices
import ru.mipt.npm.magix.api.MagixEndpoint
import ru.mipt.npm.magix.rsocket.rSocketWithTcp
import ru.mipt.npm.magix.server.startMagixServer
import space.kscience.dataforge.context.*
import tornadofx.*
class VirtualCarController : Controller(), ContextAware {
var device: VirtualCar? = null
var magixServer: ApplicationEngine? = null
var opcUaServer: OpcUaServer = OpcUaServer {
setApplicationName(LocalizedText.english("ru.mipt.npm.controls.opcua"))
endpoint {
setBindPort(9999)
//use default endpoint
}
}
override val context = Context("demoDevice") {
plugin(DeviceManager)
}
private val deviceManager = context.fetch(DeviceManager)
fun init() {
context.launch {
device = deviceManager.install("virtual-car", VirtualCar)
//starting magix event loop
magixServer = startMagixServer(enableRawRSocket = true, enableZmq = true)
//Launch device client and connect it to the server
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost", DeviceMessage.serializer())
deviceManager.connectToMagix(deviceEndpoint)
opcUaServer.startup()
opcUaServer.serveDevices(deviceManager)
}
}
fun shutdown() {
logger.info { "Shutting down..." }
opcUaServer.shutdown()
logger.info { "OpcUa server stopped" }
magixServer?.stop(1000, 5000)
logger.info { "Magix server stopped" }
device?.close()
logger.info { "Device server stopped" }
context.close()
}
}
class VirtualCarControllerView : View(title = " Virtual car controller remote") {
private val controller: VirtualCarController by inject()
private var accelerationXProperty: DoubleProperty by singleAssign()
private var accelerationXTF: TextField by singleAssign()
private var accelerationYProperty: DoubleProperty by singleAssign()
private var accelerationYTF: TextField by singleAssign()
override val root: Parent = vbox {
hbox {
label("AccelerationX")
pane {
hgrow = Priority.ALWAYS
}
accelerationXProperty = doubleProperty()
accelerationXTF = textfield(accelerationXProperty)
}
hbox {
label("AccelerationY")
pane {
hgrow = Priority.ALWAYS
}
accelerationYProperty = doubleProperty()
accelerationYTF = textfield(accelerationYProperty)
}
button("Submit") {
useMaxWidth = true
action {
controller.device?.run {
launch {
acceleration.write(Pair(accelerationXProperty.get(), accelerationYProperty.get()))
}
}
}
}
}
}
class VirtualCarControllerApp : App(VirtualCarControllerView::class) {
private val controller: VirtualCarController by inject()
override fun start(stage: Stage) {
super.start(stage)
controller.init()
}
override fun stop() {
controller.shutdown()
super.stop()
}
}
fun main() {
launch<VirtualCarControllerApp>()
}