diff --git a/exercises/static/exercises/follow_line/python_template/ros2_humble/WebGUI.py b/exercises/static/exercises/follow_line/python_template/ros2_humble/WebGUI.py index 8256052e1..ef21851aa 100755 --- a/exercises/static/exercises/follow_line/python_template/ros2_humble/WebGUI.py +++ b/exercises/static/exercises/follow_line/python_template/ros2_humble/WebGUI.py @@ -104,6 +104,11 @@ def showImage(self, image): self.image_to_be_shown_updated = True + # Prepares and sends a map to the websocket server + def stop_exercise(self): + self.send_to_client(json.dumps({"action": "stop"})) + + host = "ws://127.0.0.1:2303" gui = WebGUI(host) @@ -114,3 +119,7 @@ def showImage(self, image): # Expose to the user def showImage(image): gui.showImage(image) + +# Expose to the user +def stop(): + gui.stop_exercise() \ No newline at end of file diff --git a/exercises/static/exercises/follow_line/react-components/SpecificFollowLine.js b/exercises/static/exercises/follow_line/react-components/SpecificFollowLine.js index 5d9ef8bfc..77937a8fc 100644 --- a/exercises/static/exercises/follow_line/react-components/SpecificFollowLine.js +++ b/exercises/static/exercises/follow_line/react-components/SpecificFollowLine.js @@ -2,7 +2,7 @@ import * as React from "react"; import { Box } from "@mui/material"; import "./css/GUICanvas.css"; import { getCarPose } from "./helpers/showCarPositionFollowLine"; -import { displayLapTime} from "./helpers/showLapTimeFollowLine"; +import { displayLapTime } from "./helpers/showLapTimeFollowLine"; import defaultCircuit from "../resources/images/default_circuit.png"; import montmeloCircuit from "../resources/images/montmelo_circuit.png"; @@ -10,41 +10,47 @@ import montrealCircuit from "../resources/images/montreal_circuit.png"; import ngbCircuit from "../resources/images/ngb_circuit.png"; const SpecificFollowLine = (props) => { - const [lapTime, setLapTime] = React.useState(null) - const [carPose, setCarPose] = React.useState(null) + const [lapTime, setLapTime] = React.useState(null); + const [carPose, setCarPose] = React.useState(null); const [circuitImg, setCircuitImg] = React.useState(defaultCircuit); - const canvasRef = React.useRef(null) + const canvasRef = React.useRef(null); var circuitName = "simple"; React.useEffect(() => { console.log("TestShowScreen subscribing to ['update'] events"); const callback = (message) => { - if(message.data.update.image){ - const image = JSON.parse(message.data.update.image) - if(image.image){ + if (message.data.update.action === "stop") { + window.RoboticsExerciseComponents.commsManager + .pause() + .then(() => {}) + .catch((response) => console.log(response)); + return; + } + + if (message.data.update.image) { + const image = JSON.parse(message.data.update.image); + if (image.image) { let canvas = document.getElementById("canvas"); //Parse encoded image data and decode it function decode_utf8(s) { - return decodeURIComponent(escape(s)) + return decodeURIComponent(escape(s)); } var source = decode_utf8(image.image), - shape = image.shape; + shape = image.shape; - if(source !== ""){ + if (source !== "") { canvas.src = "data:image/png;base64," + source; canvas.width = shape[1]; canvas.height = shape[0]; } } try { - const pose = getCarPose(circuitName, message.data.update.map) - setLapTime(displayLapTime(message.data.update.lap)) - setCarPose(pose) - } catch (error) { - - } + const pose = getCarPose(circuitName, message.data.update.map); + setLapTime(displayLapTime(message.data.update.lap)); + setCarPose(pose); + } catch (error) {} } - + // Send the ACK of the msg window.RoboticsExerciseComponents.commsManager.send("gui", "ack"); }; @@ -65,14 +71,14 @@ const SpecificFollowLine = (props) => { React.useEffect(() => { const callback = (message) => { - console.log(message) + console.log(message); if (message.data.state === "application_running") { window.RoboticsExerciseComponents.commsManager.send("gui", "start"); } else if (message.data.state === "paused") { window.RoboticsExerciseComponents.commsManager.send("gui", "pause"); } else if (message.data.state === "tools_ready") { - setCarPose(null) - setLapTime(null) + setCarPose(null); + setLapTime(null); switch (context.mapSelected) { case "Simple Circuit": circuitName = "default"; @@ -108,7 +114,7 @@ const SpecificFollowLine = (props) => { break; } } - } + }; window.RoboticsExerciseComponents.commsManager.subscribe( [window.RoboticsExerciseComponents.commsManager.events.STATE_CHANGED], @@ -122,19 +128,24 @@ const SpecificFollowLine = (props) => { callback ); }; - }, []) + }, []); return ( - + - { lapTime && - - } + {lapTime && ( + + )}
- {carPose && -
- } + {carPose && ( +
+ )}
); @@ -145,4 +156,4 @@ SpecificFollowLine.defaultProps = { height: 600, }; -export default SpecificFollowLine +export default SpecificFollowLine;