-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
327 changed files
with
5,719 additions
and
2,429 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
30 changes: 30 additions & 0 deletions
30
api/src/main/kotlin/nebulosa/api/alignment/polar/PolarAlignmentController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package nebulosa.api.alignment.polar | ||
|
||
import nebulosa.api.alignment.polar.darv.DARVStart | ||
import nebulosa.api.beans.annotations.EntityBy | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
import org.springframework.web.bind.annotation.PutMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("polar-alignment") | ||
class PolarAlignmentController( | ||
private val polarAlignmentService: PolarAlignmentService, | ||
) { | ||
|
||
@PutMapping("darv/{camera}/{guideOutput}/start") | ||
fun darvStart( | ||
@EntityBy camera: Camera, @EntityBy guideOutput: GuideOutput, | ||
@RequestBody body: DARVStart, | ||
) { | ||
polarAlignmentService.darvStart(camera, guideOutput, body) | ||
} | ||
|
||
@PutMapping("darv/{camera}/{guideOutput}/stop") | ||
fun darvStop(@EntityBy camera: Camera, @EntityBy guideOutput: GuideOutput) { | ||
polarAlignmentService.darvStop(camera, guideOutput) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
api/src/main/kotlin/nebulosa/api/alignment/polar/PolarAlignmentService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package nebulosa.api.alignment.polar | ||
|
||
import nebulosa.api.alignment.polar.darv.DARVPolarAlignmentExecutor | ||
import nebulosa.api.alignment.polar.darv.DARVStart | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class PolarAlignmentService( | ||
private val darvPolarAlignmentExecutor: DARVPolarAlignmentExecutor, | ||
) { | ||
|
||
fun darvStart(camera: Camera, guideOutput: GuideOutput, darvStart: DARVStart) { | ||
check(camera.connected) { "camera not connected" } | ||
check(guideOutput.connected) { "guide output not connected" } | ||
darvPolarAlignmentExecutor.execute(darvStart.copy(camera = camera, guideOutput = guideOutput)) | ||
} | ||
|
||
fun darvStop(camera: Camera, guideOutput: GuideOutput) { | ||
darvPolarAlignmentExecutor.stop(camera, guideOutput) | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentEvent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
|
||
sealed interface DARVPolarAlignmentEvent { | ||
|
||
val camera: Camera | ||
|
||
val guideOutput: GuideOutput | ||
} |
172 changes: 172 additions & 0 deletions
172
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import io.reactivex.rxjava3.functions.Consumer | ||
import nebulosa.api.cameras.CameraCaptureEvent | ||
import nebulosa.api.cameras.CameraStartCaptureRequest | ||
import nebulosa.api.guiding.* | ||
import nebulosa.api.sequencer.* | ||
import nebulosa.api.sequencer.tasklets.delay.DelayElapsed | ||
import nebulosa.api.services.MessageService | ||
import nebulosa.common.concurrency.Incrementer | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
import nebulosa.log.loggerFor | ||
import org.springframework.batch.core.JobExecution | ||
import org.springframework.batch.core.JobExecutionListener | ||
import org.springframework.batch.core.JobParameters | ||
import org.springframework.batch.core.configuration.JobRegistry | ||
import org.springframework.batch.core.configuration.support.ReferenceJobFactory | ||
import org.springframework.batch.core.job.builder.JobBuilder | ||
import org.springframework.batch.core.launch.JobLauncher | ||
import org.springframework.batch.core.launch.JobOperator | ||
import org.springframework.batch.core.repository.JobRepository | ||
import org.springframework.core.task.SimpleAsyncTaskExecutor | ||
import org.springframework.stereotype.Component | ||
import java.nio.file.Path | ||
import java.util.* | ||
import kotlin.time.Duration.Companion.seconds | ||
|
||
/** | ||
* @see <a href="https://www.cloudynights.com/articles/cat/articles/darv-drift-alignment-by-robert-vice-r2760">Reference</a> | ||
*/ | ||
@Component | ||
class DARVPolarAlignmentExecutor( | ||
private val jobRepository: JobRepository, | ||
private val jobOperator: JobOperator, | ||
private val jobLauncher: JobLauncher, | ||
private val jobRegistry: JobRegistry, | ||
private val messageService: MessageService, | ||
private val jobIncrementer: Incrementer, | ||
private val capturesPath: Path, | ||
private val sequenceFlowFactory: SequenceFlowFactory, | ||
private val sequenceTaskletFactory: SequenceTaskletFactory, | ||
private val simpleAsyncTaskExecutor: SimpleAsyncTaskExecutor, | ||
) : SequenceJobExecutor<DARVStart, DARVSequenceJob>, Consumer<SequenceTaskletEvent>, JobExecutionListener { | ||
|
||
private val runningSequenceJobs = LinkedList<DARVSequenceJob>() | ||
|
||
@Synchronized | ||
override fun execute(request: DARVStart): DARVSequenceJob { | ||
val camera = requireNotNull(request.camera) | ||
val guideOutput = requireNotNull(request.guideOutput) | ||
|
||
if (isRunning(camera, guideOutput)) { | ||
throw IllegalStateException("DARV Polar Alignment job is already running") | ||
} | ||
|
||
LOG.info("starting DARV polar alignment. data={}", request) | ||
|
||
val cameraRequest = CameraStartCaptureRequest( | ||
camera = camera, | ||
exposureInMicroseconds = (request.exposureInSeconds + request.initialPauseInSeconds).seconds.inWholeMicroseconds, | ||
savePath = Path.of("$capturesPath", "${camera.name}-DARV.fits") | ||
) | ||
|
||
val cameraExposureTasklet = sequenceTaskletFactory.cameraExposure(cameraRequest) | ||
cameraExposureTasklet.subscribe(this) | ||
val cameraExposureFlow = sequenceFlowFactory.cameraExposure(cameraExposureTasklet) | ||
|
||
val guidePulseDuration = (request.exposureInSeconds / 2.0).seconds.inWholeMilliseconds | ||
val initialPauseDelayTasklet = sequenceTaskletFactory.delay(request.initialPauseInSeconds.seconds) | ||
initialPauseDelayTasklet.subscribe(this) | ||
|
||
val direction = if (request.reversed) request.direction.reversed else request.direction | ||
|
||
val forwardGuidePulseRequest = GuidePulseRequest(guideOutput, direction, guidePulseDuration) | ||
val forwardGuidePulseTasklet = sequenceTaskletFactory.guidePulse(forwardGuidePulseRequest) | ||
forwardGuidePulseTasklet.subscribe(this) | ||
|
||
val backwardGuidePulseRequest = GuidePulseRequest(guideOutput, direction.reversed, guidePulseDuration) | ||
val backwardGuidePulseTasklet = sequenceTaskletFactory.guidePulse(backwardGuidePulseRequest) | ||
backwardGuidePulseTasklet.subscribe(this) | ||
|
||
val guidePulseFlow = sequenceFlowFactory.guidePulse(initialPauseDelayTasklet, forwardGuidePulseTasklet, backwardGuidePulseTasklet) | ||
|
||
val darvJob = JobBuilder("DARVPolarAlignment.Job.${jobIncrementer.increment()}", jobRepository) | ||
.start(cameraExposureFlow) | ||
.split(simpleAsyncTaskExecutor) | ||
.add(guidePulseFlow) | ||
.end() | ||
.listener(this) | ||
.listener(cameraExposureTasklet) | ||
.build() | ||
|
||
return jobLauncher | ||
.run(darvJob, JobParameters()) | ||
.let { DARVSequenceJob(camera, guideOutput, request, darvJob, it) } | ||
.also(runningSequenceJobs::add) | ||
.also { jobRegistry.register(ReferenceJobFactory(darvJob)) } | ||
} | ||
|
||
@Synchronized | ||
fun stop(camera: Camera, guideOutput: GuideOutput) { | ||
val jobExecution = jobExecutionFor(camera, guideOutput) ?: return | ||
jobOperator.stop(jobExecution.id) | ||
} | ||
|
||
@Suppress("NOTHING_TO_INLINE") | ||
private inline fun jobExecutionFor(camera: Camera, guideOutput: GuideOutput): JobExecution? { | ||
return sequenceJobFor(camera, guideOutput)?.jobExecution | ||
} | ||
|
||
fun isRunning(camera: Camera, guideOutput: GuideOutput): Boolean { | ||
return sequenceJobFor(camera, guideOutput)?.jobExecution?.isRunning ?: false | ||
} | ||
|
||
override fun accept(event: SequenceTaskletEvent) { | ||
if (event !is SequenceJobEvent) { | ||
LOG.warn("unaccepted sequence task event: {}", event) | ||
return | ||
} | ||
|
||
val (camera, guideOutput, data) = sequenceJobWithId(event.jobExecution.jobId) ?: return | ||
|
||
val messageEvent = when (event) { | ||
// Initial pulse event. | ||
is DelayElapsed -> { | ||
DARVPolarAlignmentInitialPauseElapsed(camera, guideOutput, event) | ||
} | ||
// Forward & backward guide pulse event. | ||
is GuidePulseEvent -> { | ||
val direction = event.tasklet.request.direction | ||
val duration = event.tasklet.request.durationInMilliseconds | ||
val forward = (direction == data.direction) != data.reversed | ||
|
||
when (event) { | ||
is GuidePulseStarted -> { | ||
DARVPolarAlignmentGuidePulseElapsed(camera, guideOutput, forward, direction, duration, 0.0) | ||
} | ||
is GuidePulseElapsed -> { | ||
DARVPolarAlignmentGuidePulseElapsed(camera, guideOutput, forward, direction, event.remainingTime, event.progress) | ||
} | ||
is GuidePulseFinished -> { | ||
DARVPolarAlignmentGuidePulseElapsed(camera, guideOutput, forward, direction, 0L, 1.0) | ||
} | ||
} | ||
} | ||
is CameraCaptureEvent -> event | ||
else -> return | ||
} | ||
|
||
messageService.sendMessage(messageEvent) | ||
} | ||
|
||
override fun beforeJob(jobExecution: JobExecution) { | ||
val (camera, guideOutput) = sequenceJobWithId(jobExecution.jobId) ?: return | ||
messageService.sendMessage(DARVPolarAlignmentStarted(camera, guideOutput)) | ||
} | ||
|
||
override fun afterJob(jobExecution: JobExecution) { | ||
val (camera, guideOutput) = sequenceJobWithId(jobExecution.jobId) ?: return | ||
messageService.sendMessage(DARVPolarAlignmentFinished(camera, guideOutput)) | ||
} | ||
|
||
override fun iterator(): Iterator<DARVSequenceJob> { | ||
return runningSequenceJobs.iterator() | ||
} | ||
|
||
companion object { | ||
|
||
@JvmStatic private val LOG = loggerFor<DARVPolarAlignmentExecutor>() | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentFinished.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import nebulosa.api.services.MessageEvent | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
|
||
data class DARVPolarAlignmentFinished( | ||
override val camera: Camera, | ||
override val guideOutput: GuideOutput, | ||
) : MessageEvent, DARVPolarAlignmentEvent { | ||
|
||
@JsonIgnore override val eventName = "DARV_POLAR_ALIGNMENT_FINISHED" | ||
} |
19 changes: 19 additions & 0 deletions
19
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentGuidePulseElapsed.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import nebulosa.api.services.MessageEvent | ||
import nebulosa.guiding.GuideDirection | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
|
||
data class DARVPolarAlignmentGuidePulseElapsed( | ||
override val camera: Camera, | ||
override val guideOutput: GuideOutput, | ||
val forward: Boolean, | ||
val direction: GuideDirection, | ||
val remainingTime: Long, | ||
val progress: Double, | ||
) : MessageEvent, DARVPolarAlignmentEvent { | ||
|
||
@JsonIgnore override val eventName = "DARV_POLAR_ALIGNMENT_GUIDE_PULSE_ELAPSED" | ||
} |
23 changes: 23 additions & 0 deletions
23
...rc/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentInitialPauseElapsed.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import nebulosa.api.sequencer.DelayEvent | ||
import nebulosa.api.services.MessageEvent | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
|
||
data class DARVPolarAlignmentInitialPauseElapsed( | ||
override val camera: Camera, | ||
override val guideOutput: GuideOutput, | ||
val pauseTime: Long, | ||
val remainingTime: Long, | ||
val progress: Double, | ||
) : MessageEvent, DARVPolarAlignmentEvent { | ||
|
||
constructor(camera: Camera, guideOutput: GuideOutput, delay: DelayEvent) : this( | ||
camera, guideOutput, delay.waitTime.inWholeMicroseconds, | ||
delay.remainingTime.inWholeMicroseconds, delay.progress | ||
) | ||
|
||
@JsonIgnore override val eventName = "DARV_POLAR_ALIGNMENT_INITIAL_PAUSE_ELAPSED" | ||
} |
14 changes: 14 additions & 0 deletions
14
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVPolarAlignmentStarted.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import nebulosa.api.services.MessageEvent | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
|
||
data class DARVPolarAlignmentStarted( | ||
override val camera: Camera, | ||
override val guideOutput: GuideOutput, | ||
) : MessageEvent, DARVPolarAlignmentEvent { | ||
|
||
@JsonIgnore override val eventName = "DARV_POLAR_ALIGNMENT_STARTED" | ||
} |
18 changes: 18 additions & 0 deletions
18
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVSequenceJob.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import nebulosa.api.sequencer.SequenceJob | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
import org.springframework.batch.core.Job | ||
import org.springframework.batch.core.JobExecution | ||
|
||
data class DARVSequenceJob( | ||
val camera: Camera, | ||
val guideOutput: GuideOutput, | ||
val data: DARVStart, | ||
override val job: Job, | ||
override val jobExecution: JobExecution, | ||
) : SequenceJob { | ||
|
||
override val devices = listOf(camera, guideOutput) | ||
} |
16 changes: 16 additions & 0 deletions
16
api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVStart.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package nebulosa.api.alignment.polar.darv | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore | ||
import nebulosa.guiding.GuideDirection | ||
import nebulosa.indi.device.camera.Camera | ||
import nebulosa.indi.device.guide.GuideOutput | ||
import org.hibernate.validator.constraints.Range | ||
|
||
data class DARVStart( | ||
@JsonIgnore val camera: Camera? = null, | ||
@JsonIgnore val guideOutput: GuideOutput? = null, | ||
@Range(min = 1, max = 600) val exposureInSeconds: Long = 0L, | ||
@Range(min = 1, max = 60) val initialPauseInSeconds: Long = 0L, | ||
val direction: GuideDirection = GuideDirection.NORTH, | ||
val reversed: Boolean = false, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.