From 1012e1df1a40dc2a7f45b8c572ade75dc2ba4be3 Mon Sep 17 00:00:00 2001 From: Vincent Gerber Date: Mon, 21 Oct 2024 17:45:57 +0200 Subject: [PATCH] fix: Jogging panel control now shows as pressed for duration of increment jog (#123) Co-authored-by: Evan Summers --- .../jogging/JoggingCartesianAxisControl.tsx | 63 +++++++++++++++---- .../jogging/JoggingCartesianTab.tsx | 60 +++++++++++------- src/components/jogging/JoggingStore.ts | 18 ++++-- src/icons/rotation.svg | 4 +- src/themes/createDarkTheme.ts | 6 +- .../JoggingCartesianAxisControl.stories.tsx | 2 + 6 files changed, 113 insertions(+), 40 deletions(-) diff --git a/src/components/jogging/JoggingCartesianAxisControl.tsx b/src/components/jogging/JoggingCartesianAxisControl.tsx index 13004cd..db2da52 100644 --- a/src/components/jogging/JoggingCartesianAxisControl.tsx +++ b/src/components/jogging/JoggingCartesianAxisControl.tsx @@ -7,16 +7,17 @@ import JogMinus from "../../icons/jog-minus.svg" import JogPlus from "../../icons/jog-plus.svg" import type { AxisControlComponentColors } from "../../themes/themeTypes" import { useAnimationFrame } from "../utils/hooks" - -type Direction = "+" | "-" +import type { JoggingDirection } from "./JoggingStore" type JoggingCartesianAxisControlProps = { colors?: AxisControlComponentColors label: ReactNode getDisplayedValue: () => string - startJogging: (direction: Direction) => void + startJogging: (direction: JoggingDirection) => void stopJogging: () => void disabled?: boolean + /** If set, the corresponding button will be rendered in the pressed state */ + activeJoggingDirection?: JoggingDirection } & React.ComponentProps /** A input widget to control an individual cartesian axis */ @@ -29,6 +30,7 @@ export const JoggingCartesianAxisControl = externalizeComponent( startJogging, stopJogging, disabled, + activeJoggingDirection, ...rest }: JoggingCartesianAxisControlProps) => { useAnimationFrame(() => { @@ -39,7 +41,13 @@ export const JoggingCartesianAxisControl = externalizeComponent( element.textContent = displayValue }) const theme = useTheme() - const [borderColor, setBorderColor] = useState(colors?.borderColor) + + const [localActiveJoggingDirection, setLocalActiveJoggingDirection] = + useState(null) + + // Handle both controlled and uncontrolled states + const showJoggingDirection = + activeJoggingDirection || localActiveJoggingDirection const valueContainerRef = useRef(null) @@ -57,17 +65,31 @@ export const JoggingCartesianAxisControl = externalizeComponent( } } - const SxAxisControlButton = { + const borderColor = showJoggingDirection + ? colors.buttonBackgroundColor?.pressed + : colors.borderColor + + const sxAxisControlButtonBase = { width: "55px", - backgroundColor: colors.buttonBackgroundColor?.default, color: colors.color, + path: { fill: colors.color }, alignContent: "center", fontSize: "37px", + svg: { + pointerEvents: "none", + }, + } + + const sxAxisControlButtonDefault = { + ...sxAxisControlButtonBase, + backgroundColor: colors.buttonBackgroundColor?.default, "&:hover": { backgroundColor: colors.buttonBackgroundColor?.hovered, }, "&:active": { backgroundColor: colors.buttonBackgroundColor?.pressed, + color: colors.backgroundColor, + path: { fill: colors.backgroundColor }, }, ":disabled": { backgroundColor: colors.buttonBackgroundColor?.disabled, @@ -75,18 +97,33 @@ export const JoggingCartesianAxisControl = externalizeComponent( }, } - function onPointerDown(ev: React.PointerEvent, direction: Direction) { + const sxAxisControlButtonPressed = { + ...sxAxisControlButtonBase, + backgroundColor: colors.buttonBackgroundColor?.pressed, + color: colors.backgroundColor, + path: { fill: colors.backgroundColor }, + ":disabled": { + backgroundColor: colors.buttonBackgroundColor?.pressed, + "svg path": { fill: theme.palette.action.disabled }, + }, + } + + function onPointerDown( + ev: React.PointerEvent, + direction: JoggingDirection, + ) { if (disabled) { return } - setBorderColor(colors?.buttonBackgroundColor?.pressed) + if (ev.button === 0) { + setLocalActiveJoggingDirection(direction) startJogging(direction) } } function onPointerUpOrOut() { - setBorderColor(colors?.borderColor) + setLocalActiveJoggingDirection(null) stopJogging() } @@ -100,7 +137,9 @@ export const JoggingCartesianAxisControl = externalizeComponent( onPointerOut={onPointerUpOrOut} size="large" sx={{ - ...SxAxisControlButton, + ...(showJoggingDirection === "-" + ? sxAxisControlButtonPressed + : sxAxisControlButtonDefault), borderRadius: "16px 0px 0px 16px", borderLeft: `2px solid ${borderColor ?? "#fff"}`, borderBottom: `2px solid ${borderColor ?? "#fff"}`, @@ -163,7 +202,9 @@ export const JoggingCartesianAxisControl = externalizeComponent( onPointerOut={onPointerUpOrOut} size="large" sx={{ - ...SxAxisControlButton, + ...(showJoggingDirection === "+" + ? sxAxisControlButtonPressed + : sxAxisControlButtonDefault), borderRadius: "0px 16px 16px 0px", borderRight: `2px solid ${borderColor ?? "#fff"}`, borderBottom: `2px solid ${borderColor ?? "#fff"}`, diff --git a/src/components/jogging/JoggingCartesianTab.tsx b/src/components/jogging/JoggingCartesianTab.tsx index 37beca0..0d2e151 100644 --- a/src/components/jogging/JoggingCartesianTab.tsx +++ b/src/components/jogging/JoggingCartesianTab.tsx @@ -17,14 +17,19 @@ import { JoggingActivationRequired } from "./JoggingActivationRequired" import { JoggingCartesianAxisControl } from "./JoggingCartesianAxisControl" import { JoggingJointLimitDetector } from "./JoggingJointLimitDetector" import { JoggingOptions } from "./JoggingOptions" -import type { DiscreteIncrementOption, JoggingStore } from "./JoggingStore" +import type { + DiscreteIncrementOption, + JoggingAxis, + JoggingDirection, + JoggingStore, +} from "./JoggingStore" import { JoggingToggleButtonGroup } from "./JoggingToggleButtonGroup" import { JoggingVelocitySlider } from "./JoggingVelocitySlider" type JoggingCartesianOpts = { - axis: "x" | "y" | "z" + axis: JoggingAxis motionType: "translate" | "rotate" - direction: "-" | "+" + direction: JoggingDirection } export const JoggingCartesianTab = observer( @@ -70,24 +75,32 @@ export const JoggingCartesianTab = observer( if (!tcpPose) return await store.withMotionLock(async () => { - await store.jogger.runIncrementalCartesianMotion({ - currentTcpPose: tcpPose, - currentJoints: jointPosition, - coordSystemId: store.activeCoordSystemId, - velocityInRelevantUnits: store.velocityInCurrentUnits, - axis: opts.axis, - direction: opts.direction, - motion: - store.selectedCartesianMotionType === "translate" - ? { - type: "translate", - distanceMm: increment.mm, - } - : { - type: "rotate", - distanceRads: degreesToRadians(increment.degrees), - }, - }) + try { + store.setCurrentIncrementJog({ + axis: opts.axis, + direction: opts.direction, + }) + await store.jogger.runIncrementalCartesianMotion({ + currentTcpPose: tcpPose, + currentJoints: jointPosition, + coordSystemId: store.activeCoordSystemId, + velocityInRelevantUnits: store.velocityInCurrentUnits, + axis: opts.axis, + direction: opts.direction, + motion: + store.selectedCartesianMotionType === "translate" + ? { + type: "translate", + distanceMm: increment.mm, + } + : { + type: "rotate", + distanceRads: degreesToRadians(increment.degrees), + }, + }) + } finally { + store.setCurrentIncrementJog(null) + } }) } @@ -195,6 +208,11 @@ export const JoggingCartesianTab = observer( key={axis.id} colors={axis.colors} disabled={store.isLocked} + activeJoggingDirection={ + store.incrementJogInProgress?.axis === axis.id + ? store.incrementJogInProgress.direction + : undefined + } label={ <> {axis.icon} diff --git a/src/components/jogging/JoggingStore.ts b/src/components/jogging/JoggingStore.ts index 13acac1..37d42bf 100644 --- a/src/components/jogging/JoggingStore.ts +++ b/src/components/jogging/JoggingStore.ts @@ -27,6 +27,8 @@ const incrementOptions = [ ...discreteIncrementOptions, ] as const +export type JoggingAxis = "x" | "y" | "z" +export type JoggingDirection = "+" | "-" export type DiscreteIncrementOption = (typeof discreteIncrementOptions)[number] export type IncrementOption = (typeof incrementOptions)[number] export type IncrementOptionId = IncrementOption["id"] @@ -34,6 +36,11 @@ export type IncrementOptionId = IncrementOption["id"] export const ORIENTATION_IDS = ["coordsys", "tool"] export type OrientationId = (typeof ORIENTATION_IDS)[number] +export type IncrementJogInProgress = { + direction: JoggingDirection + axis: JoggingAxis +} + export class JoggingStore { selectedTabId: "cartesian" | "joint" | "debug" = "cartesian" @@ -87,8 +94,11 @@ export class JoggingStore { */ selectedCartesianMotionType: "translate" | "rotate" = "translate" - /** True when the API is busy doing a planned increment jog motion */ - incrementJoggingInProgress = false + /** + * If the jogger is busy running an incremental jog, this will be set + * with the information about the motion + */ + incrementJogInProgress: IncrementJogInProgress | null = null /** How fast the robot goes when doing cartesian translate jogging in mm/s */ translationVelocityMmPerSec: number = 10 @@ -437,8 +447,8 @@ export class JoggingStore { this.selectedIncrementId = id } - setIncrementJoggingInProgress(inProgress: boolean) { - this.incrementJoggingInProgress = inProgress + setCurrentIncrementJog(incrementJog: IncrementJogInProgress | null) { + this.incrementJogInProgress = incrementJog } setVelocityFromSlider(velocity: number) { diff --git a/src/icons/rotation.svg b/src/icons/rotation.svg index db06c14..3fbe87a 100644 --- a/src/icons/rotation.svg +++ b/src/icons/rotation.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/themes/createDarkTheme.ts b/src/themes/createDarkTheme.ts index 520ac90..ca30d34 100644 --- a/src/themes/createDarkTheme.ts +++ b/src/themes/createDarkTheme.ts @@ -212,7 +212,7 @@ export function createDarkTheme(): Theme { hovered: "rgba(241, 77, 66, 1)", disabled: "rgba(241, 77, 66, 1)", }, - color: "rgba(255, 255, 255, 1)", + color: "rgba(255, 198, 198, 1)", }, Y: { backgroundColor: "rgba(20, 151, 108, 1)", @@ -223,7 +223,7 @@ export function createDarkTheme(): Theme { disabled: "rgba(28, 188, 135, 1)", hovered: "rgba(28, 188, 135, 1)", }, - color: "rgba(255, 255, 255, 1)", + color: "rgba(215, 255, 242, 1)", }, Z: { backgroundColor: "rgba(1, 87, 155, 1)", @@ -234,7 +234,7 @@ export function createDarkTheme(): Theme { disabled: "rgba(2, 136, 209, 1)", hovered: "rgba(2, 136, 209, 1)", }, - color: "rgba(255, 255, 255, 1)", + color: "rgba(210, 239, 255, 1)", }, }, }, diff --git a/stories/JoggingCartesianAxisControl.stories.tsx b/stories/JoggingCartesianAxisControl.stories.tsx index b5e26ca..02d7ef0 100644 --- a/stories/JoggingCartesianAxisControl.stories.tsx +++ b/stories/JoggingCartesianAxisControl.stories.tsx @@ -13,7 +13,9 @@ const meta: Meta = { args: { label: "X", disabled: false, + activeJoggingDirection: "+", }, + render: function Component(args) { const joggingDirRef = useRef<"+" | "-" | null>(null) const joggingValueRef = useRef(0)