show progress arc while waiting for first map and clean up atomic state#17
show progress arc while waiting for first map and clean up atomic state#17
Conversation
c2df93b to
71b5798
Compare
6a13444 to
de03d7f
Compare
71b5798 to
151372c
Compare
151372c to
6d5fc3d
Compare
cloudslam/cloudslam.go
Outdated
| // generateProgressRingPCD generates a point cloud of a progress arc indicating elapsed time. | ||
| // The arc grows clockwise from 0 to a full circle over progressRingDuration, giving the user | ||
| // visual feedback while waiting for the first cloudslam map to appear. | ||
| func generateProgressRingPCD(elapsed time.Duration) ([]byte, error) { |
There was a problem hiding this comment.
when running cloudslam there is always a period of waiting for the job to start, because we have to spin up a job and setup the machine.
now we display something that moves, and in the next pr we expand on that further
cloudslam/cloudslam.go
Outdated
|
|
||
| pc := pointcloud.NewBasicEmpty() | ||
| for i := 0; i < filledPoints; i++ { | ||
| angle := float64(i) / numPoints * 2 * math.Pi |
There was a problem hiding this comment.
kk going to update the code to store the pointcloud in state rather than recreate everytime
cloudslam/cloudslam.go
Outdated
| } | ||
|
|
||
| var buf bytes.Buffer | ||
| if err := pointcloud.ToPCD(pc, &buf, pointcloud.PCDAscii); err != nil { |
While a job is active but no map has been received yet, PointCloudMap returns a PCD point arc instead of the blank default. The arc grows from a small sliver to a full circle over 5 minutes, giving the user visual feedback that the session is running. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- merge activeJob + jobStartTime into activeJobState struct; nil pointer replaces empty-string sentinel, and startedAt replaces the separate jobStartTime atomic so both fields are updated atomically - wrap updatingMapName/updatingMapVersion into updatingMapInfo struct; nil replaces the != "" guard and fixes a latent bug where version could be set with an empty name - clear activeJob in StopJob (stops polling) while keeping lastPointCloudURL so the final map stays visible after a session ends - store logger on AppClient at construction; drop logger param from CheckSensorsDataCapture Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
part_id is now required (from config or env var), matching the existing machine_id behavior. removes the dead partID != "" guard in initialize. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6d5fc3d to
3280815
Compare
- ParseSensorsForPackage now delegates to sensorInfoToProto instead of re-iterating svc.sensors - generateProgressRingPCD uses PCDBinary instead of PCDAscii for smaller output Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Background thread now owns the current PCD entirely: builds the progress arc incrementally (appending only new points per tick) while waiting for a real map, then downloads and stores map bytes once available. PointCloudMap just reads the stored bytes. - Removes lastPointCloudURL and progressPCD atomics in favor of a single currentPCD atomic.Pointer[[]byte] - ParseSensorsForPackage delegates to sensorInfoToProto to avoid duplicating sensor iteration - generateProgressRingPCD uses PCDBinary instead of PCDAscii Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| mapURL := resp.GetMapUrl() | ||
| svc.lastPointCloudURL.Store(&mapURL) | ||
|
|
||
| if mapURL := resp.GetMapUrl(); mapURL != "" { |
There was a problem hiding this comment.
moved all of the pcd generation logic to the background thread, so now we don't have multiple threads making pcds
the background thread builds them, and GetMap sends them
cloudslam/cloudslam.go
Outdated
| } | ||
| } else if !job.startedAt.IsZero() { | ||
| // no map yet — incrementally build the progress arc | ||
| fraction := math.Max(0.02, math.Min(time.Since(job.startedAt).Seconds()/arcProgressRingDuration.Seconds(), 1.0)) |
There was a problem hiding this comment.
0.02 so we always start with some % of the circle showing up
cloudslam/cloudslam.go
Outdated
| } | ||
| } else if !job.startedAt.IsZero() { | ||
| // no map yet — incrementally build the progress arc | ||
| fraction := math.Max(minArcPercent, math.Min(time.Since(job.startedAt).Seconds()/arcProgressRingDuration.Seconds(), 1.0)) |
| angle := float64(i) / arcNumPoints * 2 * math.Pi | ||
| x := arcRadius * math.Cos(angle) | ||
| y := arcRadius * math.Sin(angle) | ||
| if err := arcPC.Set(r3.Vector{X: x, Y: y, Z: 0}, pointcloud.NewBasicData()); err != nil { |
nfranczak
left a comment
There was a problem hiding this comment.
just the optional to have
arcPC.Set(r3.Vector{X: x, Y: y, Z: 0}
become
arcPC.Set(r3.Vector{X: x, Y: y, Z: someConstName}
Two related changes: a user-visible feature and the internal state refactor it motivated.
Progress arc
While a job is running but no map has arrived yet,
PointCloudMapreturns a point cloud arc instead of the blank default. The arc grows from a small sliver to a full circle over 5 minutes, giving visual feedback that the session is active. (Text label added in the next PR.)Atomic state cleanup
activeJob(job ID string) +jobStartTimeinto a singleactiveJobStateatomic struct — both fields are now updated in one atomic swap, eliminating the window where one is set and the other isn't. Nil pointer replaces the empty-string sentinel.updatingMapName/updatingMapVersioninto anupdatingMapInfostruct; nil replaces the!= ""guard and fixes a latent bug where version could be set alongside an empty name.activeJobinStopJobto stop the polling loop, while preservinglastPointCloudURLso the final map stays visible after the session ends.machine_part_idis now required at startup (matchingmachine_idbehavior) — safe now that it's auto-populated from the env var.AppClientat construction; removes the logger parameter fromCheckSensorsDataCapture.Fix
page=slamto theStopJobreturn URL (without it the app backend redirects to/fleet/location/...).Part of a series: [PR A] → [PR B] → PR C → [PR D]