add limit readers

This commit is contained in:
Alexander Nozik 2023-10-30 22:51:17 +03:00
parent 984e7f12ef
commit 811477a636
6 changed files with 61 additions and 13 deletions

View File

@ -73,6 +73,7 @@ public class VirtualDrive(
// compute new value based on velocity and acceleration from the previous step
positionState.value += velocity * dtSeconds + force / mass * dtSeconds.pow(2) / 2
propertyChanged(Drive.position, positionState.value)
// compute new velocity based on acceleration on the previous step
velocity += force / mass * dtSeconds

View File

@ -1,5 +1,7 @@
package space.kscience.controls.constructor
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import space.kscience.controls.api.Device
import space.kscience.controls.spec.DeviceBySpec
import space.kscience.controls.spec.DevicePropertySpec
@ -28,6 +30,13 @@ public class VirtualLimitSwitch(
context: Context,
public val lockedState: DeviceState<Boolean>,
) : DeviceBySpec<LimitSwitch>(LimitSwitch, context), LimitSwitch {
init {
lockedState.valueFlow.onEach {
propertyChanged(LimitSwitch.locked, it)
}.launchIn(this)
}
override val locked: Boolean get() = lockedState.value
}

View File

@ -62,6 +62,7 @@ public class PidRegulator(
lastPosition = drive.position
drive.force = pidParameters.kp * delta + pidParameters.ki * integral + pidParameters.kd * derivative
propertyChanged(Regulator.position, drive.position)
}
}
}

View File

@ -32,10 +32,10 @@ public class DoubleRangeState(
/**
* A state showing that the range is on its lower boundary
*/
public val atStartState: DeviceState<Boolean> = map(MetaConverter.boolean) { it == range.start }
public val atStartState: DeviceState<Boolean> = map(MetaConverter.boolean) { it <= range.start }
/**
* A state showing that the range is on its higher boundary
*/
public val atEndState: DeviceState<Boolean> = map(MetaConverter.boolean) { it == range.endInclusive }
public val atEndState: DeviceState<Boolean> = map(MetaConverter.boolean) { it >= range.endInclusive }
}

View File

@ -9,11 +9,10 @@ import space.kscience.controls.api.propertyMessageFlow
import space.kscience.controls.constructor.DeviceState
import space.kscience.controls.manager.clock
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.meta.ListValue
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.Null
import space.kscience.dataforge.meta.Value
import space.kscience.dataforge.meta.*
import space.kscience.plotly.Plot
import space.kscience.plotly.bar
import space.kscience.plotly.models.Bar
import space.kscience.plotly.models.Scatter
import space.kscience.plotly.models.TraceValues
import space.kscience.plotly.scatter
@ -33,7 +32,7 @@ public fun Plot.plotDeviceProperty(
propertyName: String,
extractValue: Meta.() -> Value = { value ?: Null },
pointsNumber: Int = 400,
coroutineScope: CoroutineScope = device,
coroutineScope: CoroutineScope = device.context,
configuration: Scatter.() -> Unit = {},
): Job = scatter(configuration).run {
val clock = device.context.clock
@ -43,7 +42,8 @@ public fun Plot.plotDeviceProperty(
}.launchIn(coroutineScope)
}
public fun Plot.plotDeviceState(
public fun Plot.plotNumberState(
context: Context,
state: DeviceState<out Number>,
pointsNumber: Int = 400,
@ -54,4 +54,17 @@ public fun Plot.plotDeviceState(
x.strings = (x.strings + clock.now().toString()).takeLast(pointsNumber)
y.numbers = (y.numbers + it).takeLast(pointsNumber)
}.launchIn(context)
}
public fun Plot.plotBooleanState(
context: Context,
state: DeviceState<Boolean>,
pointsNumber: Int = 400,
configuration: Bar.() -> Unit = {},
): Job = bar(configuration).run {
val clock = context.clock
state.valueFlow.onEach {
x.strings = (x.strings + clock.now().toString()).takeLast(pointsNumber)
y.values = (y.values + it.asValue()).takeLast(pointsNumber)
}.launchIn(context)
}

View File

@ -13,9 +13,10 @@ import space.kscience.controls.spec.doRecurring
import space.kscience.controls.spec.name
import space.kscience.controls.spec.write
import space.kscience.controls.vision.plotDeviceProperty
import space.kscience.controls.vision.plotDeviceState
import space.kscience.controls.vision.plotNumberState
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.ScatterMode
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.plotly.PlotlyPlugin
@ -40,7 +41,7 @@ public fun main() {
val deviceManager = context.request(DeviceManager)
val visionManager = context.request(VisionManager)
val state = DoubleRangeState(0.0, -100.0..100.0)
val state = DoubleRangeState(0.0, -5.0..5.0)
val pidParameters = PidParameters(
kp = 2.5,
@ -79,14 +80,37 @@ public fun main() {
) {
vision {
plotly {
plotDeviceState(context, state){
name = "value"
plotNumberState(context, state) {
name = "real position"
}
plotDeviceProperty(device["pid"], Regulator.target.name){
plotDeviceProperty(device["pid"], Regulator.position.name) {
name = "read position"
}
plotDeviceProperty(device["pid"], Regulator.target.name) {
name = "target"
}
}
}
vision {
plotly {
// plotBooleanState(context, state.atStartState) {
// name = "start"
// }
// plotBooleanState(context, state.atEndState) {
// name = "end"
// }
plotDeviceProperty(device["start"], LimitSwitch.locked.name) {
name = "start measured"
mode = ScatterMode.markers
}
plotDeviceProperty(device["end"], LimitSwitch.locked.name) {
name = "end measured"
mode = ScatterMode.markers
}
}
}
}
}.start(false)