Compare commits
	
		
			4 Commits
		
	
	
		
			d46aa6af45
			...
			feat/image
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cd866cc511 | |||
| 9f86d060f0 | |||
| e2f4a0d2a5 | |||
| bc96cea2b9 | 
							
								
								
									
										59
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								README.md
									
									
									
									
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | <p align="center"> | ||||||
|  |     <img src="logo.png" width="300"> | ||||||
|  | </p> | ||||||
|  |  | ||||||
|  | # Rally Racer | ||||||
|  |  | ||||||
|  | This repository holds a sandbox driving simulation controllable via a network interface as a machine learning and data collection challenge. | ||||||
|  |  | ||||||
|  | # Installation | ||||||
|  | From the root of the repository, run | ||||||
|  | ```sh | ||||||
|  | uv sync | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | To run the game, you can use | ||||||
|  | ```sh | ||||||
|  | uv run main.py | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # Generality | ||||||
|  | Launching [`main.py`](main.py) starts a race with a single car on the provided track.  | ||||||
|  | This track can be controlled either by keyboard (*WASD*) or by a socket interface.  | ||||||
|  | An example of such interface is included in the code in [*`scripts/recorder.py`*](scripts/recorder.py). To run it, simply use the following command: | ||||||
|  | ```sh | ||||||
|  | uv run -m scripts.recorder | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | # Sensing | ||||||
|  | The car sensing is available in two commodities: **raycasts** and **images**. These sensing snapshots are sent at 10 Hertz (i.e. 10 times a second). Due to this fact, correct reception of snapshot messages has to be done regularly. | ||||||
|  |  | ||||||
|  | # Communication protocol | ||||||
|  |  | ||||||
|  | A remote controller can be impemented using TCP socket connecting on localhost on port 5000. | ||||||
|  | Different commands can be issued to the race simulation to control the car. | ||||||
|  |  | ||||||
|  | These commands are declared in [`src/command.py`](src/command.py) | ||||||
|  |  | ||||||
|  | ##  Car controls | ||||||
|  | ```python | ||||||
|  | ControlCommand(control: CarControl, active: bool) | ||||||
|  | ``` | ||||||
|  | To simulate key press and control the car. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Controls | ||||||
|  |  | ||||||
|  | - <kbd>W</kbd> Move forward | ||||||
|  | - <kbd>S</kbd> Brake / move backward | ||||||
|  | - <kbd>A</kbd> Turn left | ||||||
|  | - <kbd>D</kbd> Turn right | ||||||
|  | - <kbd>F</kbd> Toggle FPS indicator | ||||||
|  | - <kbd>V</kbd> Toggle speedometer | ||||||
|  | - <kbd>R</kbd> Reset car | ||||||
|  | - <kbd>C</kbd> Toggle raycasts visibility | ||||||
|  | - <kbd>Esc</kbd> Quit | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Credits | ||||||
|  | This project is based on the repository [https://github.com/ISC-HEI/RallyRobotPilot_2025](https://github.com/ISC-HEI/RallyRobotPilot_2025), which is in turn based on [https://github.com/mandaw2014/Rally](https://github.com/mandaw2014/Rally) | ||||||
							
								
								
									
										143
									
								
								car.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								car.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||||
|  |  | ||||||
|  | <svg | ||||||
|  |    width="64" | ||||||
|  |    height="64" | ||||||
|  |    viewBox="0 0 64 64.000003" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg1" | ||||||
|  |    inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" | ||||||
|  |    sodipodi:docname="car.svg" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview1" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:document-units="mm" | ||||||
|  |      showgrid="true" | ||||||
|  |      inkscape:zoom="11.313709" | ||||||
|  |      inkscape:cx="42.470601" | ||||||
|  |      inkscape:cy="34.957591" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1016" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="layer1"> | ||||||
|  |     <inkscape:grid | ||||||
|  |        id="grid1" | ||||||
|  |        units="px" | ||||||
|  |        originx="0" | ||||||
|  |        originy="0" | ||||||
|  |        spacingx="1" | ||||||
|  |        spacingy="1" | ||||||
|  |        empcolor="#0099e5" | ||||||
|  |        empopacity="0.30196078" | ||||||
|  |        color="#0099e5" | ||||||
|  |        opacity="0.14901961" | ||||||
|  |        empspacing="8" | ||||||
|  |        enabled="true" | ||||||
|  |        visible="true" /> | ||||||
|  |   </sodipodi:namedview> | ||||||
|  |   <defs | ||||||
|  |      id="defs1"> | ||||||
|  |     <inkscape:path-effect | ||||||
|  |        effect="fillet_chamfer" | ||||||
|  |        id="path-effect3" | ||||||
|  |        is_visible="true" | ||||||
|  |        lpeversion="1" | ||||||
|  |        nodesatellites_param="F,0,0,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1" | ||||||
|  |        radius="0" | ||||||
|  |        unit="px" | ||||||
|  |        method="auto" | ||||||
|  |        mode="F" | ||||||
|  |        chamfer_steps="1" | ||||||
|  |        flexible="false" | ||||||
|  |        use_knot_distance="true" | ||||||
|  |        apply_no_radius="true" | ||||||
|  |        apply_with_radius="true" | ||||||
|  |        only_selected="false" | ||||||
|  |        hide_knots="false" /> | ||||||
|  |     <inkscape:path-effect | ||||||
|  |        effect="fillet_chamfer" | ||||||
|  |        id="path-effect2" | ||||||
|  |        is_visible="true" | ||||||
|  |        lpeversion="1" | ||||||
|  |        nodesatellites_param="F,0,1,1,0,1.0000001,0,1 @ F,0,1,1,0,1.0000001,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,1,1,0,1.0000001,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1" | ||||||
|  |        radius="0" | ||||||
|  |        unit="px" | ||||||
|  |        method="auto" | ||||||
|  |        mode="F" | ||||||
|  |        chamfer_steps="1" | ||||||
|  |        flexible="false" | ||||||
|  |        use_knot_distance="true" | ||||||
|  |        apply_no_radius="true" | ||||||
|  |        apply_with_radius="true" | ||||||
|  |        only_selected="false" | ||||||
|  |        hide_knots="false" /> | ||||||
|  |   </defs> | ||||||
|  |   <g | ||||||
|  |      inkscape:label="Calque 1" | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      id="layer1"> | ||||||
|  |     <g | ||||||
|  |        id="g5" | ||||||
|  |        inkscape:label="car" | ||||||
|  |        transform="translate(-5.9999998,-7.9999997)"> | ||||||
|  |       <g | ||||||
|  |          id="g4" | ||||||
|  |          inkscape:label="wheels"> | ||||||
|  |         <path | ||||||
|  |            style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 25.000001,31.999999 v -2 h 4 v 2 z" | ||||||
|  |            id="path2" | ||||||
|  |            sodipodi:nodetypes="ccccc" /> | ||||||
|  |         <path | ||||||
|  |            style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 43.000001,31.999999 v -2 h 4 v 2 z" | ||||||
|  |            id="path2-3" | ||||||
|  |            sodipodi:nodetypes="ccccc" /> | ||||||
|  |         <path | ||||||
|  |            style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 25.000001,49.999999 v -2 h 4 v 2 z" | ||||||
|  |            id="path2-1" | ||||||
|  |            sodipodi:nodetypes="ccccc" /> | ||||||
|  |         <path | ||||||
|  |            style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 43.000001,49.999999 v -2 h 4 v 2 z" | ||||||
|  |            id="path2-3-2" | ||||||
|  |            sodipodi:nodetypes="ccccc" /> | ||||||
|  |       </g> | ||||||
|  |       <path | ||||||
|  |          style="fill:#e14324;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |          d="m 16,33 v 13.999999 a 1.1327823,1.1327823 48.562508 0 0 0.992278,1.124035 l 7.007723,0.875965 h 24 l 11.003454,-0.916955 a 1.0867997,1.0867997 132.61818 0 0 0.996546,-1.083045 v -14 A 1.0867996,1.0867996 47.381818 0 0 59.003455,31.916954 L 48.000001,31 h -24 l -7.007723,0.875965 A 1.1327823,1.1327823 131.43749 0 0 16,33 Z" | ||||||
|  |          id="path1" | ||||||
|  |          inkscape:path-effect="#path-effect2" | ||||||
|  |          inkscape:original-d="m 16,32 v 15.999999 l 8.000001,1 h 24 l 12,-1 v -16 L 48.000001,31 h -24 z" | ||||||
|  |          inkscape:label="body" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:#53170b;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |          d="m 50.000001,33.500001 v 13 a 1.0867994,1.0867994 132.61819 0 1 -0.996546,1.083045 l -4.006908,0.333908 A 0.92013337,0.92013337 42.618189 0 1 44.000001,46.999999 V 33 a 0.92013291,0.92013291 137.38183 0 1 0.996546,-0.916954 l 4.006908,0.333909 a 1.0867999,1.0867999 47.381826 0 1 0.996546,1.083046 z" | ||||||
|  |          id="path3" | ||||||
|  |          inkscape:path-effect="#path-effect3" | ||||||
|  |          inkscape:original-d="m 50.000001,32.500001 v 15 l -6,0.499998 V 32 Z" | ||||||
|  |          sodipodi:nodetypes="ccccc" | ||||||
|  |          inkscape:label="windshield" /> | ||||||
|  |       <path | ||||||
|  |          style="fill:#af3116;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |          d="m 29.000001,46.999999 c -4,0 -8.000001,0 -11.000001,-1 v -12 c 3,-1 7.000001,-1 11.000001,-1 z" | ||||||
|  |          id="path4" | ||||||
|  |          sodipodi:nodetypes="ccccc" | ||||||
|  |          inkscape:label="back_window" /> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 5.2 KiB | 
							
								
								
									
										202
									
								
								logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								logo.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||||
|  | <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||||
|  |  | ||||||
|  | <svg | ||||||
|  |    width="64" | ||||||
|  |    height="64" | ||||||
|  |    viewBox="0 0 64 64.000003" | ||||||
|  |    version="1.1" | ||||||
|  |    id="svg1" | ||||||
|  |    inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)" | ||||||
|  |    sodipodi:docname="logo.svg" | ||||||
|  |    inkscape:export-filename="logo.png" | ||||||
|  |    inkscape:export-xdpi="768" | ||||||
|  |    inkscape:export-ydpi="768" | ||||||
|  |    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||||
|  |    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||||
|  |    xmlns="http://www.w3.org/2000/svg" | ||||||
|  |    xmlns:svg="http://www.w3.org/2000/svg"> | ||||||
|  |   <sodipodi:namedview | ||||||
|  |      id="namedview1" | ||||||
|  |      pagecolor="#ffffff" | ||||||
|  |      bordercolor="#000000" | ||||||
|  |      borderopacity="0.25" | ||||||
|  |      inkscape:showpageshadow="2" | ||||||
|  |      inkscape:pageopacity="0.0" | ||||||
|  |      inkscape:pagecheckerboard="0" | ||||||
|  |      inkscape:deskcolor="#d1d1d1" | ||||||
|  |      inkscape:document-units="mm" | ||||||
|  |      showgrid="true" | ||||||
|  |      inkscape:zoom="11.313709" | ||||||
|  |      inkscape:cx="31.952386" | ||||||
|  |      inkscape:cy="30.803338" | ||||||
|  |      inkscape:window-width="1920" | ||||||
|  |      inkscape:window-height="1016" | ||||||
|  |      inkscape:window-x="0" | ||||||
|  |      inkscape:window-y="27" | ||||||
|  |      inkscape:window-maximized="1" | ||||||
|  |      inkscape:current-layer="layer1" | ||||||
|  |      inkscape:export-bgcolor="#ffffffff"> | ||||||
|  |     <inkscape:grid | ||||||
|  |        id="grid1" | ||||||
|  |        units="px" | ||||||
|  |        originx="0" | ||||||
|  |        originy="0" | ||||||
|  |        spacingx="1" | ||||||
|  |        spacingy="1" | ||||||
|  |        empcolor="#0099e5" | ||||||
|  |        empopacity="0.30196078" | ||||||
|  |        color="#0099e5" | ||||||
|  |        opacity="0.14901961" | ||||||
|  |        empspacing="8" | ||||||
|  |        enabled="true" | ||||||
|  |        visible="true" /> | ||||||
|  |   </sodipodi:namedview> | ||||||
|  |   <defs | ||||||
|  |      id="defs1"> | ||||||
|  |     <inkscape:path-effect | ||||||
|  |        effect="fillet_chamfer" | ||||||
|  |        id="path-effect3" | ||||||
|  |        is_visible="true" | ||||||
|  |        lpeversion="1" | ||||||
|  |        nodesatellites_param="F,0,0,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1 @ F,0,1,1,0,1.0000002,0,1" | ||||||
|  |        radius="0" | ||||||
|  |        unit="px" | ||||||
|  |        method="auto" | ||||||
|  |        mode="F" | ||||||
|  |        chamfer_steps="1" | ||||||
|  |        flexible="false" | ||||||
|  |        use_knot_distance="true" | ||||||
|  |        apply_no_radius="true" | ||||||
|  |        apply_with_radius="true" | ||||||
|  |        only_selected="false" | ||||||
|  |        hide_knots="false" /> | ||||||
|  |     <inkscape:path-effect | ||||||
|  |        effect="fillet_chamfer" | ||||||
|  |        id="path-effect2" | ||||||
|  |        is_visible="true" | ||||||
|  |        lpeversion="1" | ||||||
|  |        nodesatellites_param="F,0,1,1,0,1.0000001,0,1 @ F,0,1,1,0,1.0000001,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,1.0000001,0,1 @ F,0,1,1,0,1.0000001,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1" | ||||||
|  |        radius="0" | ||||||
|  |        unit="px" | ||||||
|  |        method="auto" | ||||||
|  |        mode="F" | ||||||
|  |        chamfer_steps="1" | ||||||
|  |        flexible="false" | ||||||
|  |        use_knot_distance="true" | ||||||
|  |        apply_no_radius="true" | ||||||
|  |        apply_with_radius="true" | ||||||
|  |        only_selected="false" | ||||||
|  |        hide_knots="false" /> | ||||||
|  |   </defs> | ||||||
|  |   <g | ||||||
|  |      inkscape:label="Calque 1" | ||||||
|  |      inkscape:groupmode="layer" | ||||||
|  |      id="layer1"> | ||||||
|  |     <g | ||||||
|  |        id="g14" | ||||||
|  |        transform="matrix(1.12,0,0,1.12,-6.6400002,3.1600025)"> | ||||||
|  |       <path | ||||||
|  |          id="path13" | ||||||
|  |          style="fill:none;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |          d="m 38,43.499998 -11,-21 m 0,0 -9,20 M 50,32.749996 38,43.499998 M 53,16.749997 50,32.749996 M 40.000001,7.9999998 27,22.499998 M 16,7.9999998 27,22.499998" | ||||||
|  |          sodipodi:nodetypes="cccccccccccc" /> | ||||||
|  |       <g | ||||||
|  |          id="g13"> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5" | ||||||
|  |            cx="16" | ||||||
|  |            cy="8" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-3" | ||||||
|  |            cx="40" | ||||||
|  |            cy="7.9999995" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-1" | ||||||
|  |            cx="27" | ||||||
|  |            cy="22.499998" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-6" | ||||||
|  |            cx="38" | ||||||
|  |            cy="43.499996" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-18" | ||||||
|  |            cx="18" | ||||||
|  |            cy="42.499996" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-2" | ||||||
|  |            cx="50" | ||||||
|  |            cy="32.749996" | ||||||
|  |            r="3" /> | ||||||
|  |         <circle | ||||||
|  |            style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" | ||||||
|  |            id="path5-22" | ||||||
|  |            cx="53" | ||||||
|  |            cy="16.749996" | ||||||
|  |            r="3" /> | ||||||
|  |       </g> | ||||||
|  |       <g | ||||||
|  |          id="g5" | ||||||
|  |          inkscape:label="car" | ||||||
|  |          transform="matrix(0.1163734,0.24290774,-0.24290774,0.1163734,38.296019,19.616451)" | ||||||
|  |          style="display:inline"> | ||||||
|  |         <g | ||||||
|  |            id="g4" | ||||||
|  |            inkscape:label="wheels"> | ||||||
|  |           <path | ||||||
|  |              style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |              d="m 25.000001,31.999999 v -2 h 4 v 2 z" | ||||||
|  |              id="path2" | ||||||
|  |              sodipodi:nodetypes="ccccc" /> | ||||||
|  |           <path | ||||||
|  |              style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |              d="m 43.000001,31.999999 v -2 h 4 v 2 z" | ||||||
|  |              id="path2-3" | ||||||
|  |              sodipodi:nodetypes="ccccc" /> | ||||||
|  |           <path | ||||||
|  |              style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |              d="m 25.000001,49.999999 v -2 h 4 v 2 z" | ||||||
|  |              id="path2-1" | ||||||
|  |              sodipodi:nodetypes="ccccc" /> | ||||||
|  |           <path | ||||||
|  |              style="fill:#000000;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |              d="m 43.000001,49.999999 v -2 h 4 v 2 z" | ||||||
|  |              id="path2-3-2" | ||||||
|  |              sodipodi:nodetypes="ccccc" /> | ||||||
|  |         </g> | ||||||
|  |         <path | ||||||
|  |            style="fill:#e14324;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 16,33 v 13.999999 a 1.1327823,1.1327823 48.562508 0 0 0.992278,1.124035 l 7.007723,0.875965 h 24 l 11.003454,-0.916955 a 1.0867997,1.0867997 132.61818 0 0 0.996546,-1.083045 v -14 A 1.0867996,1.0867996 47.381818 0 0 59.003455,31.916954 L 48.000001,31 h -24 l -7.007723,0.875965 A 1.1327823,1.1327823 131.43749 0 0 16,33 Z" | ||||||
|  |            id="path1" | ||||||
|  |            inkscape:path-effect="#path-effect2" | ||||||
|  |            inkscape:original-d="m 16,32 v 15.999999 l 8.000001,1 h 24 l 12,-1 v -16 L 48.000001,31 h -24 z" | ||||||
|  |            inkscape:label="body" /> | ||||||
|  |         <path | ||||||
|  |            style="fill:#53170b;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 50.000001,33.500001 v 13 a 1.0867994,1.0867994 132.61819 0 1 -0.996546,1.083045 l -4.006908,0.333908 A 0.92013337,0.92013337 42.618189 0 1 44.000001,46.999999 V 33 a 0.92013291,0.92013291 137.38183 0 1 0.996546,-0.916954 l 4.006908,0.333909 a 1.0867999,1.0867999 47.381826 0 1 0.996546,1.083046 z" | ||||||
|  |            id="path3" | ||||||
|  |            inkscape:path-effect="#path-effect3" | ||||||
|  |            inkscape:original-d="m 50.000001,32.500001 v 15 l -6,0.499998 V 32 Z" | ||||||
|  |            sodipodi:nodetypes="ccccc" | ||||||
|  |            inkscape:label="windshield" /> | ||||||
|  |         <path | ||||||
|  |            style="fill:#af3116;fill-opacity:1;stroke-linecap:round;stroke-linejoin:round" | ||||||
|  |            d="m 29.000001,46.999999 c -4,0 -8.000001,0 -11.000001,-1 v -12 c 3,-1 7.000001,-1 11.000001,-1 z" | ||||||
|  |            id="path4" | ||||||
|  |            sodipodi:nodetypes="ccccc" | ||||||
|  |            inkscape:label="back_window" /> | ||||||
|  |       </g> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 7.5 KiB | 
| @@ -1,3 +1,4 @@ | |||||||
|  | import lzma | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| import struct | import struct | ||||||
| import time | import time | ||||||
| @@ -12,7 +13,7 @@ class RecordFile: | |||||||
|     def __init__(self, path: str | Path, mode: Literal["w", "r"]) -> None: |     def __init__(self, path: str | Path, mode: Literal["w", "r"]) -> None: | ||||||
|         self.path: str | Path = path |         self.path: str | Path = path | ||||||
|         self.mode: Literal["w", "r"] = mode |         self.mode: Literal["w", "r"] = mode | ||||||
|         self.file = open(self.path, self.mode + "b") |         self.file: lzma.LZMAFile = lzma.LZMAFile(self.path, self.mode) | ||||||
|  |  | ||||||
|     def __enter__(self): |     def __enter__(self): | ||||||
|         return self |         return self | ||||||
| @@ -21,8 +22,7 @@ class RecordFile: | |||||||
|         self.file.close() |         self.file.close() | ||||||
|  |  | ||||||
|     def write_header(self, n_snapshots: int): |     def write_header(self, n_snapshots: int): | ||||||
|         data: bytes = struct.pack( |         data: bytes = struct.pack(">IId", self.VERSION, n_snapshots, time.time()) | ||||||
|             ">IId", self.VERSION, n_snapshots, time.time()) |  | ||||||
|         self.file.write(data) |         self.file.write(data) | ||||||
|  |  | ||||||
|     def write_snapshots(self, snapshots: list[Snapshot]): |     def write_snapshots(self, snapshots: list[Snapshot]): | ||||||
| @@ -35,7 +35,8 @@ class RecordFile: | |||||||
|         version: int = struct.unpack(">I", self.file.read(4))[0] |         version: int = struct.unpack(">I", self.file.read(4))[0] | ||||||
|         if version != self.VERSION: |         if version != self.VERSION: | ||||||
|             raise ValueError( |             raise ValueError( | ||||||
|                 f"Cannot parse record file with format version {version} (current version: {self.VERSION})") |                 f"Cannot parse record file with format version {version} (current version: {self.VERSION})" | ||||||
|  |             ) | ||||||
|  |  | ||||||
|         n_snapshots: int |         n_snapshots: int | ||||||
|         timestamp: float |         timestamp: float | ||||||
|   | |||||||
| @@ -243,7 +243,7 @@ class RecorderWindow(Ui_Recorder, QMainWindow): | |||||||
|  |  | ||||||
|         self.SAVE_DIR.mkdir(exist_ok=True) |         self.SAVE_DIR.mkdir(exist_ok=True) | ||||||
|  |  | ||||||
|         record_name: str = "record_%d.rec" |         record_name: str = "record_%d.rec.xz" | ||||||
|         fid = 0 |         fid = 0 | ||||||
|         while os.path.exists(self.SAVE_DIR / (record_name % fid)): |         while os.path.exists(self.SAVE_DIR / (record_name % fid)): | ||||||
|             fid += 1 |             fid += 1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user