Skip to content

Commit

Permalink
feat(#243): Add cartesian position to telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
jugglingcats committed Oct 17, 2024
1 parent 8a8d72e commit c55a799
Show file tree
Hide file tree
Showing 15 changed files with 497 additions and 380 deletions.
42 changes: 8 additions & 34 deletions libs/controls/src/telemetry/TelemetryChartBrush.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,24 @@
/*
* Copyright (c) 2023. Glowbuzzer. All rights reserved
* Copyright (c) 2023-2024. Glowbuzzer. All rights reserved
*/

import {
TelemetryVisibilityOptions,
useTelemetryData,
useTelemetrySettings
} from "@glowbuzzer/store"
import { useTelemetryData } from "@glowbuzzer/store"
import React, { useEffect } from "react"
import * as d3 from "d3"
import { update } from "./update"
import { useElementSize } from "./hooks"
import { TelemetrySeries } from "./types"

type TelemetryChartBrushProps = {
joints: number[]
selected: boolean[]
view: TelemetryVisibilityOptions
series: TelemetrySeries[]
onBrush: (v: { selection: number[] }) => void
domain: number[]
}
/**
* Renders a brushable chart below the primary chart when the telemetry is paused
*/
export const TelemetryChartBrush = ({
joints,
selected,
view,
onBrush,
domain
}: TelemetryChartBrushProps) => {
const { plot } = useTelemetrySettings()
const { firstTimecode, lastTimecode, data, selector } = useTelemetryData()
export const TelemetryChartBrush = ({ series, onBrush, domain }: TelemetryChartBrushProps) => {
const { firstTimecode, lastTimecode, data } = useTelemetryData()
const [svgRef, width, height] = useElementSize<SVGSVGElement>()

useEffect(() => {
Expand All @@ -51,22 +39,8 @@ export const TelemetryChartBrush = ({
// render the brushable chart when the data or size changes
// here we will render all the available data
const x_domain = [firstTimecode, lastTimecode]
update(
svgRef.current,
data,
selector,
joints,
selected,
plot,
view,
x_domain,
domain,
0,
false,
0,
undefined
)
}, [lastTimecode, joints, view, plot, domain, width, height])
update(svgRef.current, data, series, x_domain, domain, 0, false, 0, undefined)
}, [lastTimecode, series, domain, width, height])

// the brushable chart is the `g` element of the svg, and we reduce the width by the right axis margin
return (
Expand Down
128 changes: 0 additions & 128 deletions libs/controls/src/telemetry/TelemetryChartCombined.tsx

This file was deleted.

115 changes: 115 additions & 0 deletions libs/controls/src/telemetry/TelemetryChartCombinedJoints.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2023-2024. Glowbuzzer. All rights reserved
*/
import React, { useCallback, useEffect, useMemo, useState } from "react"
import {
CaptureState,
get_telemetry_values_joints,
KinematicsConfigurationConfig,
TelemetryVisibilityOptions,
useTelemetryControls,
useTelemetryData
} from "@glowbuzzer/store"
import { TelemetryChartBrush } from "./TelemetryChartBrush"
import { TelemetryChartPrimary } from "./TelemetryChartPrimary"
import { TelemetrySeries } from "./types"
import { StyledChartsContainer } from "./styles"

type TelemetryChartCombinedProps = {
kinematicsConfiguration: KinematicsConfigurationConfig
view: TelemetryVisibilityOptions
selected: boolean[]
}
/**
* Render the primary chart and the brushable chart below it when the telemetry is paused
*/
export const TelemetryChartCombinedJoints = ({
kinematicsConfiguration,
view, // what to view: pos, vel, acc, etc
selected // the joints selected for charting, using kc indexes
}: TelemetryChartCombinedProps) => {
const { captureState, plot } = useTelemetryControls()
const { count, lastTimecode, domains } = useTelemetryData()
const [brush, setBrush] = React.useState(null)
const [domain, setDomain] = useState([0, 0])

useEffect(() => {
// when the data or selections change, we need to update the y-domain for the chart
const domain = kinematicsConfiguration.participatingJoints
.filter((_, i) => selected[i]) // remove unselected joints
.map(j => domains(j, plot, view)) // get the domains for each joint based on what is being viewed
.reduce(
(a, b) => [Math.min(a[0], b[0]), Math.max(a[1], b[1])],
[Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]
) // get single min/max
const [from, to] = domain.sort((a, b) => a - b)
const interval = to - from
setDomain([from - interval * 0.05, to + interval * 0.05]) // expand by 5%
}, [lastTimecode, selected, view, plot])

useEffect(() => {
// when switching capture state, make sure there is no brush
setBrush(null)
}, [captureState])

const series: TelemetrySeries[] = useMemo(() => {
return kinematicsConfiguration.participatingJoints
.map((_, i): TelemetrySeries[] => {
switch (view) {
case TelemetryVisibilityOptions.BOTH:
return [
{
key: `set-${i}`,
colourIndex: i,
value: item => get_telemetry_values_joints(item, i, view, plot)[0]
},
{
key: `act-${i}`,
colourIndex: i,
value: item => get_telemetry_values_joints(item, i, view, plot)[1],
secondary: true
}
]
case TelemetryVisibilityOptions.ACT:
return [
{
key: `act-${i}`,
colourIndex: i,
value: item => get_telemetry_values_joints(item, i, view, plot)[0],
secondary: true
}
]
default:
return [
{
key: `set-${i}`,
colourIndex: i,
value: item => get_telemetry_values_joints(item, i, view, plot)[0]
}
]
}
})
.filter((_, i) => selected[i])
.flat()
}, [kinematicsConfiguration.participatingJoints, view, plot, selected])

// we want a stable function as we pass this as prop to the brush component
const update_brush = useCallback(
(v: { selection: number[] }) => {
setBrush(v.selection)
},
[setBrush]
)

// do we want to show the brushable area?
const show_brush = captureState === CaptureState.PAUSED && count > 0

return (
<StyledChartsContainer>
<TelemetryChartPrimary series={series} brush={brush} domain={domain} />
{show_brush && (
<TelemetryChartBrush series={series} onBrush={update_brush} domain={domain} />
)}
</StyledChartsContainer>
)
}
46 changes: 8 additions & 38 deletions libs/controls/src/telemetry/TelemetryChartPrimary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,30 @@
* Copyright (c) 2024. Glowbuzzer. All rights reserved
*/

import {
TelemetryPVAT,
TelemetryVisibilityOptions,
useTelemetryControls,
useTelemetryData
} from "@glowbuzzer/store"
import { useTelemetryControls, useTelemetryData } from "@glowbuzzer/store"
import { useElementSize } from "./hooks"
import React, { useEffect } from "react"
import { update } from "./update"
import * as d3 from "d3"
import { TelemetrySeries } from "./types"

type TelemetryChartGenericProps = {
joints: number[]
selected: boolean[]
plot: TelemetryPVAT
view: TelemetryVisibilityOptions
series: TelemetrySeries[]
domain: number[]
brush?: number[]
}

export const TelemetryChartPrimary = ({
joints,
selected,
plot,
view,
domain,
brush
}: TelemetryChartGenericProps) => {
export const TelemetryChartPrimary = ({ series, domain, brush }: TelemetryChartGenericProps) => {
const { captureDuration } = useTelemetryControls()
const { firstTimecode, lastTimecode, data, count, selector } = useTelemetryData()
const { firstTimecode, lastTimecode, data, count } = useTelemetryData()
const [svgRef, width, height] = useElementSize<SVGSVGElement>()

useEffect(() => {
function exec_update(x_domain, from, to) {
function exec_update(x_domain: number[], from: number, to: number) {
const [x_scale, y_scale] = update(
svgRef.current,
data,
selector,
joints,
selected,
plot,
view,
series,
x_domain,
domain,
30,
Expand Down Expand Up @@ -75,19 +57,7 @@ export const TelemetryChartPrimary = ({
const from = -captureDuration
exec_update(x_domain, from, undefined)
}
}, [
firstTimecode,
lastTimecode,
width,
height,
brush,
captureDuration,
joints,
selected,
view,
plot,
domain
])
}, [firstTimecode, lastTimecode, width, height, brush, captureDuration, domain, series])

return (
<svg className="main" ref={svgRef}>
Expand Down
Loading

0 comments on commit c55a799

Please sign in to comment.