From f7a4cfa4a6f9e7b79ca43966422fbbe65a2f7eeb Mon Sep 17 00:00:00 2001 From: Joel Chan <39267610+JoelChanZhiYang@users.noreply.github.com> Date: Mon, 6 May 2024 01:07:09 +0800 Subject: [PATCH] Ev3 defensive tabs (#313) * Remove unused variable in Program * Make the ev3 tabs more defensive --- .../controllers/program/Program.ts | 2 +- src/bundles/robot_simulation/engine/World.ts | 17 ++++++++++------- .../components/Simulation/index.tsx | 18 +++++++++++++----- .../components/TabPanels/ColorSensorPanel.tsx | 12 ++++++++---- .../components/TabPanels/ConsolePanel.tsx | 2 +- .../components/TabPanels/MotorPidPanel.tsx | 17 ++++++++++++++++- .../TabPanels/UltrasonicSensorPanel.tsx | 13 ++++++++++--- .../components/TabPanels/WheelPidPanel.tsx | 18 +++++++++++++++++- 8 files changed, 76 insertions(+), 23 deletions(-) diff --git a/src/bundles/robot_simulation/controllers/program/Program.ts b/src/bundles/robot_simulation/controllers/program/Program.ts index a6fa5d5cc..c7c67c9cb 100644 --- a/src/bundles/robot_simulation/controllers/program/Program.ts +++ b/src/bundles/robot_simulation/controllers/program/Program.ts @@ -67,7 +67,7 @@ export class Program implements Controller { // steps per tick for (let i = 0; i < this.config.stepsPerTick; i++) { - const result = this.iterator.next(); + this.iterator.next(); } } catch (e) { console.error(e); diff --git a/src/bundles/robot_simulation/engine/World.ts b/src/bundles/robot_simulation/engine/World.ts index 95239fcda..6bec650a9 100644 --- a/src/bundles/robot_simulation/engine/World.ts +++ b/src/bundles/robot_simulation/engine/World.ts @@ -30,7 +30,12 @@ export class World extends TypedEventTarget { robotConsole: RobotConsole; controllers: ControllerGroup; - constructor(physics: Physics, render: Renderer, timer: Timer, robotConsole: RobotConsole) { + constructor( + physics: Physics, + render: Renderer, + timer: Timer, + robotConsole: RobotConsole + ) { super(); this.state = 'unintialized'; this.physics = physics; @@ -71,10 +76,7 @@ export class World extends TypedEventTarget { private setState(newState: WorldState) { if (this.state !== newState) { - this.dispatchEvent( - 'worldStateChange', - new Event('worldStateChange'), - ); + this.dispatchEvent('worldStateChange', new Event('worldStateChange')); this.state = newState; } } @@ -90,6 +92,7 @@ export class World extends TypedEventTarget { window.requestAnimationFrame(this.step.bind(this)); } } + step(timestamp: number) { try { const frameTimingInfo = this.timer.step(timestamp); @@ -99,12 +102,12 @@ export class World extends TypedEventTarget { // Update render this.dispatchEvent( 'beforeRender', - new TimeStampedEvent('beforeRender', physicsTimingInfo), + new TimeStampedEvent('beforeRender', physicsTimingInfo) ); this.render.step(frameTimingInfo); this.dispatchEvent( 'afterRender', - new TimeStampedEvent('afterRender', physicsTimingInfo), + new TimeStampedEvent('afterRender', physicsTimingInfo) ); if (this.state === 'running') { diff --git a/src/tabs/RobotSimulation/components/Simulation/index.tsx b/src/tabs/RobotSimulation/components/Simulation/index.tsx index 4726003fc..aa599b953 100644 --- a/src/tabs/RobotSimulation/components/Simulation/index.tsx +++ b/src/tabs/RobotSimulation/components/Simulation/index.tsx @@ -46,13 +46,16 @@ export const SimulationCanvas: React.FC = ({ }) => { const ref = useRef(null); const sensorRef = useRef(null); - const [currentState, setCurrentState] - = useState('unintialized'); + const [currentState, setCurrentState] = useState('unintialized'); + + // We know this is true because it is checked in RobotSimulation/index.tsx (toSpawn) const world = context.context.moduleContexts.robot_simulation.state .world as World; - const ev3 = context.context.moduleContexts.robot_simulation.state - .ev3 as DefaultEv3; + // This is not guaranteed to be true. + const ev3 = context.context.moduleContexts.robot_simulation.state.ev3 as + | DefaultEv3 + | undefined; const robotConsole = world.robotConsole; @@ -65,9 +68,14 @@ export const SimulationCanvas: React.FC = ({ if (ref.current) { ref.current.replaceChildren(world.render.getElement()); } + if (!ev3) { + return; + } if (sensorRef.current) { - sensorRef.current.replaceChildren(ev3.get('colorSensor').renderer.getElement()); + sensorRef.current.replaceChildren( + ev3.get('colorSensor').renderer.getElement() + ); } }; diff --git a/src/tabs/RobotSimulation/components/TabPanels/ColorSensorPanel.tsx b/src/tabs/RobotSimulation/components/TabPanels/ColorSensorPanel.tsx index 644cc42ab..380aa5d0f 100644 --- a/src/tabs/RobotSimulation/components/TabPanels/ColorSensorPanel.tsx +++ b/src/tabs/RobotSimulation/components/TabPanels/ColorSensorPanel.tsx @@ -4,25 +4,29 @@ import { useFetchFromSimulation } from '../../hooks/fetchFromSimulation'; import { LastUpdated } from './tabComponents/LastUpdated'; import { TabWrapper } from './tabComponents/Wrapper'; -export const ColorSensorPanel: React.FC<{ ev3: DefaultEv3 }> = ({ ev3 }) => { - const colorSensor = ev3.get('colorSensor'); +export const ColorSensorPanel: React.FC<{ ev3?: DefaultEv3 }> = ({ ev3 }) => { + const colorSensor = ev3?.get('colorSensor'); const sensorVisionRef = useRef(null); const [timing, color] = useFetchFromSimulation(() => { - if (ev3.get('colorSensor') === undefined) { + if (colorSensor === undefined) { return null; } return colorSensor.sense(); }, 1000); useEffect(() => { - if (sensorVisionRef.current) { + if (colorSensor && sensorVisionRef.current) { sensorVisionRef.current.replaceChildren( colorSensor.renderer.getElement() ); } }, [timing]); + if (!ev3) { + return EV3 not found in context. Did you call saveToContext('ev3', ev3);; + } + if (timing === null) { return Loading color sensor; } diff --git a/src/tabs/RobotSimulation/components/TabPanels/ConsolePanel.tsx b/src/tabs/RobotSimulation/components/TabPanels/ConsolePanel.tsx index 8ff7e73c4..856cf34a6 100644 --- a/src/tabs/RobotSimulation/components/TabPanels/ConsolePanel.tsx +++ b/src/tabs/RobotSimulation/components/TabPanels/ConsolePanel.tsx @@ -17,7 +17,7 @@ const getLogString = (log: LogEntry) => { }; export const ConsolePanel: React.FC<{ - robot_console?: RobotConsole; + robot_console: RobotConsole; }> = ({ robot_console }) => { const [timing, logs] = useFetchFromSimulation(() => { if (robot_console === undefined) { diff --git a/src/tabs/RobotSimulation/components/TabPanels/MotorPidPanel.tsx b/src/tabs/RobotSimulation/components/TabPanels/MotorPidPanel.tsx index ec9a88f43..d51bb8059 100644 --- a/src/tabs/RobotSimulation/components/TabPanels/MotorPidPanel.tsx +++ b/src/tabs/RobotSimulation/components/TabPanels/MotorPidPanel.tsx @@ -9,7 +9,22 @@ const RowStyle: CSSProperties = { gap: '0.6rem', }; -export const MotorPidPanel: React.FC<{ ev3: DefaultEv3 }> = ({ ev3 }) => { +export const MotorPidPanel: React.FC<{ ev3?: DefaultEv3 }> = ({ ev3 }) => { + if (!ev3) { + return ( + + EV3 not found in context. Did you call saveToContext('ev3', ev3); + + ); + } + + const leftMotor = ev3.get('leftMotor'); + const rightMotor = ev3.get('rightMotor'); + + if (!leftMotor || !rightMotor) { + return Motor not found; + } + const onChangeProportional = (value: number) => { ev3.get('leftMotor').pid.proportionalGain = value; ev3.get('rightMotor').pid.proportionalGain = value; diff --git a/src/tabs/RobotSimulation/components/TabPanels/UltrasonicSensorPanel.tsx b/src/tabs/RobotSimulation/components/TabPanels/UltrasonicSensorPanel.tsx index dfa64a3fe..04a7a558b 100644 --- a/src/tabs/RobotSimulation/components/TabPanels/UltrasonicSensorPanel.tsx +++ b/src/tabs/RobotSimulation/components/TabPanels/UltrasonicSensorPanel.tsx @@ -4,11 +4,10 @@ import { useFetchFromSimulation } from '../../hooks/fetchFromSimulation'; import { LastUpdated } from './tabComponents/LastUpdated'; import { TabWrapper } from './tabComponents/Wrapper'; -export const UltrasonicSensorPanel: React.FC<{ ev3: DefaultEv3 }> = ({ +export const UltrasonicSensorPanel: React.FC<{ ev3?: DefaultEv3 }> = ({ ev3, }) => { - const ultrasonicSensor = ev3.get('ultrasonicSensor'); - + const ultrasonicSensor = ev3?.get('ultrasonicSensor'); const [timing, distanceSensed] = useFetchFromSimulation(() => { if (ultrasonicSensor === undefined) { return null; @@ -16,6 +15,14 @@ export const UltrasonicSensorPanel: React.FC<{ ev3: DefaultEv3 }> = ({ return ultrasonicSensor.sense(); }, 1000); + if (!ev3) { + return ( + + EV3 not found in context. Did you call saveToContext('ev3', ev3); + + ); + } + if (timing === null) { return Loading ultrasonic sensor; } diff --git a/src/tabs/RobotSimulation/components/TabPanels/WheelPidPanel.tsx b/src/tabs/RobotSimulation/components/TabPanels/WheelPidPanel.tsx index b4f5fcd30..d800f3ec6 100644 --- a/src/tabs/RobotSimulation/components/TabPanels/WheelPidPanel.tsx +++ b/src/tabs/RobotSimulation/components/TabPanels/WheelPidPanel.tsx @@ -9,7 +9,23 @@ const RowStyle: CSSProperties = { gap: '0.6rem', }; -export const WheelPidPanel: React.FC<{ ev3: DefaultEv3 }> = ({ ev3 }) => { +export const WheelPidPanel: React.FC<{ ev3?: DefaultEv3 }> = ({ ev3 }) => { + if (!ev3) { + return ( + + EV3 not found in context. Did you call saveToContext('ev3', ev3); + + ); + } + if ( + !ev3.get('backLeftWheel') || + !ev3.get('backRightWheel') || + !ev3.get('frontLeftWheel') || + !ev3.get('frontRightWheel') + ) { + return Wheel not found; + } + const onChangeProportional = (value: number) => { ev3.get('backLeftWheel').pid.proportionalGain = value; ev3.get('backRightWheel').pid.proportionalGain = value;