Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-Focus Support #363

Merged
merged 23 commits into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0e9b61f
[api]: Implement Quadratic Curve Fitting algorithm
tiagohm Mar 5, 2024
3cfa652
[api]: Reformat code
tiagohm Mar 5, 2024
fe59c90
[ci]: Group Apache dependency updates
tiagohm Mar 5, 2024
f321e0e
[api]: Implement TrendLine and Hyperbolic Curve Fitting algorithm
tiagohm Mar 9, 2024
3666fe4
Merge branch 'dev' into feature/auto-focus
tiagohm Apr 1, 2024
29502bc
Merge branch 'dev' into feature/auto-focus
tiagohm May 22, 2024
617bf57
[api]: Improve Curve Fitting algorithm
tiagohm May 22, 2024
31d1391
[api]: Fix build failure
tiagohm May 22, 2024
574ea0b
Merge branch 'dev' into feature/auto-focus
tiagohm May 25, 2024
b9dc8b3
[api]: Support Auto Focus
tiagohm May 25, 2024
67e0cf4
[api]: Support Auto Focus
tiagohm May 26, 2024
860b3ac
[api]: Support Auto Focus
tiagohm May 26, 2024
908a1d5
[api]: Don't create a new temp directory on each task execution
tiagohm May 26, 2024
a43e263
[desktop]: Support Auto Focus
tiagohm May 26, 2024
a2b5000
[api][desktop]: Device Chooser
tiagohm May 27, 2024
df472e9
[api][desktop]: Support Auto Focus
tiagohm May 28, 2024
dddc47b
[desktop]: Support Auto Focus
tiagohm May 29, 2024
9384a3c
[api][desktop]: Support Auto Focus
tiagohm May 30, 2024
32e5c0f
[api][desktop]: Support Auto Focus
tiagohm May 30, 2024
2e04410
[api][desktop]: Support Auto Focus
tiagohm May 31, 2024
64ac7ec
[desktop]: Minor changes
tiagohm Jun 1, 2024
de81b7a
[api][desktop]: Support Auto Focus
tiagohm Jun 1, 2024
b65ee66
Merge branch 'dev' into feature/auto-focus
tiagohm Jun 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ ij_kotlin_continuation_indent_size = 8
[*.py]
ij_python_wrap_long_lines = false
ij_python_method_parameters_wrap = off

[{*.yml, *.yaml}]
ij_yaml_indent_size = 2
18 changes: 9 additions & 9 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ updates:
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 16
open-pull-requests-limit: 64
target-branch: "dev"
commit-message:
prefix: "[api]"
Expand All @@ -21,21 +21,21 @@ updates:
netty:
patterns:
- "io.netty*"
retrofit:
patterns:
- "com.squareup.retrofit2*"
okhttp:
squareup:
patterns:
- "com.squareup.okhttp3*"
- "com.squareup*"
rx:
patterns:
- "io.reactivex.rxjava3*"
jackson:
- "io.reactivex*"
fasterxml:
patterns:
- "com.fasterxml.jackson*"
- "com.fasterxml*"
kotlin:
patterns:
- "org.jetbrains.kotlin*"
apache:
patterns:
- "org.apache*"

- package-ecosystem: "npm"
directory: "/desktop"
Expand Down
2 changes: 1 addition & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies {
implementation(project(":nebulosa-astrometrynet"))
implementation(project(":nebulosa-alpaca-indi"))
implementation(project(":nebulosa-common"))
implementation(project(":nebulosa-curve-fitting"))
implementation(project(":nebulosa-guiding-phd2"))
implementation(project(":nebulosa-hips2fits"))
implementation(project(":nebulosa-horizons"))
Expand All @@ -26,7 +27,6 @@ dependencies {
implementation(project(":nebulosa-sbd"))
implementation(project(":nebulosa-simbad"))
implementation(project(":nebulosa-stellarium-protocol"))
implementation(project(":nebulosa-watney"))
implementation(project(":nebulosa-wcs"))
implementation(project(":nebulosa-xisf"))
implementation(libs.rx)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package nebulosa.api.alignment.polar.darv

import nebulosa.api.cameras.CameraEventAware
import nebulosa.api.tasks.Job
import nebulosa.indi.device.camera.CameraEvent

data class DARVJob(override val task: DARVTask) : Job() {
data class DARVJob(override val task: DARVTask) : Job(), CameraEventAware {

override val name = "${task.camera.name} DARV Job"

fun handleCameraEvent(event: CameraEvent) {
override fun handleCameraEvent(event: CameraEvent) {
task.handleCameraEvent(event)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package nebulosa.api.alignment.polar.darv

import io.reactivex.rxjava3.functions.Consumer
import nebulosa.api.cameras.AutoSubFolderMode
import nebulosa.api.cameras.CameraCaptureEvent
import nebulosa.api.cameras.CameraCaptureState
import nebulosa.api.cameras.CameraCaptureTask
import nebulosa.api.cameras.*
import nebulosa.api.guiding.GuidePulseEvent
import nebulosa.api.guiding.GuidePulseRequest
import nebulosa.api.guiding.GuidePulseTask
Expand All @@ -30,11 +27,11 @@ data class DARVTask(
@JvmField val guideOutput: GuideOutput,
@JvmField val request: DARVStartRequest,
private val executor: Executor,
) : AbstractTask<MessageEvent>(), Consumer<Any> {
) : AbstractTask<MessageEvent>(), Consumer<Any>, CameraEventAware {

@JvmField val cameraRequest = request.capture.copy(
exposureTime = request.capture.exposureTime + request.capture.exposureDelay,
savePath = Files.createTempDirectory("darv"),
savePath = CAPTURE_SAVE_PATH,
exposureAmount = 1, exposureDelay = Duration.ZERO,
frameType = FrameType.LIGHT, autoSave = false, autoSubFolderMode = AutoSubFolderMode.OFF
)
Expand All @@ -60,7 +57,7 @@ data class DARVTask(
backwardGuidePulseTask.subscribe(this)
}

fun handleCameraEvent(event: CameraEvent) {
override fun handleCameraEvent(event: CameraEvent) {
cameraCaptureTask.handleCameraEvent(event)
}

Expand Down Expand Up @@ -126,5 +123,6 @@ data class DARVTask(
companion object {

@JvmStatic private val LOG = loggerFor<DARVTask>()
@JvmStatic private val CAPTURE_SAVE_PATH = Files.createTempDirectory("darv-")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import io.reactivex.rxjava3.functions.Consumer
import nebulosa.api.beans.annotations.Subscriber
import nebulosa.api.messages.MessageEvent
import nebulosa.api.messages.MessageService
import nebulosa.api.solver.PlateSolverService
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.camera.CameraEvent
import nebulosa.indi.device.mount.Mount
import okhttp3.OkHttpClient
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.springframework.stereotype.Component
Expand All @@ -17,7 +17,7 @@ import java.util.concurrent.ConcurrentHashMap
@Subscriber
class TPPAExecutor(
private val messageService: MessageService,
private val plateSolverService: PlateSolverService,
private val httpClient: OkHttpClient,
) : Consumer<MessageEvent> {

private val jobs = ConcurrentHashMap.newKeySet<TPPAJob>(1)
Expand All @@ -38,7 +38,7 @@ class TPPAExecutor(
check(jobs.none { it.task.camera === camera }) { "${camera.name} TPPA Job is already in progress" }
check(jobs.none { it.task.mount === mount }) { "${camera.name} TPPA Job is already in progress" }

val solver = plateSolverService.solverFor(request.plateSolver)
val solver = request.plateSolver.get(httpClient)
val task = TPPATask(camera, solver, request, mount)
task.subscribe(this)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package nebulosa.api.alignment.polar.tppa

import nebulosa.api.cameras.CameraEventAware
import nebulosa.api.tasks.Job
import nebulosa.indi.device.camera.CameraEvent

data class TPPAJob(override val task: TPPATask) : Job() {
data class TPPAJob(override val task: TPPATask) : Job(), CameraEventAware {

override val name = "${task.camera.name} TPPA Job"

fun handleCameraEvent(event: CameraEvent) {
override fun handleCameraEvent(event: CameraEvent) {
task.handleCameraEvent(event)
}
}
24 changes: 11 additions & 13 deletions api/src/main/kotlin/nebulosa/api/alignment/polar/tppa/TPPATask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package nebulosa.api.alignment.polar.tppa
import io.reactivex.rxjava3.functions.Consumer
import nebulosa.alignment.polar.point.three.ThreePointPolarAlignment
import nebulosa.alignment.polar.point.three.ThreePointPolarAlignmentResult
import nebulosa.api.cameras.AutoSubFolderMode
import nebulosa.api.cameras.CameraCaptureEvent
import nebulosa.api.cameras.CameraCaptureState
import nebulosa.api.cameras.CameraCaptureTask
import nebulosa.api.cameras.*
import nebulosa.api.messages.MessageEvent
import nebulosa.api.mounts.MountMoveRequest
import nebulosa.api.mounts.MountMoveTask
Expand Down Expand Up @@ -38,12 +35,12 @@ data class TPPATask(
@JvmField val mount: Mount? = null,
@JvmField val longitude: Angle = mount!!.longitude,
@JvmField val latitude: Angle = mount!!.latitude,
) : AbstractTask<MessageEvent>(), Consumer<Any>, PauseListener {
) : AbstractTask<MessageEvent>(), Consumer<Any>, PauseListener, CameraEventAware {

@JvmField val mountMoveRequest = MountMoveRequest(request.stepDirection, request.stepDuration, request.stepSpeed)

@JvmField val cameraRequest = request.capture.copy(
savePath = Files.createTempDirectory("tppa"),
savePath = CAPTURE_SAVE_PATH,
exposureAmount = 0, exposureDelay = Duration.ZERO,
exposureTime = maxOf(request.capture.exposureTime, MIN_EXPOSURE_TIME),
frameType = FrameType.LIGHT, autoSave = false, autoSubFolderMode = AutoSubFolderMode.OFF
Expand Down Expand Up @@ -73,7 +70,7 @@ data class TPPATask(
settleDelayTask.subscribe(this)
}

fun handleCameraEvent(event: CameraEvent) {
override fun handleCameraEvent(event: CameraEvent) {
if (camera === event.device) {
cameraCaptureTask.handleCameraEvent(event)
}
Expand Down Expand Up @@ -117,14 +114,14 @@ data class TPPATask(

cancellationToken.listenToPause(this)

while (!cancellationToken.isDone) {
while (!cancellationToken.isCancelled) {
if (cancellationToken.isPaused) {
pausing.set(false)
sendEvent(TPPAState.PAUSED)
cancellationToken.waitForPause()
}

if (cancellationToken.isDone) break
if (cancellationToken.isCancelled) break

mount?.tracking(true)

Expand All @@ -137,7 +134,7 @@ data class TPPATask(
mountMoveState[alignment.state.ordinal] = true
}

if (cancellationToken.isDone) break
if (cancellationToken.isCancelled) break

rightAscension = mount.rightAscension
declination = mount.declination
Expand All @@ -149,14 +146,14 @@ data class TPPATask(
}
}

if (cancellationToken.isDone) break
if (cancellationToken.isCancelled) break

sendEvent(TPPAState.EXPOSURING)

// CAPTURE.
cameraCaptureTask.execute(cancellationToken)

if (cancellationToken.isDone || savedImage == null) {
if (cancellationToken.isCancelled || savedImage == null) {
break
}

Expand All @@ -180,7 +177,7 @@ data class TPPATask(

LOG.info("TPPA alignment completed. result=$result")

if (cancellationToken.isDone) break
if (cancellationToken.isCancelled) break

when (result) {
is ThreePointPolarAlignmentResult.NeedMoreMeasurement -> {
Expand Down Expand Up @@ -313,6 +310,7 @@ data class TPPATask(

@JvmStatic private val MIN_EXPOSURE_TIME = Duration.ofSeconds(1L)
@JvmStatic private val SETTLE_TIME = Duration.ofSeconds(5)
@JvmStatic private val CAPTURE_SAVE_PATH = Files.createTempDirectory("tppa-")
@JvmStatic private val LOG = loggerFor<TPPATask>()

const val MAX_ATTEMPTS = 30
Expand Down
22 changes: 22 additions & 0 deletions api/src/main/kotlin/nebulosa/api/autofocus/AutoFocusController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package nebulosa.api.autofocus

import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.focuser.Focuser
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("auto-focus")
class AutoFocusController(private val autoFocusService: AutoFocusService) {

@PutMapping("{camera}/{focuser}/start")
fun start(
camera: Camera, focuser: Focuser,
@RequestBody body: AutoFocusRequest,
) = autoFocusService.start(camera, focuser, body)

@PutMapping("{camera}/stop")
fun stop(camera: Camera) = autoFocusService.stop(camera)

@GetMapping("{camera}/status")
fun status(camera: Camera) = autoFocusService.status(camera)
}
32 changes: 32 additions & 0 deletions api/src/main/kotlin/nebulosa/api/autofocus/AutoFocusEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package nebulosa.api.autofocus

import nebulosa.api.cameras.CameraCaptureEvent
import nebulosa.api.messages.MessageEvent
import nebulosa.curve.fitting.CurvePoint
import nebulosa.curve.fitting.HyperbolicFitting
import nebulosa.curve.fitting.QuadraticFitting
import nebulosa.curve.fitting.TrendLineFitting

data class AutoFocusEvent(
@JvmField val state: AutoFocusState = AutoFocusState.IDLE,
@JvmField val focusPoint: CurvePoint? = null,
@JvmField val determinedFocusPoint: CurvePoint? = null,
@JvmField val starCount: Int = 0,
@JvmField val starHFD: Double = 0.0,
@JvmField val chart: Chart? = null,
@JvmField val capture: CameraCaptureEvent? = null,
) : MessageEvent {

data class Chart(
@JvmField val predictedFocusPoint: CurvePoint? = null,
@JvmField val minX: Double = 0.0,
@JvmField val minY: Double = 0.0,
@JvmField val maxX: Double = 0.0,
@JvmField val maxY: Double = 0.0,
@JvmField val trendLine: TrendLineFitting.Curve? = null,
@JvmField val parabolic: QuadraticFitting.Curve? = null,
@JvmField val hyperbolic: HyperbolicFitting.Curve? = null,
)

override val eventName = "AUTO_FOCUS.ELAPSED"
}
Loading