{"authorId":"","cover":"/content/images/2026/10/9e08d4941150-social-background.png","heroes":{"59ab1e54b3a5386e6900ca8678d4e839":"/content/images/2026/10/b1e12503f058-nullg-rl-full-preview.png","729c9a4edc92eaa4171ac274dda70ca2":"/content/images/2019/11/IMG_9531.JPG","72b96875d26f256ca5a8e7bea23a0319":"/content/images/2017/07/logo.png","7a23b4fc9f63f7327ef52913289d4327":"/content/images/2017/12/20171201-4K4X9516.jpg","7b367212a739706ba4e3e9b999bec15d":"/content/images/2026/10/5febc720f2c6-nullg-rl-hero.png","901f2fab2646e83671fe8f6e5500c117":"/content/images/2018/11/IMG_6734.jpg","94b2de371382ec793a64ed49343c14c6":"/content/images/2017/11/IMG_3194.JPG","bfd1ec8875b9ff5807a23c1e5275e668":"/content/images/2017/06/IMG_1248.jpg","e1df6d8cca38bcc838098d61f321952d":"/content/images/2017/11/IMG_3182.jpg"},"kind":"index","logo":"/content/images/2016/08/projectable-me-4.png","nav":[{"id":"62e854d471683dea63488bcbca5c6188","label":"Home","url":"/","sortOrder":0},{"id":"1bc84fb15620acd635df7735a0b8ddd8","label":"Projects","url":"/projects/","sortOrder":1},{"id":"3207e2fec51d66d2a5b3d8d04feb9dd8","label":"Sim Racing","url":"/tag/sim-racing/","sortOrder":2},{"id":"59115afd52e59a74faa4b386e00ae3fa","label":"About","url":"/about-me/","sortOrder":3}],"page":1,"perPage":10,"posts":[{"id":"59ab1e54b3a5386e6900ca8678d4e839","siteId":"projectable","slug":"nullg-reinforcement-learning-journey","title":"Teaching NullG to race: the reinforcement-learning journey so far","markdown":"[NullG](https://projectable.me/projects/nullg/) now has a reinforcement-learning pipeline that can train a pilot in the native racing simulation, export its learned controls into the game, and record complete races for review. The latest footage follows that work into weapon combat: preserving a learned driver while training decisions about when and how to use its inventory.\n\nGetting here has involved several changes of direction. Road observations, steering, rewards, exploration, Turbo handling and combat timing have each needed their own experiments. A useful race raises the next question: which part of the system produced that behaviour, and does it hold up on another circuit?\n\nThe [NullG YouTube playlist](https://www.youtube.com/playlist?list=PLaR-_mRLlb6E) follows the progression through recorded driving and combat runs. This post explains the engineering behind those videos, the external projects informing the approach, and the repeated work between longer training sessions.\n\n## A pilot that drives through the game’s controls\n\nNullG’s starting point is its own C++ racing simulation. Python training tools communicate with isolated native workers, each running a race with the engine’s physics, pickups, weapons and race rules. Gymnasium provides the environment interface, and PyTorch with [Stable-Baselines3 PPO](https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html) provides the main training implementation.\n\nA policy is the neural network that turns observations into controls. Its companion during training, the critic, estimates the return expected from a state. PPO collects experience with the current policy, then makes bounded updates to those networks. In NullG, that experience comes from the same native simulation used by gameplay.\n\nThe pilot receives structured observations: its motion and health, connected road geometry ahead, nearby racers, available pickups, visible projectiles, inventory and previous controls. This gives development direct access to questions such as how far the pilot can see into a corner and how it represents lateral movement across the road.\n\nThe outputs correspond to familiar inputs: throttle, analog steering, left and right airbrakes, pitch and weapon commands. Decisions arrive at 30 Hz through the normal player-input path, while the session advances at 60 Hz with the selected source physics cadence. Movement is held between decisions; weapon commands follow the engine’s input timing.\n\nOnce trained, the actor exports into a compact `.ngpolicy` package. A native C++ evaluator reads the observations and produces controls inside NullG. Python remains part of the development workflow, while the exported pilot runs in the engine. Package metadata records the observation contract, model identity and supported configuration, making the training-to-game handoff inspectable.\n\n![](/content/images/2026/10/b1b8220f350c-nullg-rl-full-title-preview.png)\n\n*The latest recorded evaluation race, presented through NullG’s cinematic replay exporter. The driving policy and the replay camera are separate systems.*\n\n## External projects that shaped the approach\n\nRacing RL already has a substantial body of practical work. NullG uses those projects as references for particular engineering decisions, adapting the ideas to an anti-gravity racer and a native engine.\n\n[Sony AI’s Gran Turismo Sophy training account](https://ai.sony/blog/how-to-train-your-race-car) is a reference for building a varied training regimen. Solo driving, interaction with traffic and specialised situations each contribute useful experience. For NullG, that encourages deliberate coverage of circuits, traffic conditions and difficult states, with several kinds of practice available during development.\n\n[TMRL](https://github.com/trackmania-rl/tmrl), the TrackMania reinforcement-learning framework, is useful for its treatment of real-time control, observation histories, analog actions and off-policy learning. It helped motivate a controlled SAC steering comparison alongside PPO. NullG’s native worker supplies a different integration path, while the timing and control questions transfer well.\n\n[Linesight](https://linesight-rl.github.io/linesight/build/html/main_objects.html) provides another TrackMania reference, including its IQN-based approach and explicit reference-line geometry. Its value here is the care given to defining progress and training coverage. [Learn-to-Race](https://github.com/learn-to-race/l2r) adds a useful autonomous-racing environment and baseline perspective: conventional and learned controllers can be compared through a clearly defined task.\n\n[CAPS](https://ai.bu.edu/caps/) informs the smooth-control studies. Action variation and the frequency content of motion provide ways to examine steering quality. That sits alongside a separate question about exploration: the sampled actions used while learning and the deterministic controls used by an exported actor can behave differently.\n\n[NeuralKart](https://github.com/rameshvarun/NeuralKart) supplies a practical reference for searching for useful driving actions and learning from them. NullG adapts that principle using native snapshots from states reached by its own learner. [DAgger](https://proceedings.mlr.press/v15/ross11a.html) gives the broader rationale for collecting corrective examples where the learner actually drives, as successive actions change the states it encounters.\n\nThese references contribute different pieces: curriculum design, control timing, progress geometry, smoothness, baseline comparisons and corrective data collection. NullG combines them with its existing simulation, input and replay systems.\n\n## Giving the driver useful information\n\nEarly work established the loop from observation to action, followed by closer examination of what the network was actually receiving. That led to an audit of observation scaling, feature connectivity, road preview and the steering adapter.\n\nScaling deserves attention because a number can be technically present yet convey very little useful variation after normalisation and clipping. The corrected foundation uses explicit physical scales and identity normalisation for its observation contract. Checks also trace new features through to the network inputs, so a change to the observation layout has a verifiable effect on the model being trained.\n\nRoad guidance then became more explicit. The pilot receives road-forward directions, heading error, longitudinal and lateral velocity, displacement across the road, curvature and available clearance. Connected-road projection gives those measurements a continuous position along the route, including the neighbourhood of section boundaries and qualified junctions.\n\nThat same care applies to progress rewards. Canonical road distance and high-water accounting make forward progress meaningful across the track’s connected geometry. Pickups and boost pads have their own bounded contributions. A reward can then describe a useful driving objective with a clear relationship to what happened on the circuit.\n\nSteering also moved to a native analog contract, with 513 signed positions available through the XL input adapter. A controlled comparison could then ask about the observation design while holding the control protocol and experience budget steady. Another steering study compared PPO and SAC under the same restricted auxiliary controls. Those experiments narrowed individual design choices before the full driver took on more responsibilities.\n\n## The repeated work between longer runs\n\nThe development record across October 15–20 contains an ongoing cycle of collecting races, reviewing telemetry, making a focused adjustment, and testing the resulting policy again. This has occupied a substantial part of the RL work alongside the training itself.\n\nSeveral strategies needed revisiting. Increasing a steering-change penalty could make sampled inputs look quieter, so review expanded to the policy’s mean output and the ship’s actual heading and lateral motion. Longer road preview and different brake commitment were tested separately. Exploration settings were examined alongside deterministic native inference, giving both the training behaviour and the exported driver a direct comparison.\n\nTurbo made preservation especially important. A steering change affects the trajectory from which Turbo is used, even when the weapon-control weights stay identical. Naturally earned Turbo states therefore became part of the review panels and corrective training anchors. Useful speed, health, recovery and the rest of the race all contribute to judging the manoeuvre.\n\nThe corrective-driving work took another route. Native snapshots preserve a state reached by the learner, then development tooling tries small steering interventions from that same state. Accepted examples become training labels, with unchanged actions retained as anchors. Focused work on Gare d’Europa and Odessa Keys added longer follow-through checks and preservation samples from the other circuits.\n\nEach revision brought additional work around the optimiser: reconstructing states, verifying the replayed baseline, collecting examples, fitting a bounded update, exporting the actor and running complete races. Longer safety follow-through was added to examine the consequences beyond a promising short steering branch.\n\nThe time involved can be described concretely from the run receipts. Three completed combat jobs alone—the eight-hour run on October 18, the four-hour run on October 19, and the latest four-hour continuation—account for **more than 16 hours of training wall time**. Short comparison arms, earlier driving work, evaluation races, corrective searches and media production add to that. Those three jobs branch from selected earlier checkpoints, so their durations describe compute spent across experiments rather than sixteen uninterrupted hours on one policy.\n\nThe records establish those training durations. Reading references, inspecting footage and revising the tools also take development time; that human work has no consolidated hour counter in the run receipts. The visible pattern is a sequence of experiments and adjustments over several days, with longer jobs following more focused checks.\n\n## From driving practice to racing and combat\n\nThe driving foundation gave the pilot room to practise navigation, traffic, pickups and earned Turbo. Combat then introduced a different timing problem: choosing an action now can affect another racer several seconds later, and that exchange can change the final placing.\n\nThe approach evolved toward training the weapon outputs and critic while freezing the actor’s driving features and movement outputs. That lets the combat experiment build on an existing driver. Weight checks verify the protected parameters, while complete races show how the new combat choices affect the resulting trajectories.\n\nThe objective also became explicitly placement-first. Race outcome has the dominant reward, with bounded auxiliary credit for effective combat and useful pickups or pads. Shot count by itself receives no bonus. The critic and credit-assignment settings then become important parts of learning when a weapon opportunity is worth taking.\n\nExperiments examined longer credit assignment, combat reward weighting and critic calibration. Calibration fits the value estimate to returns collected from the retained policy, while preserving the actor. Opportunity starts reconstruct naturally reached situations with offensive inventory and nearby opponents, giving the learner more practice around decisions that may be relatively sparse in ordinary races.\n\nThe latest configuration combines ordinary races with ten-second combat opportunity windows. These windows start from verified native states and collect fresh actions from the current policy. Their training cutoff is handled separately from a race finish or elimination, preserving the meaning of the full-race objective.\n\nTraining opposition has expanded too: original XL opponents, a retained learned challenger, and mixed fields provide different contexts. The active development rotation is Talon’s Reach, Sagarmatha, Gare d’Europa and Odessa Keys.\n\n## What the latest four-hour continuation did\n\nThe latest completed continuation began at the earlier combat run’s hour-two checkpoint. Four CPU workers added **6,639,616 decisions**, moving the checkpoint counter from **32,651,264 to 39,290,880**. That number belongs to this checkpoint lineage; it is separate from the experience collected across all the other experiments.\n\nThe run preserved the driving parameters and continued learning weapon outputs and the critic. Its recorded settings retained a placement-first objective, gamma 1.0, GAE lambda 0.95, combat reward scale 1.0 and 300-decision opportunity windows. In practical terms, the experiment concentrated on combat choices while retaining the driver’s learned control function.\n\nHourly checkpoints made it possible to compare behaviour during the continuation. The subsequent review covered six policies, with 48 standard evaluation races per policy and additional cross-play and confirmation panels. [RLiable’s evaluation guidance](https://research.google/blog/rliable-towards-reliable-evaluation-reporting-in-reinforcement-learning/) informs this emphasis on paired conditions, multiple seeds and the distribution of results.\n\nThe final checkpoint won 18 of its 48 standard-panel races and finished 31. In the additional 24-race confirmation panel, it won 9 and finished 15. Different intermediate checkpoints had different strengths, so the review retains those trade-offs for the next decision. A cinematic race shows the driving and combat in detail; the larger panels establish the context for interpreting it.\n\n![](/content/images/2026/10/b1e12503f058-nullg-rl-full-preview.png)\n\n*Recorded Gare d’Europa gameplay from the final checkpoint. The cinematic director follows racing interest and weapon exchanges across the field, including opponents as well as the learned racer.*\n\n## Watch the latest races\n\nThe videos make the development easier to follow alongside the technical account. Earlier driving updates show the broader training progression; the latest full race and Short focus on racing with weapons. The learned pilot occupies slot 0 in the latest full race, while automatic cinematic cameras also cover other racers and exchanges.\n\n### Learning to fight: the complete Gare d’Europa race\n\nThis complete three-lap race comes from the final checkpoint of the latest four-hour continuation. It runs for approximately three minutes, with native race audio and cinematic presentation.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/__kpDHYbsCg\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n[Watch the full Gare d’Europa race on YouTube](https://youtu.be/__kpDHYbsCg).\n\n### Learning to race and fight: the Short\n\nThe latest Short offers a compact look at the racing and combat work.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/lTbLUj1QKt4\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n[Watch the racing and combat on YouTube](https://youtu.be/lTbLUj1QKt4).\n\n### Earlier training footage: update 3\n\nThis earlier upload is titled “NullG - 8 hour AI driving training 3 (reinforcement learning)” and forms part of the playlist’s training record.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/fkUTwW2p_8k\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n[Watch training update 3 on YouTube](https://youtu.be/fkUTwW2p_8k).\n\n### Earlier training footage: update 2\n\nThe preceding “NullG - 8 hour AI driving training 2 (reinforcement learning)” upload provides another point in that recorded progression.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/9ddeaoyyIY4\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n[Watch training update 2 on YouTube](https://youtu.be/9ddeaoyyIY4).\n\n## Following the next experiments\n\nThe work now has a native training loop, portable in-game policies, corrective driving tools, combat-focused continuations and recorded evaluations to guide further changes. The next direction is to build on the checkpoint comparisons: keep race outcome central, improve the usefulness of weapon decisions, and preserve driving quality across the four-circuit rotation.\n\nThe [reinforcement-learning project page](https://projectable.me/projects/nullg/reinforcement-learning/) describes the engine integration. The [YouTube playlist](https://www.youtube.com/playlist?list=PLaR-_mRLlb6E) follows the training through the races themselves, with the full recordings providing context for each shorter highlight.","html":"\u003cp\u003e\u003ca href=\"https://projectable.me/projects/nullg/\" rel=\"nofollow\"\u003eNullG\u003c/a\u003e now has a reinforcement-learning pipeline that can train a pilot in the native racing simulation, export its learned controls into the game, and record complete races for review. The latest footage follows that work into weapon combat: preserving a learned driver while training decisions about when and how to use its inventory.\u003c/p\u003e\n\u003cp\u003eGetting here has involved several changes of direction. Road observations, steering, rewards, exploration, Turbo handling and combat timing have each needed their own experiments. A useful race raises the next question: which part of the system produced that behaviour, and does it hold up on another circuit?\u003c/p\u003e\n\u003cp\u003eThe \u003ca href=\"https://www.youtube.com/playlist?list=PLaR-_mRLlb6E\" rel=\"nofollow\"\u003eNullG YouTube playlist\u003c/a\u003e follows the progression through recorded driving and combat runs. This post explains the engineering behind those videos, the external projects informing the approach, and the repeated work between longer training sessions.\u003c/p\u003e\n\u003ch2\u003eA pilot that drives through the game’s controls\u003c/h2\u003e\n\u003cp\u003eNullG’s starting point is its own C++ racing simulation. Python training tools communicate with isolated native workers, each running a race with the engine’s physics, pickups, weapons and race rules. Gymnasium provides the environment interface, and PyTorch with \u003ca href=\"https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html\" rel=\"nofollow\"\u003eStable-Baselines3 PPO\u003c/a\u003e provides the main training implementation.\u003c/p\u003e\n\u003cp\u003eA policy is the neural network that turns observations into controls. Its companion during training, the critic, estimates the return expected from a state. PPO collects experience with the current policy, then makes bounded updates to those networks. In NullG, that experience comes from the same native simulation used by gameplay.\u003c/p\u003e\n\u003cp\u003eThe pilot receives structured observations: its motion and health, connected road geometry ahead, nearby racers, available pickups, visible projectiles, inventory and previous controls. This gives development direct access to questions such as how far the pilot can see into a corner and how it represents lateral movement across the road.\u003c/p\u003e\n\u003cp\u003eThe outputs correspond to familiar inputs: throttle, analog steering, left and right airbrakes, pitch and weapon commands. Decisions arrive at 30 Hz through the normal player-input path, while the session advances at 60 Hz with the selected source physics cadence. Movement is held between decisions; weapon commands follow the engine’s input timing.\u003c/p\u003e\n\u003cp\u003eOnce trained, the actor exports into a compact \u003ccode\u003e.ngpolicy\u003c/code\u003e package. A native C++ evaluator reads the observations and produces controls inside NullG. Python remains part of the development workflow, while the exported pilot runs in the engine. Package metadata records the observation contract, model identity and supported configuration, making the training-to-game handoff inspectable.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/b1b8220f350c-nullg-rl-full-title-preview.png\" alt=\"\"\u003e\n\u003cp\u003e\u003cem\u003eThe latest recorded evaluation race, presented through NullG’s cinematic replay exporter. The driving policy and the replay camera are separate systems.\u003c/em\u003e\u003c/p\u003e\n\u003ch2\u003eExternal projects that shaped the approach\u003c/h2\u003e\n\u003cp\u003eRacing RL already has a substantial body of practical work. NullG uses those projects as references for particular engineering decisions, adapting the ideas to an anti-gravity racer and a native engine.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://ai.sony/blog/how-to-train-your-race-car\" rel=\"nofollow\"\u003eSony AI’s Gran Turismo Sophy training account\u003c/a\u003e is a reference for building a varied training regimen. Solo driving, interaction with traffic and specialised situations each contribute useful experience. For NullG, that encourages deliberate coverage of circuits, traffic conditions and difficult states, with several kinds of practice available during development.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/trackmania-rl/tmrl\" rel=\"nofollow\"\u003eTMRL\u003c/a\u003e, the TrackMania reinforcement-learning framework, is useful for its treatment of real-time control, observation histories, analog actions and off-policy learning. It helped motivate a controlled SAC steering comparison alongside PPO. NullG’s native worker supplies a different integration path, while the timing and control questions transfer well.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://linesight-rl.github.io/linesight/build/html/main_objects.html\" rel=\"nofollow\"\u003eLinesight\u003c/a\u003e provides another TrackMania reference, including its IQN-based approach and explicit reference-line geometry. Its value here is the care given to defining progress and training coverage. \u003ca href=\"https://github.com/learn-to-race/l2r\" rel=\"nofollow\"\u003eLearn-to-Race\u003c/a\u003e adds a useful autonomous-racing environment and baseline perspective: conventional and learned controllers can be compared through a clearly defined task.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://ai.bu.edu/caps/\" rel=\"nofollow\"\u003eCAPS\u003c/a\u003e informs the smooth-control studies. Action variation and the frequency content of motion provide ways to examine steering quality. That sits alongside a separate question about exploration: the sampled actions used while learning and the deterministic controls used by an exported actor can behave differently.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/rameshvarun/NeuralKart\" rel=\"nofollow\"\u003eNeuralKart\u003c/a\u003e supplies a practical reference for searching for useful driving actions and learning from them. NullG adapts that principle using native snapshots from states reached by its own learner. \u003ca href=\"https://proceedings.mlr.press/v15/ross11a.html\" rel=\"nofollow\"\u003eDAgger\u003c/a\u003e gives the broader rationale for collecting corrective examples where the learner actually drives, as successive actions change the states it encounters.\u003c/p\u003e\n\u003cp\u003eThese references contribute different pieces: curriculum design, control timing, progress geometry, smoothness, baseline comparisons and corrective data collection. NullG combines them with its existing simulation, input and replay systems.\u003c/p\u003e\n\u003ch2\u003eGiving the driver useful information\u003c/h2\u003e\n\u003cp\u003eEarly work established the loop from observation to action, followed by closer examination of what the network was actually receiving. That led to an audit of observation scaling, feature connectivity, road preview and the steering adapter.\u003c/p\u003e\n\u003cp\u003eScaling deserves attention because a number can be technically present yet convey very little useful variation after normalisation and clipping. The corrected foundation uses explicit physical scales and identity normalisation for its observation contract. Checks also trace new features through to the network inputs, so a change to the observation layout has a verifiable effect on the model being trained.\u003c/p\u003e\n\u003cp\u003eRoad guidance then became more explicit. The pilot receives road-forward directions, heading error, longitudinal and lateral velocity, displacement across the road, curvature and available clearance. Connected-road projection gives those measurements a continuous position along the route, including the neighbourhood of section boundaries and qualified junctions.\u003c/p\u003e\n\u003cp\u003eThat same care applies to progress rewards. Canonical road distance and high-water accounting make forward progress meaningful across the track’s connected geometry. Pickups and boost pads have their own bounded contributions. A reward can then describe a useful driving objective with a clear relationship to what happened on the circuit.\u003c/p\u003e\n\u003cp\u003eSteering also moved to a native analog contract, with 513 signed positions available through the XL input adapter. A controlled comparison could then ask about the observation design while holding the control protocol and experience budget steady. Another steering study compared PPO and SAC under the same restricted auxiliary controls. Those experiments narrowed individual design choices before the full driver took on more responsibilities.\u003c/p\u003e\n\u003ch2\u003eThe repeated work between longer runs\u003c/h2\u003e\n\u003cp\u003eThe development record across October 15–20 contains an ongoing cycle of collecting races, reviewing telemetry, making a focused adjustment, and testing the resulting policy again. This has occupied a substantial part of the RL work alongside the training itself.\u003c/p\u003e\n\u003cp\u003eSeveral strategies needed revisiting. Increasing a steering-change penalty could make sampled inputs look quieter, so review expanded to the policy’s mean output and the ship’s actual heading and lateral motion. Longer road preview and different brake commitment were tested separately. Exploration settings were examined alongside deterministic native inference, giving both the training behaviour and the exported driver a direct comparison.\u003c/p\u003e\n\u003cp\u003eTurbo made preservation especially important. A steering change affects the trajectory from which Turbo is used, even when the weapon-control weights stay identical. Naturally earned Turbo states therefore became part of the review panels and corrective training anchors. Useful speed, health, recovery and the rest of the race all contribute to judging the manoeuvre.\u003c/p\u003e\n\u003cp\u003eThe corrective-driving work took another route. Native snapshots preserve a state reached by the learner, then development tooling tries small steering interventions from that same state. Accepted examples become training labels, with unchanged actions retained as anchors. Focused work on Gare d’Europa and Odessa Keys added longer follow-through checks and preservation samples from the other circuits.\u003c/p\u003e\n\u003cp\u003eEach revision brought additional work around the optimiser: reconstructing states, verifying the replayed baseline, collecting examples, fitting a bounded update, exporting the actor and running complete races. Longer safety follow-through was added to examine the consequences beyond a promising short steering branch.\u003c/p\u003e\n\u003cp\u003eThe time involved can be described concretely from the run receipts. Three completed combat jobs alone—the eight-hour run on October 18, the four-hour run on October 19, and the latest four-hour continuation—account for \u003cstrong\u003emore than 16 hours of training wall time\u003c/strong\u003e. Short comparison arms, earlier driving work, evaluation races, corrective searches and media production add to that. Those three jobs branch from selected earlier checkpoints, so their durations describe compute spent across experiments rather than sixteen uninterrupted hours on one policy.\u003c/p\u003e\n\u003cp\u003eThe records establish those training durations. Reading references, inspecting footage and revising the tools also take development time; that human work has no consolidated hour counter in the run receipts. The visible pattern is a sequence of experiments and adjustments over several days, with longer jobs following more focused checks.\u003c/p\u003e\n\u003ch2\u003eFrom driving practice to racing and combat\u003c/h2\u003e\n\u003cp\u003eThe driving foundation gave the pilot room to practise navigation, traffic, pickups and earned Turbo. Combat then introduced a different timing problem: choosing an action now can affect another racer several seconds later, and that exchange can change the final placing.\u003c/p\u003e\n\u003cp\u003eThe approach evolved toward training the weapon outputs and critic while freezing the actor’s driving features and movement outputs. That lets the combat experiment build on an existing driver. Weight checks verify the protected parameters, while complete races show how the new combat choices affect the resulting trajectories.\u003c/p\u003e\n\u003cp\u003eThe objective also became explicitly placement-first. Race outcome has the dominant reward, with bounded auxiliary credit for effective combat and useful pickups or pads. Shot count by itself receives no bonus. The critic and credit-assignment settings then become important parts of learning when a weapon opportunity is worth taking.\u003c/p\u003e\n\u003cp\u003eExperiments examined longer credit assignment, combat reward weighting and critic calibration. Calibration fits the value estimate to returns collected from the retained policy, while preserving the actor. Opportunity starts reconstruct naturally reached situations with offensive inventory and nearby opponents, giving the learner more practice around decisions that may be relatively sparse in ordinary races.\u003c/p\u003e\n\u003cp\u003eThe latest configuration combines ordinary races with ten-second combat opportunity windows. These windows start from verified native states and collect fresh actions from the current policy. Their training cutoff is handled separately from a race finish or elimination, preserving the meaning of the full-race objective.\u003c/p\u003e\n\u003cp\u003eTraining opposition has expanded too: original XL opponents, a retained learned challenger, and mixed fields provide different contexts. The active development rotation is Talon’s Reach, Sagarmatha, Gare d’Europa and Odessa Keys.\u003c/p\u003e\n\u003ch2\u003eWhat the latest four-hour continuation did\u003c/h2\u003e\n\u003cp\u003eThe latest completed continuation began at the earlier combat run’s hour-two checkpoint. Four CPU workers added \u003cstrong\u003e6,639,616 decisions\u003c/strong\u003e, moving the checkpoint counter from \u003cstrong\u003e32,651,264 to 39,290,880\u003c/strong\u003e. That number belongs to this checkpoint lineage; it is separate from the experience collected across all the other experiments.\u003c/p\u003e\n\u003cp\u003eThe run preserved the driving parameters and continued learning weapon outputs and the critic. Its recorded settings retained a placement-first objective, gamma 1.0, GAE lambda 0.95, combat reward scale 1.0 and 300-decision opportunity windows. In practical terms, the experiment concentrated on combat choices while retaining the driver’s learned control function.\u003c/p\u003e\n\u003cp\u003eHourly checkpoints made it possible to compare behaviour during the continuation. The subsequent review covered six policies, with 48 standard evaluation races per policy and additional cross-play and confirmation panels. \u003ca href=\"https://research.google/blog/rliable-towards-reliable-evaluation-reporting-in-reinforcement-learning/\" rel=\"nofollow\"\u003eRLiable’s evaluation guidance\u003c/a\u003e informs this emphasis on paired conditions, multiple seeds and the distribution of results.\u003c/p\u003e\n\u003cp\u003eThe final checkpoint won 18 of its 48 standard-panel races and finished 31. In the additional 24-race confirmation panel, it won 9 and finished 15. Different intermediate checkpoints had different strengths, so the review retains those trade-offs for the next decision. A cinematic race shows the driving and combat in detail; the larger panels establish the context for interpreting it.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/b1e12503f058-nullg-rl-full-preview.png\" alt=\"\"\u003e\n\u003cp\u003e\u003cem\u003eRecorded Gare d’Europa gameplay from the final checkpoint. The cinematic director follows racing interest and weapon exchanges across the field, including opponents as well as the learned racer.\u003c/em\u003e\u003c/p\u003e\n\u003ch2\u003eWatch the latest races\u003c/h2\u003e\n\u003cp\u003eThe videos make the development easier to follow alongside the technical account. Earlier driving updates show the broader training progression; the latest full race and Short focus on racing with weapons. The learned pilot occupies slot 0 in the latest full race, while automatic cinematic cameras also cover other racers and exchanges.\u003c/p\u003e\n\u003ch3\u003eLearning to fight: the complete Gare d’Europa race\u003c/h3\u003e\n\u003cp\u003eThis complete three-lap race comes from the final checkpoint of the latest four-hour continuation. It runs for approximately three minutes, with native race audio and cinematic presentation.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/__kpDHYbsCg\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003ca href=\"https://youtu.be/__kpDHYbsCg\" rel=\"nofollow\"\u003eWatch the full Gare d’Europa race on YouTube\u003c/a\u003e.\u003c/p\u003e\n\u003ch3\u003eLearning to race and fight: the Short\u003c/h3\u003e\n\u003cp\u003eThe latest Short offers a compact look at the racing and combat work.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/lTbLUj1QKt4\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003ca href=\"https://youtu.be/lTbLUj1QKt4\" rel=\"nofollow\"\u003eWatch the racing and combat on YouTube\u003c/a\u003e.\u003c/p\u003e\n\u003ch3\u003eEarlier training footage: update 3\u003c/h3\u003e\n\u003cp\u003eThis earlier upload is titled “NullG - 8 hour AI driving training 3 (reinforcement learning)” and forms part of the playlist’s training record.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/fkUTwW2p_8k\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003ca href=\"https://youtu.be/fkUTwW2p_8k\" rel=\"nofollow\"\u003eWatch training update 3 on YouTube\u003c/a\u003e.\u003c/p\u003e\n\u003ch3\u003eEarlier training footage: update 2\u003c/h3\u003e\n\u003cp\u003eThe preceding “NullG - 8 hour AI driving training 2 (reinforcement learning)” upload provides another point in that recorded progression.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/9ddeaoyyIY4\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003ca href=\"https://youtu.be/9ddeaoyyIY4\" rel=\"nofollow\"\u003eWatch training update 2 on YouTube\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003eFollowing the next experiments\u003c/h2\u003e\n\u003cp\u003eThe work now has a native training loop, portable in-game policies, corrective driving tools, combat-focused continuations and recorded evaluations to guide further changes. The next direction is to build on the checkpoint comparisons: keep race outcome central, improve the usefulness of weapon decisions, and preserve driving quality across the four-circuit rotation.\u003c/p\u003e\n\u003cp\u003eThe \u003ca href=\"https://projectable.me/projects/nullg/reinforcement-learning/\" rel=\"nofollow\"\u003ereinforcement-learning project page\u003c/a\u003e describes the engine integration. The \u003ca href=\"https://www.youtube.com/playlist?list=PLaR-_mRLlb6E\" rel=\"nofollow\"\u003eYouTube playlist\u003c/a\u003e follows the training through the races themselves, with the full recordings providing context for each shorter highlight.\u003c/p\u003e\n","excerpt":"From native driving controls and road guidance to Turbo preservation and weapon combat: the experiments, references and repeated adjustments behind NullG’s learning pilots.","metaTitle":"NullG’s reinforcement-learning journey: driving, Turbo and combat","metaDescription":"Explore NullG’s native racing RL pipeline, external research references, strategy revisions and latest training videos, from analog steering to combat.","status":"published","featured":false,"publishedAt":"2026-10-20T13:21:42Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"2de6b37e96d56188d9b74019123198cd","projectId":"ae4bdb66da6dc1729a263a475e1cdbe3","tags":[{"id":"10a974c0a281d4fcf3d44f5ef8dae079","name":"NullG","slug":"nullg"},{"id":"1c9e8a1339a8f8b797767e91a9673016","name":"Game","slug":"game"},{"id":"60103f47eb65b46c6138b9d6fc7b17d0","name":"Machine Learning","slug":"machine-learning"}],"createdAt":"2026-10-20T13:10:40Z","updatedAt":"2026-10-20T15:07:55Z"},{"id":"7b367212a739706ba4e3e9b999bec15d","siteId":"projectable","slug":"introducing-nullg-anti-gravity-racing-and-ai","title":"Introducing NullG: anti-gravity racing and AI-assisted development","markdown":"[NullG](https://projectable.me/projects/nullg/) is an anti-gravity racing engine built in C++20 with Vulkan for rendering. It combines legacy game asset imports with racing physics, weapons, multiplayer, and tools for testing and capturing gameplay.\n\nThe longer-term goal is a motion simulator pod, with acceleration, braking, cornering, and impacts feeding into physical movement. Positional audio and multiple displays are part of that plan too. Earlier projects such as the [Car-cade](https://projectable.me/my-dirt-rally-tabletop-car-cade-game/) and [motion rig](https://projectable.me/sim-racing-motion-rig-v2-updates/) explored racing through custom hardware. NullG takes that work into the game engine.\n\nDevelopment started in January 2026 with AI-assisted planning and implementation. Over the following months, the work expanded into asset loading, rendering, physics, and automated tests. October added more direct access for agents to inspect the engine, run controlled scenarios, and review the results.\n\n![Original NullG ship artwork](/content/images/2026/10/583bdbe059a6-ship.png)\n\n*Original NullG ship artwork.*\n\n## January: plans and the first renderer\n\nThe first git commit, dated January 22, 2026, contains the project outline, research files, architecture notes, and initial application code. The plans already covered asset conversion, input, audio, networking, computer-controlled opponents, and motion output. The application had a window, Vulkan setup, input handling, configuration, and logging.\n\nThe architecture put the race simulation at the center. Graphics and sound would use the state produced by the simulation, with motion hardware eventually reading the same data. This kept the simulator goal part of the engine design from the beginning.\n\nEarly development used Cursor, with project commands for planning, preparation, and review. The preparation step directed the agent to read reference material and trace the relevant code before making changes. Tasks were broken into smaller pieces, with examples and written decisions available for the next session.\n\n![G_jZiq3WQAAg2Cz.jpeg](/content/images/2026/10/037075fac8ed-G_jZiq3WQAAg2Cz.jpeg)\n\nJanuary 23 brought asset conversion tooling and the first renderer pass. Menus, model loading, asset management, and track parsing followed over the next few days. Existing WipEout research and community projects provided references for loading the ships, tracks, textures, and scenery.\n\n## February: loading the original assets\n\nBy February 8, the project had a direct PlayStation asset-loading checkpoint. Work during this period covered track rendering, scene objects, sprites, and texture transparency.\n\nLoading the geometry, textures, and scenery together made it possible to check the imported data in the renderer. File-format notes and agent rules developed alongside the loaders, giving later tasks a record of how the assets were organized and used.\n\n## March: handling, race flow, and weapons\n\nMarch focused more on how ships move around a track: hover height, coasting, weight, jumps, boost, recovery, and tunnel-wall collisions. Scene placement, sky textures, pickups, and boost pads also received attention, along with the camera moving through the track behind the menus.\n\nReal-time lighting, shadows, and GPU particles added to the presentation. By March 6, the code included race-session flow and a weapon system, handling the transition into a race and back to the menus.\n\nThese changes were developed as individual tasks using the relevant code and reference material. Code review and updated implementation notes kept the decisions available as the systems grew.\n\n## May: rendering and automated tests\n\nMay brought a larger pass through the engine internals. The original engine plan was split into focused documents with a shared status index, making individual areas easier to track.\n\nRenderer work included dynamic rendering, geometry access, material organization, and a move to Slang for runtime shaders. Lighting work covered animated scene lights, illuminated pickups, shields, and the shadows received by ships from surrounding scenery.\n\nAn entity/component scene system and render snapshots were added during the same period. A snapshot holds the scene data needed for a frame, including ship and object positions, giving the renderer a consistent set of data to draw.\n\nOn May 28, a headless test suite added checks for the job system, memory, and asset handling. Agents could run these tests after editing the code and inspect the results directly. This became the starting point for the more extensive inspection and gameplay tools added later.\n\n## June: collision, effects, and XL\n\nJune added Jolt collision integration and further GPU effects work. Research notes covered established techniques for effects, shadows, and physics, providing examples for subsequent implementation tasks.\n\nWipEout XL became the default asset source in a June 9 checkpoint. Source descriptors drove the menus, allowing the selected game's data to determine the available choices. Other changes covered waterfall texture scrolling and the starting-grid camera.\n\nBy this stage, the codebase covered rendering, asset loading, handling, race flow, weapons, collision, and tests. The next concentrated stretch of commits begins on October 9, with the existing agent guidance brought into Codex, engine-backed inspection tools, and a fixed 60 Hz racing setup. Multiplayer followed on October 10, then the XL reconstruction checkpoint on October 11.\n\n## October: giving agents access to the engine\n\nOctober also marked a decision to use OpenAI Codex exclusively for NullG's coding-agent work. The existing planning commands, project rules, and reference notes were carried over from Cursor, keeping the earlier work available as context. Development then focused more heavily on giving Codex access to the tools needed to inspect, test, and review changes.\n\nRecently watched YouTube videos about Blender MCP helped shape that approach. They showed how an agent could work directly with a scene and inspect the result. Those concepts were brought into NullG's model-authoring process and reinforced the value of connecting agents to the engine's own inspection tools.\n\nOctober's tooling work gave agents more ways to check their changes. [MCP, the Model Context Protocol](https://modelcontextprotocol.io/introduction), connects AI applications to external tools and data. NullG uses it to expose native inspection windows, track validators, model viewers, and controlled race sessions.\n\nAn agent can load a track, choose a camera, inspect geometry, and capture a frame. Model inspection provides access to materials, bounds, and different viewing angles. Test harnesses provide repeatable scenarios with known inputs.\n\n![NullG Track Validator showing track geometry, texture inspection, and timeline controls](/content/images/2026/10/nullg/intro-track-inspection.png)\n\n*The track inspector, with the track view, texture panel, and playback controls.*\n\nThe weapon harness opens a paused production race scene. An agent can deploy a weapon and advance the scene in controlled steps, inspecting a projectile, impact, or Quake effect at a specific point. Simulation state and rendered output can then be reviewed together.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/pbUzB3j74p8\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n*Reactive engine plumes viewed through the MCP harness.*\n\nPhysics tests compare movement with expected values, track checks inspect road geometry, and screenshots show the rendered result. Replaying the same inputs checks consistency across changes. Together, these tools let agents run a larger part of the validation process themselves, with reports and captures available for human review.\n\n![Ships racing with engine trails and a weapon effect in NullG](/content/images/2026/10/nullg/nullg-ships-weapon-action.png)\n\n### Working through a change\n\nA weapon-effect investigation starts with a specific scene and setup. The agent deploys the weapon, steps through the action, checks the state, and follows the code responsible for the effect. After an edit, it builds the affected code and repeats the scenario.\n\nSaved reports retain the inputs and settings. That allows the case to be repeated in another session or compared across versions. Visual review and gameplay testing provide additional checks on appearance and handling.\n\n![Diagram showing an agent connected through MCP to native inspection and headless validation tools](/content/images/2026/10/nullg/intro-agent-workflow.png)\n\n*The agent can run a test, open an inspector, and save the results for review.*\n\n## Reverse engineering WipEout XL\n\nThe October research also examined WipEout XL / 2097 behavior in more detail, including steering, weapon updates, starting positions, and animated objects.\n\n[REA, Reverse Engineer Anything](https://github.com/morluto/rea), formed part of the research setup. It connects agents with tools for investigating applications and binaries. The PlayStation XL executable decompilation used a PSX-aware Ghidra workflow, with scripts retaining instructions, references, annotations, and findings.\n\nThe starting grid provides a useful example. Following the original track numbering and route links established where ships should start. Those findings became checks against the imported track, with the inspector showing the selected position on the road.\n\n![An overhead track inspection with a highlighted grid marker](/content/images/2026/10/nullg/intro-grid-placement.png)\n\n*Checking a grid position against the track geometry.*\n\nThe research covers both USA and European editions. Each finding retains the edition and executable details so timing values and behavior can be traced to their source.\n\nRecovered calculations and state changes are implemented as small C++ reference models, tested, and then connected to NullG. The records distinguish behavior derived from the original executable, adaptations for NullG, and observations from running the engine.\n\nAgent access to analysis tools makes this kind of detailed investigation more accessible to individual developers. Existing products can be studied one behavior at a time, with findings carried into tests and new implementations. For NullG, that supports continued refinement of racing behavior alongside modern rendering, controls, and multiplayer. Imported content comes from user-supplied game files, while original NullG assets are developed separately.\n\n## A wider wave of software reconstruction\n\nREA's rapid rise in attention during early October put agent-assisted reverse engineering in front of a much larger audience. [Coverage of its growth](https://www.onfirstlaunch.com/blog/reverse-engineer-anything-rea-explained) described a surge in interest around demonstrations of agents inspecting applications and reconstructing their behavior.\n\nAt the same time, “vibe-coded” alternatives to familiar creative and office software were attracting attention. [ArtCraft's projects](https://github.com/storytold) include photo, video, and PDF tools, alongside [WordCraft](https://github.com/storytold/wordcraft), [GridCraft](https://github.com/storytold/gridcraft), and [DeckCraft](https://github.com/storytold/deckcraft), which target Word, Excel, and PowerPoint-style workflows. [October coverage](https://www.techradar.com/computing/office-suites/developer-who-vibe-coded-free-adobe-clones-reveals-apps-to-take-down-microsoft-office-next-and-says-there-is-no-reason-to-save-broken-software) connected these AI-assisted projects with the growing interest in alternatives to Adobe and Microsoft applications.\n\nThese are separate projects exploring related possibilities: using agents to understand software, implement familiar workflows, and build tools around specific needs. NullG applies that approach to racing. Executable research informs individual behaviors, while tests, inspectors, and recorded scenarios provide ways to check the implementation. The same emphasis on repeatable validation carries through asset production and gameplay development.\n\n## Blender and model production\n\nThe Blender MCP concepts from those videos were applied to a specific job: preparing original menu models for the engine. Scene access let the agent inspect parts, make scoped edits, export a candidate, and produce comparison views within the same task.\n\nThe benefit was practical. Model changes could be checked from several angles in Blender and then reviewed at their actual size in NullG's menus. Saved revisions and repeatable exports made the process easier to iterate, while geometry checks and visual review stayed part of the finishing pass.\n\nBlender MCP provides agent access to scene inspection, geometry and material editing, and visual review. The menu-model process starts with visual references and generated models where useful, followed by a Blender finishing pass.\n\nThat pass covers shape, individual parts, surface cleanup, materials, and polygon count. Models are reviewed from several angles, exported, and checked in NullG's model viewer and menus at their intended display size.\n\n![Four Blender review renders of the original monitor-shaped Graphics menu model](/content/images/2026/10/nullg/intro-blender-graphics-model.png)\n\n*Front, side, rear, and angled review renders of the Graphics menu model.*\n\nThe authoring files, exports, and comparison images remain available through each revision. Connecting these tools lets an agent work through research, code, tests, and visual checks within the same development session.\n\n## Race capture and social media\n\nNullG includes race recording, replay playback, cinematic cameras, and video export. Recorded races can be rendered with ship-focused shots, action cuts, titles, and audio. Landscape, portrait, and square formats support both longer videos and shorter social clips.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/tREm0SM8zmg\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n*The XL cinematic race intro.*\n\nScreenshot tools capture menus, starting grids, tracks, and weapons in action. Agents can help select and organize those captures, with settings and source details retained alongside the images. The same recorded race can support a gameplay review and provide footage for a project update.\n\n## Reinforcement learning for the pilots\n\nNullG also includes reinforcement-learning experiments for computer-controlled pilots. A trained model selects ship controls during a race. Development agents help build the training tools, run checks, and prepare the results for review.\n\nThe pilot receives information about speed and direction, the road ahead, nearby ships, and pickups. It selects throttle, steering, air brakes, pitch, and weapon commands, which pass through the racing simulation as player-style inputs.\n\nTraining uses Python, Gymnasium, Stable-Baselines3, and PyTorch, with PPO as the learning algorithm. Native workers run NullG's race simulation, allowing several driving attempts to run in parallel while the training process updates the model.\n\n![](/content/images/2026/10/nullg/intro-rl-city-race.png)\n\n*A frame from an RL evaluation replay on Gare d’Europa, rendered through NullG's replay tools.*\n\n### Training and evaluation\n\nA short run checks the training setup and controls. Longer runs save checkpoints for evaluation on a chosen set of tracks and race configurations. Saved settings and seeds allow those checks to be repeated.\n\nEvaluation measures completion, time, damage, and steering smoothness. Traffic and combat scenarios also examine race position, pickup use, and weapon timing. Training checkpoints and policies approved for gameplay have separate evaluation steps.\n\nReplays provide another view of the results. Chase cameras show ship movement through a corner, while overhead views show racer positions around the circuit. These views can be compared with the recorded controls and race metrics.\n\n![](/content/images/2026/10/nullg/intro-rl-overhead.png)\n\n*An overhead replay view from the RL development work, with colored racer markers.*\n\nThe exported pilot is a compact model evaluated by native C++ code. Python handles training, and the game runs the exported policy. Retained checkpoints allow different training runs to be compared using the same evaluation setup.\n\nAgents can run the checks, read reports, and prepare replay captures. This supports review of individual driving behaviors and produces footage for documenting the experiments.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/fkUTwW2p_8k\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n*An AI-driving training clip from the NullG playlist.*\n\nMore detail is available on the [MCP tooling page](https://projectable.me/projects/nullg/mcp-tooling/) and [reinforcement-learning page](https://projectable.me/projects/nullg/reinforcement-learning/).\n\n## Publishing to projectable.me\n\nThe same agent-assisted workflow extends to publishing on projectable.me. Agents can prepare illustrated posts, update project pages, and organize development updates under the NullG project.\n\nThe process starts with the git history, project documentation, and relevant captures. An agent prepares the article, adds screenshots and video embeds, and saves a draft on projectable.me. The post can then be reviewed and edited on the site before publication.\n\nThis post follows that process, using repository history for the timeline, project documentation for the workflow details, and existing engine captures for the screenshots. Keeping these updates attached to the NullG project makes the development history easy to follow alongside the project pages.\n\n## Current state and next steps\n\nNullG now includes racing, weapons, computer-controlled opponents, local split-screen, LAN and private online rooms, and replay tools. Inspection and validation tools support development across those systems.\n\n![Two-player vertical split-screen racing with WipEout XL content in NullG](/content/images/2026/10/nullg/intro-xl-splitscreen.png)\n\n*Two racers, two views, and independent HUDs in a NullG split-screen session.*\n\nThe longer-term work includes original ships and tracks, sound, and handling for gamepad and simulator use. Motion output, positional audio, and multiple displays remain part of the simulator plan.\n\nThe [NullG project pages](https://projectable.me/projects/nullg/) cover the engine and its tools in more detail. Development footage is available in the [NullG video playlist](https://www.youtube.com/playlist?list=PLaR-_mRLlb6E), with further updates collected in the [project blog](https://projectable.me/projects/nullg/blog/).","html":"\u003cp\u003e\u003ca href=\"https://projectable.me/projects/nullg/\" rel=\"nofollow\"\u003eNullG\u003c/a\u003e is an anti-gravity racing engine built in C++20 with Vulkan for rendering. It combines legacy game asset imports with racing physics, weapons, multiplayer, and tools for testing and capturing gameplay.\u003c/p\u003e\n\u003cp\u003eThe longer-term goal is a motion simulator pod, with acceleration, braking, cornering, and impacts feeding into physical movement. Positional audio and multiple displays are part of that plan too. Earlier projects such as the \u003ca href=\"https://projectable.me/my-dirt-rally-tabletop-car-cade-game/\" rel=\"nofollow\"\u003eCar-cade\u003c/a\u003e and \u003ca href=\"https://projectable.me/sim-racing-motion-rig-v2-updates/\" rel=\"nofollow\"\u003emotion rig\u003c/a\u003e explored racing through custom hardware. NullG takes that work into the game engine.\u003c/p\u003e\n\u003cp\u003eDevelopment started in January 2026 with AI-assisted planning and implementation. Over the following months, the work expanded into asset loading, rendering, physics, and automated tests. October added more direct access for agents to inspect the engine, run controlled scenarios, and review the results.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/583bdbe059a6-ship.png\" alt=\"Original NullG ship artwork\"\u003e\n\u003cp\u003e\u003cem\u003eOriginal NullG ship artwork.\u003c/em\u003e\u003c/p\u003e\n\u003ch2\u003eJanuary: plans and the first renderer\u003c/h2\u003e\n\u003cp\u003eThe first git commit, dated January 22, 2026, contains the project outline, research files, architecture notes, and initial application code. The plans already covered asset conversion, input, audio, networking, computer-controlled opponents, and motion output. The application had a window, Vulkan setup, input handling, configuration, and logging.\u003c/p\u003e\n\u003cp\u003eThe architecture put the race simulation at the center. Graphics and sound would use the state produced by the simulation, with motion hardware eventually reading the same data. This kept the simulator goal part of the engine design from the beginning.\u003c/p\u003e\n\u003cp\u003eEarly development used Cursor, with project commands for planning, preparation, and review. The preparation step directed the agent to read reference material and trace the relevant code before making changes. Tasks were broken into smaller pieces, with examples and written decisions available for the next session.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/037075fac8ed-G_jZiq3WQAAg2Cz.jpeg\" alt=\"G_jZiq3WQAAg2Cz.jpeg\"\u003e\n\u003cp\u003eJanuary 23 brought asset conversion tooling and the first renderer pass. Menus, model loading, asset management, and track parsing followed over the next few days. Existing WipEout research and community projects provided references for loading the ships, tracks, textures, and scenery.\u003c/p\u003e\n\u003ch2\u003eFebruary: loading the original assets\u003c/h2\u003e\n\u003cp\u003eBy February 8, the project had a direct PlayStation asset-loading checkpoint. Work during this period covered track rendering, scene objects, sprites, and texture transparency.\u003c/p\u003e\n\u003cp\u003eLoading the geometry, textures, and scenery together made it possible to check the imported data in the renderer. File-format notes and agent rules developed alongside the loaders, giving later tasks a record of how the assets were organized and used.\u003c/p\u003e\n\u003ch2\u003eMarch: handling, race flow, and weapons\u003c/h2\u003e\n\u003cp\u003eMarch focused more on how ships move around a track: hover height, coasting, weight, jumps, boost, recovery, and tunnel-wall collisions. Scene placement, sky textures, pickups, and boost pads also received attention, along with the camera moving through the track behind the menus.\u003c/p\u003e\n\u003cp\u003eReal-time lighting, shadows, and GPU particles added to the presentation. By March 6, the code included race-session flow and a weapon system, handling the transition into a race and back to the menus.\u003c/p\u003e\n\u003cp\u003eThese changes were developed as individual tasks using the relevant code and reference material. Code review and updated implementation notes kept the decisions available as the systems grew.\u003c/p\u003e\n\u003ch2\u003eMay: rendering and automated tests\u003c/h2\u003e\n\u003cp\u003eMay brought a larger pass through the engine internals. The original engine plan was split into focused documents with a shared status index, making individual areas easier to track.\u003c/p\u003e\n\u003cp\u003eRenderer work included dynamic rendering, geometry access, material organization, and a move to Slang for runtime shaders. Lighting work covered animated scene lights, illuminated pickups, shields, and the shadows received by ships from surrounding scenery.\u003c/p\u003e\n\u003cp\u003eAn entity/component scene system and render snapshots were added during the same period. A snapshot holds the scene data needed for a frame, including ship and object positions, giving the renderer a consistent set of data to draw.\u003c/p\u003e\n\u003cp\u003eOn May 28, a headless test suite added checks for the job system, memory, and asset handling. Agents could run these tests after editing the code and inspect the results directly. This became the starting point for the more extensive inspection and gameplay tools added later.\u003c/p\u003e\n\u003ch2\u003eJune: collision, effects, and XL\u003c/h2\u003e\n\u003cp\u003eJune added Jolt collision integration and further GPU effects work. Research notes covered established techniques for effects, shadows, and physics, providing examples for subsequent implementation tasks.\u003c/p\u003e\n\u003cp\u003eWipEout XL became the default asset source in a June 9 checkpoint. Source descriptors drove the menus, allowing the selected game\u0026#39;s data to determine the available choices. Other changes covered waterfall texture scrolling and the starting-grid camera.\u003c/p\u003e\n\u003cp\u003eBy this stage, the codebase covered rendering, asset loading, handling, race flow, weapons, collision, and tests. The next concentrated stretch of commits begins on October 9, with the existing agent guidance brought into Codex, engine-backed inspection tools, and a fixed 60 Hz racing setup. Multiplayer followed on October 10, then the XL reconstruction checkpoint on October 11.\u003c/p\u003e\n\u003ch2\u003eOctober: giving agents access to the engine\u003c/h2\u003e\n\u003cp\u003eOctober also marked a decision to use OpenAI Codex exclusively for NullG\u0026#39;s coding-agent work. The existing planning commands, project rules, and reference notes were carried over from Cursor, keeping the earlier work available as context. Development then focused more heavily on giving Codex access to the tools needed to inspect, test, and review changes.\u003c/p\u003e\n\u003cp\u003eRecently watched YouTube videos about Blender MCP helped shape that approach. They showed how an agent could work directly with a scene and inspect the result. Those concepts were brought into NullG\u0026#39;s model-authoring process and reinforced the value of connecting agents to the engine\u0026#39;s own inspection tools.\u003c/p\u003e\n\u003cp\u003eOctober\u0026#39;s tooling work gave agents more ways to check their changes. \u003ca href=\"https://modelcontextprotocol.io/introduction\" rel=\"nofollow\"\u003eMCP, the Model Context Protocol\u003c/a\u003e, connects AI applications to external tools and data. NullG uses it to expose native inspection windows, track validators, model viewers, and controlled race sessions.\u003c/p\u003e\n\u003cp\u003eAn agent can load a track, choose a camera, inspect geometry, and capture a frame. Model inspection provides access to materials, bounds, and different viewing angles. Test harnesses provide repeatable scenarios with known inputs.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-track-inspection.png\" alt=\"NullG Track Validator showing track geometry, texture inspection, and timeline controls\"\u003e\n\u003cp\u003e\u003cem\u003eThe track inspector, with the track view, texture panel, and playback controls.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe weapon harness opens a paused production race scene. An agent can deploy a weapon and advance the scene in controlled steps, inspecting a projectile, impact, or Quake effect at a specific point. Simulation state and rendered output can then be reviewed together.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/pbUzB3j74p8\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003cem\u003eReactive engine plumes viewed through the MCP harness.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003ePhysics tests compare movement with expected values, track checks inspect road geometry, and screenshots show the rendered result. Replaying the same inputs checks consistency across changes. Together, these tools let agents run a larger part of the validation process themselves, with reports and captures available for human review.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/nullg-ships-weapon-action.png\" alt=\"Ships racing with engine trails and a weapon effect in NullG\"\u003e\n\u003ch3\u003eWorking through a change\u003c/h3\u003e\n\u003cp\u003eA weapon-effect investigation starts with a specific scene and setup. The agent deploys the weapon, steps through the action, checks the state, and follows the code responsible for the effect. After an edit, it builds the affected code and repeats the scenario.\u003c/p\u003e\n\u003cp\u003eSaved reports retain the inputs and settings. That allows the case to be repeated in another session or compared across versions. Visual review and gameplay testing provide additional checks on appearance and handling.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-agent-workflow.png\" alt=\"Diagram showing an agent connected through MCP to native inspection and headless validation tools\"\u003e\n\u003cp\u003e\u003cem\u003eThe agent can run a test, open an inspector, and save the results for review.\u003c/em\u003e\u003c/p\u003e\n\u003ch2\u003eReverse engineering WipEout XL\u003c/h2\u003e\n\u003cp\u003eThe October research also examined WipEout XL / 2097 behavior in more detail, including steering, weapon updates, starting positions, and animated objects.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/morluto/rea\" rel=\"nofollow\"\u003eREA, Reverse Engineer Anything\u003c/a\u003e, formed part of the research setup. It connects agents with tools for investigating applications and binaries. The PlayStation XL executable decompilation used a PSX-aware Ghidra workflow, with scripts retaining instructions, references, annotations, and findings.\u003c/p\u003e\n\u003cp\u003eThe starting grid provides a useful example. Following the original track numbering and route links established where ships should start. Those findings became checks against the imported track, with the inspector showing the selected position on the road.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-grid-placement.png\" alt=\"An overhead track inspection with a highlighted grid marker\"\u003e\n\u003cp\u003e\u003cem\u003eChecking a grid position against the track geometry.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe research covers both USA and European editions. Each finding retains the edition and executable details so timing values and behavior can be traced to their source.\u003c/p\u003e\n\u003cp\u003eRecovered calculations and state changes are implemented as small C++ reference models, tested, and then connected to NullG. The records distinguish behavior derived from the original executable, adaptations for NullG, and observations from running the engine.\u003c/p\u003e\n\u003cp\u003eAgent access to analysis tools makes this kind of detailed investigation more accessible to individual developers. Existing products can be studied one behavior at a time, with findings carried into tests and new implementations. For NullG, that supports continued refinement of racing behavior alongside modern rendering, controls, and multiplayer. Imported content comes from user-supplied game files, while original NullG assets are developed separately.\u003c/p\u003e\n\u003ch2\u003eA wider wave of software reconstruction\u003c/h2\u003e\n\u003cp\u003eREA\u0026#39;s rapid rise in attention during early October put agent-assisted reverse engineering in front of a much larger audience. \u003ca href=\"https://www.onfirstlaunch.com/blog/reverse-engineer-anything-rea-explained\" rel=\"nofollow\"\u003eCoverage of its growth\u003c/a\u003e described a surge in interest around demonstrations of agents inspecting applications and reconstructing their behavior.\u003c/p\u003e\n\u003cp\u003eAt the same time, “vibe-coded” alternatives to familiar creative and office software were attracting attention. \u003ca href=\"https://github.com/storytold\" rel=\"nofollow\"\u003eArtCraft\u0026#39;s projects\u003c/a\u003e include photo, video, and PDF tools, alongside \u003ca href=\"https://github.com/storytold/wordcraft\" rel=\"nofollow\"\u003eWordCraft\u003c/a\u003e, \u003ca href=\"https://github.com/storytold/gridcraft\" rel=\"nofollow\"\u003eGridCraft\u003c/a\u003e, and \u003ca href=\"https://github.com/storytold/deckcraft\" rel=\"nofollow\"\u003eDeckCraft\u003c/a\u003e, which target Word, Excel, and PowerPoint-style workflows. \u003ca href=\"https://www.techradar.com/computing/office-suites/developer-who-vibe-coded-free-adobe-clones-reveals-apps-to-take-down-microsoft-office-next-and-says-there-is-no-reason-to-save-broken-software\" rel=\"nofollow\"\u003eOctober coverage\u003c/a\u003e connected these AI-assisted projects with the growing interest in alternatives to Adobe and Microsoft applications.\u003c/p\u003e\n\u003cp\u003eThese are separate projects exploring related possibilities: using agents to understand software, implement familiar workflows, and build tools around specific needs. NullG applies that approach to racing. Executable research informs individual behaviors, while tests, inspectors, and recorded scenarios provide ways to check the implementation. The same emphasis on repeatable validation carries through asset production and gameplay development.\u003c/p\u003e\n\u003ch2\u003eBlender and model production\u003c/h2\u003e\n\u003cp\u003eThe Blender MCP concepts from those videos were applied to a specific job: preparing original menu models for the engine. Scene access let the agent inspect parts, make scoped edits, export a candidate, and produce comparison views within the same task.\u003c/p\u003e\n\u003cp\u003eThe benefit was practical. Model changes could be checked from several angles in Blender and then reviewed at their actual size in NullG\u0026#39;s menus. Saved revisions and repeatable exports made the process easier to iterate, while geometry checks and visual review stayed part of the finishing pass.\u003c/p\u003e\n\u003cp\u003eBlender MCP provides agent access to scene inspection, geometry and material editing, and visual review. The menu-model process starts with visual references and generated models where useful, followed by a Blender finishing pass.\u003c/p\u003e\n\u003cp\u003eThat pass covers shape, individual parts, surface cleanup, materials, and polygon count. Models are reviewed from several angles, exported, and checked in NullG\u0026#39;s model viewer and menus at their intended display size.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-blender-graphics-model.png\" alt=\"Four Blender review renders of the original monitor-shaped Graphics menu model\"\u003e\n\u003cp\u003e\u003cem\u003eFront, side, rear, and angled review renders of the Graphics menu model.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe authoring files, exports, and comparison images remain available through each revision. Connecting these tools lets an agent work through research, code, tests, and visual checks within the same development session.\u003c/p\u003e\n\u003ch2\u003eRace capture and social media\u003c/h2\u003e\n\u003cp\u003eNullG includes race recording, replay playback, cinematic cameras, and video export. Recorded races can be rendered with ship-focused shots, action cuts, titles, and audio. Landscape, portrait, and square formats support both longer videos and shorter social clips.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/tREm0SM8zmg\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003cem\u003eThe XL cinematic race intro.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eScreenshot tools capture menus, starting grids, tracks, and weapons in action. Agents can help select and organize those captures, with settings and source details retained alongside the images. The same recorded race can support a gameplay review and provide footage for a project update.\u003c/p\u003e\n\u003ch2\u003eReinforcement learning for the pilots\u003c/h2\u003e\n\u003cp\u003eNullG also includes reinforcement-learning experiments for computer-controlled pilots. A trained model selects ship controls during a race. Development agents help build the training tools, run checks, and prepare the results for review.\u003c/p\u003e\n\u003cp\u003eThe pilot receives information about speed and direction, the road ahead, nearby ships, and pickups. It selects throttle, steering, air brakes, pitch, and weapon commands, which pass through the racing simulation as player-style inputs.\u003c/p\u003e\n\u003cp\u003eTraining uses Python, Gymnasium, Stable-Baselines3, and PyTorch, with PPO as the learning algorithm. Native workers run NullG\u0026#39;s race simulation, allowing several driving attempts to run in parallel while the training process updates the model.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-rl-city-race.png\" alt=\"\"\u003e\n\u003cp\u003e\u003cem\u003eA frame from an RL evaluation replay on Gare d’Europa, rendered through NullG\u0026#39;s replay tools.\u003c/em\u003e\u003c/p\u003e\n\u003ch3\u003eTraining and evaluation\u003c/h3\u003e\n\u003cp\u003eA short run checks the training setup and controls. Longer runs save checkpoints for evaluation on a chosen set of tracks and race configurations. Saved settings and seeds allow those checks to be repeated.\u003c/p\u003e\n\u003cp\u003eEvaluation measures completion, time, damage, and steering smoothness. Traffic and combat scenarios also examine race position, pickup use, and weapon timing. Training checkpoints and policies approved for gameplay have separate evaluation steps.\u003c/p\u003e\n\u003cp\u003eReplays provide another view of the results. Chase cameras show ship movement through a corner, while overhead views show racer positions around the circuit. These views can be compared with the recorded controls and race metrics.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-rl-overhead.png\" alt=\"\"\u003e\n\u003cp\u003e\u003cem\u003eAn overhead replay view from the RL development work, with colored racer markers.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe exported pilot is a compact model evaluated by native C++ code. Python handles training, and the game runs the exported policy. Retained checkpoints allow different training runs to be compared using the same evaluation setup.\u003c/p\u003e\n\u003cp\u003eAgents can run the checks, read reports, and prepare replay captures. This supports review of individual driving behaviors and produces footage for documenting the experiments.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/fkUTwW2p_8k\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003cp\u003e\u003cem\u003eAn AI-driving training clip from the NullG playlist.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eMore detail is available on the \u003ca href=\"https://projectable.me/projects/nullg/mcp-tooling/\" rel=\"nofollow\"\u003eMCP tooling page\u003c/a\u003e and \u003ca href=\"https://projectable.me/projects/nullg/reinforcement-learning/\" rel=\"nofollow\"\u003ereinforcement-learning page\u003c/a\u003e.\u003c/p\u003e\n\u003ch2\u003ePublishing to projectable.me\u003c/h2\u003e\n\u003cp\u003eThe same agent-assisted workflow extends to publishing on projectable.me. Agents can prepare illustrated posts, update project pages, and organize development updates under the NullG project.\u003c/p\u003e\n\u003cp\u003eThe process starts with the git history, project documentation, and relevant captures. An agent prepares the article, adds screenshots and video embeds, and saves a draft on projectable.me. The post can then be reviewed and edited on the site before publication.\u003c/p\u003e\n\u003cp\u003eThis post follows that process, using repository history for the timeline, project documentation for the workflow details, and existing engine captures for the screenshots. Keeping these updates attached to the NullG project makes the development history easy to follow alongside the project pages.\u003c/p\u003e\n\u003ch2\u003eCurrent state and next steps\u003c/h2\u003e\n\u003cp\u003eNullG now includes racing, weapons, computer-controlled opponents, local split-screen, LAN and private online rooms, and replay tools. Inspection and validation tools support development across those systems.\u003c/p\u003e\n\u003cimg src=\"/content/images/2026/10/nullg/intro-xl-splitscreen.png\" alt=\"Two-player vertical split-screen racing with WipEout XL content in NullG\"\u003e\n\u003cp\u003e\u003cem\u003eTwo racers, two views, and independent HUDs in a NullG split-screen session.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe longer-term work includes original ships and tracks, sound, and handling for gamepad and simulator use. Motion output, positional audio, and multiple displays remain part of the simulator plan.\u003c/p\u003e\n\u003cp\u003eThe \u003ca href=\"https://projectable.me/projects/nullg/\" rel=\"nofollow\"\u003eNullG project pages\u003c/a\u003e cover the engine and its tools in more detail. Development footage is available in the \u003ca href=\"https://www.youtube.com/playlist?list=PLaR-_mRLlb6E\" rel=\"nofollow\"\u003eNullG video playlist\u003c/a\u003e, with further updates collected in the \u003ca href=\"https://projectable.me/projects/nullg/blog/\" rel=\"nofollow\"\u003eproject blog\u003c/a\u003e.\u003c/p\u003e\n","excerpt":"NullG’s development from January’s engine plans through asset loading, racing systems, XL research, agent validation, and reinforcement learning.","metaTitle":"Introducing NullG: racing and AI-assisted development","metaDescription":"The development of NullG: a C++20 and Vulkan racing engine with WipEout XL research, MCP tools, Blender workflows, reinforcement learning, and replay capture.","status":"published","featured":true,"publishedAt":"2026-10-19T02:27:51Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"3cd28585400f94ee7115b744db06b6a1","projectId":"ae4bdb66da6dc1729a263a475e1cdbe3","tags":[{"id":"1c9e8a1339a8f8b797767e91a9673016","name":"Game","slug":"game"},{"id":"ecaaace3f367d1a9865ae0933d53d715","name":"Sim Racing","slug":"sim-racing"}],"createdAt":"2026-10-19T02:05:13Z","updatedAt":"2026-10-19T20:15:35Z"},{"id":"add9e77292c614f59260072375d13db5","siteId":"projectable","slug":"ubuntu-24-04-nvidia-drivers-ollama","title":"Ubuntu 24.04 + Nvidia Drivers + Ollama","markdown":"![](/content/images/2025/03/IMG_8241.JPG)\n\nI am building an updated server to play with LLMs for local home automation control using Home Assistant (https://www.home-assistant.io). \n\nI managed to pick up a Dell R740 for a great price ($400) and with a few additional eBay purchases have a nice server capable of housing 3 GPUs. I have an existing Nvidia Tesla P100 from my other server that I am moving to this new server, and will eventually look at finding a Tesla V100 32G PCIe as they seem to have a slightly more accessible price compared to the Tesla A100 PCIe. \n\n![](/content/images/2025/03/IMG_8212.JPG)\n![](/content/images/2025/03/IMG_8213.JPG)\n![](/content/images/2025/03/IMG_8216.jpg)\n\nI will continue to run Home Assistant on my [Home Assistant Yellow](https://www.home-assistant.io/yellow/) (PoE, Raspberry Pi CM5 8GB, NVMe SSD), but will land Ollama, and other tools on this new server.\n\n![](/content/images/2025/03/IMG_8243.JPG)\n\nI was banging my head against this for the 2nd time I thought it would be helpful to document the setup process for getting Ollama running on Ubuntu 24.04 along with the steps to reliably install the Nvidia drivers \u0026 CUDA packages. \n\n\n### Nvidia Driver install\n\nBefore you begin, ensure that your Nvidia card is showing up on the PCI bus. Run `lspci | grep -i nvidia` and you should get output similar to this:\n```\naf:00.0 3D controller: NVIDIA Corporation GP100GL [Tesla P100 PCIe 16GB] (rev a1)\n```\n\nIf you have already attempted to install nvidia drivers and have failed cleanup your existing Nvidia nuggets as follows:\n```sh\nsudo apt-get remove --purge 'libnvidia-.*'\nsudo apt-get remove --purge '^nvidia-.*'\nsudo apt-get remove --purge '^libnvidia-.*'\nsudo apt-get remove --purge '^cuda-.*'\nsudo apt clean\nsudo apt autoremove\n```\n\nNow install the updated Nvidia drivers:\n```sh\nsudo add-apt-repository ppa:graphics-drivers/ppa --yes\nsudo apt-get update\n\nupdate-pciids\n\nsudo apt-get install nvidia-driver-570 -y\nsudo apt-get reinstall linux-headers-$(uname -r)\n\nsudo update-initramfs -u\n```\n\nValidate that the DKMS modules are actually there, and then reboot if they are:\n```sh\nsudo dkms status\nsudo reboot\n```\n\nAfter a reboot you should be able to run `nvidia-smi` and get output similar to this:\n```\nroot@r740:~# nvidia-smi \nWed Mar 5 14:34:02 2025 \n+-----------------------------------------------------------------------------------------+\n| NVIDIA-SMI 570.86.16 Driver Version: 570.86.16 CUDA Version: 12.8 |\n|-----------------------------------------+------------------------+----------------------+\n| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n| | | MIG M. |\n|=========================================+========================+======================|\n| 0 Tesla P100-PCIE-16GB Off | 00000000:AF:00.0 Off | 0 |\n| N/A 30C P0 26W / 250W | 0MiB / 16384MiB | 0% Default |\n| | | N/A |\n+-----------------------------------------+------------------------+----------------------+\n \n+-----------------------------------------------------------------------------------------+\n| Processes: |\n| GPU GI CI PID Type Process name GPU Memory |\n| ID ID Usage |\n|=========================================================================================|\n| No running processes found |\n+-----------------------------------------------------------------------------------------+\n```\n\n\n### Nvidia CUDA install\n\n```sh\nwget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb\nsudo dpkg -i cuda-keyring_1.1-1_all.deb\n\nsudo apt-get update\n\nsudo apt-get install cuda-toolkit -y\nsudo apt-get install nvidia-gds -y\n```\n\nI don't think the `nvidia-gds` package is required for my P100, but the official CUDA install guide has it so I'm including it here. Check that the `nvidia-fs` module is now available in DKMS and then reboot.\n\n```sh\nsudo dkms status\nsudo reboot\n```\n\nAfter rebooting you will likely see that there are updated packages for the Nvidia drivers, you can upgrade them if you like. I found that installing the drivers from the `ppa:graphics-drivers/ppa` repository first had more consistent results than installing from the nvidia repos first. Your mileage may vary... \n\n\n### Install Docker\nWe will use docker to host the ollama web ui, but we will run ollama locally on the system.\n```sh\nsudo apt-get install curl apt-transport-https ca-certificates software-properties-common -y\n\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg\necho \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list \u003e /dev/null\n\nsudo apt-get update\nsudo apt-get install docker-ce -y\n```\nNow add your local user to the docker group `sudo usermod -aG docker $USER`.\n\n\n### Install Nvidia Container Toolkit\n```sh\ncurl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \\\n \u0026\u0026 curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \\\n sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \\\n sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list\n\nsudo apt-get update\nsudo apt-get install nvidia-container-toolkit -y\n\nsudo systemctl restart docker\n```\n\n### Install Ollama\n```sh\ncurl -fsSL https://ollama.com/install.sh | sh\n```\n\nNow edit the systemd service file to allow the Ollama to listen on all network interfaces on the system instead of just `localhost` by adding `OLLAMA_HOST=0.0.0.0:11434`\n\n**Edit**: `/etc/systemd/system/ollama.service`\n```\n[Unit]\nDescription=Ollama Service\nAfter=network-online.target\n\n[Service]\nExecStart=/usr/local/bin/ollama serve\nUser=ollama\nGroup=ollama\nRestart=always\nRestartSec=3\nEnvironment=\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin\"\nEnvironment=\"OLLAMA_HOST=0.0.0.0:11434\"\n\n[Install]\nWantedBy=default.target\n```\n\nThen run the following to apply the changes:\n```sh\nsudo systemctl daemon-reload\nsudo systemctl restart ollama \n```\n\n\n### Install Open WebUI\n```sh\ndocker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main\n```\n\nYou should now be able to navigate to Open WebUI using your server IP and port 3000. Create your admin account and you are ready to start installing models from https://ollama.com/library.\n\n![](/content/images/2025/03/ollama1-1.png)\n![](/content/images/2025/03/ollama2.png)","html":"\u003cimg src=\"/content/images/2025/03/IMG_8241.JPG\" alt=\"\"\u003e\n\u003cp\u003eI am building an updated server to play with LLMs for local home automation control using Home Assistant (\u003ca href=\"https://www.home-assistant.io\" rel=\"nofollow\"\u003ehttps://www.home-assistant.io\u003c/a\u003e).\u003c/p\u003e\n\u003cp\u003eI managed to pick up a Dell R740 for a great price ($400) and with a few additional eBay purchases have a nice server capable of housing 3 GPUs. I have an existing Nvidia Tesla P100 from my other server that I am moving to this new server, and will eventually look at finding a Tesla V100 32G PCIe as they seem to have a slightly more accessible price compared to the Tesla A100 PCIe.\u003c/p\u003e\n\u003cimg src=\"/content/images/2025/03/IMG_8212.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2025/03/IMG_8213.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2025/03/IMG_8216.jpg\" alt=\"\"\u003e\n\u003cp\u003eI will continue to run Home Assistant on my \u003ca href=\"https://www.home-assistant.io/yellow/\" rel=\"nofollow\"\u003eHome Assistant Yellow\u003c/a\u003e (PoE, Raspberry Pi CM5 8GB, NVMe SSD), but will land Ollama, and other tools on this new server.\u003c/p\u003e\n\u003cimg src=\"/content/images/2025/03/IMG_8243.JPG\" alt=\"\"\u003e\n\u003cp\u003eI was banging my head against this for the 2nd time I thought it would be helpful to document the setup process for getting Ollama running on Ubuntu 24.04 along with the steps to reliably install the Nvidia drivers \u0026amp; CUDA packages.\u003c/p\u003e\n\u003ch3\u003eNvidia Driver install\u003c/h3\u003e\n\u003cp\u003eBefore you begin, ensure that your Nvidia card is showing up on the PCI bus. Run \u003ccode\u003elspci | grep -i nvidia\u003c/code\u003e and you should get output similar to this:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eaf:00.0 3D controller: NVIDIA Corporation GP100GL [Tesla P100 PCIe 16GB] (rev a1)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf you have already attempted to install nvidia drivers and have failed cleanup your existing Nvidia nuggets as follows:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo apt-get remove --purge \u0026#39;libnvidia-.*\u0026#39;\nsudo apt-get remove --purge \u0026#39;^nvidia-.*\u0026#39;\nsudo apt-get remove --purge \u0026#39;^libnvidia-.*\u0026#39;\nsudo apt-get remove --purge \u0026#39;^cuda-.*\u0026#39;\nsudo apt clean\nsudo apt autoremove\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow install the updated Nvidia drivers:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo add-apt-repository ppa:graphics-drivers/ppa --yes\nsudo apt-get update\n\nupdate-pciids\n\nsudo apt-get install nvidia-driver-570 -y\nsudo apt-get reinstall linux-headers-$(uname -r)\n\nsudo update-initramfs -u\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eValidate that the DKMS modules are actually there, and then reboot if they are:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo dkms status\nsudo reboot\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAfter a reboot you should be able to run \u003ccode\u003envidia-smi\u003c/code\u003e and get output similar to this:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eroot@r740:~# nvidia-smi \nWed Mar 5 14:34:02 2025 \n+-----------------------------------------------------------------------------------------+\n| NVIDIA-SMI 570.86.16 Driver Version: 570.86.16 CUDA Version: 12.8 |\n|-----------------------------------------+------------------------+----------------------+\n| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n| | | MIG M. |\n|=========================================+========================+======================|\n| 0 Tesla P100-PCIE-16GB Off | 00000000:AF:00.0 Off | 0 |\n| N/A 30C P0 26W / 250W | 0MiB / 16384MiB | 0% Default |\n| | | N/A |\n+-----------------------------------------+------------------------+----------------------+\n \n+-----------------------------------------------------------------------------------------+\n| Processes: |\n| GPU GI CI PID Type Process name GPU Memory |\n| ID ID Usage |\n|=========================================================================================|\n| No running processes found |\n+-----------------------------------------------------------------------------------------+\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3\u003eNvidia CUDA install\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003ewget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb\nsudo dpkg -i cuda-keyring_1.1-1_all.deb\n\nsudo apt-get update\n\nsudo apt-get install cuda-toolkit -y\nsudo apt-get install nvidia-gds -y\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eI don\u0026#39;t think the \u003ccode\u003envidia-gds\u003c/code\u003e package is required for my P100, but the official CUDA install guide has it so I\u0026#39;m including it here. Check that the \u003ccode\u003envidia-fs\u003c/code\u003e module is now available in DKMS and then reboot.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo dkms status\nsudo reboot\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAfter rebooting you will likely see that there are updated packages for the Nvidia drivers, you can upgrade them if you like. I found that installing the drivers from the \u003ccode\u003eppa:graphics-drivers/ppa\u003c/code\u003e repository first had more consistent results than installing from the nvidia repos first. Your mileage may vary...\u003c/p\u003e\n\u003ch3\u003eInstall Docker\u003c/h3\u003e\n\u003cp\u003eWe will use docker to host the ollama web ui, but we will run ollama locally on the system.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo apt-get install curl apt-transport-https ca-certificates software-properties-common -y\n\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg\necho \u0026#34;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\u0026#34; | sudo tee /etc/apt/sources.list.d/docker.list \u0026gt; /dev/null\n\nsudo apt-get update\nsudo apt-get install docker-ce -y\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow add your local user to the docker group \u003ccode\u003esudo usermod -aG docker $USER\u003c/code\u003e.\u003c/p\u003e\n\u003ch3\u003eInstall Nvidia Container Toolkit\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003ecurl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \\\n \u0026amp;\u0026amp; curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \\\n sed \u0026#39;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g\u0026#39; | \\\n sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list\n\nsudo apt-get update\nsudo apt-get install nvidia-container-toolkit -y\n\nsudo systemctl restart docker\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3\u003eInstall Ollama\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003ecurl -fsSL https://ollama.com/install.sh | sh\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow edit the systemd service file to allow the Ollama to listen on all network interfaces on the system instead of just \u003ccode\u003elocalhost\u003c/code\u003e by adding \u003ccode\u003eOLLAMA_HOST=0.0.0.0:11434\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eEdit\u003c/strong\u003e: \u003ccode\u003e/etc/systemd/system/ollama.service\u003c/code\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e[Unit]\nDescription=Ollama Service\nAfter=network-online.target\n\n[Service]\nExecStart=/usr/local/bin/ollama serve\nUser=ollama\nGroup=ollama\nRestart=always\nRestartSec=3\nEnvironment=\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin\u0026#34;\nEnvironment=\u0026#34;OLLAMA_HOST=0.0.0.0:11434\u0026#34;\n\n[Install]\nWantedBy=default.target\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThen run the following to apply the changes:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003esudo systemctl daemon-reload\nsudo systemctl restart ollama \n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3\u003eInstall Open WebUI\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"language-sh\"\u003edocker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eYou should now be able to navigate to Open WebUI using your server IP and port 3000. Create your admin account and you are ready to start installing models from \u003ca href=\"https://ollama.com/library\" rel=\"nofollow\"\u003ehttps://ollama.com/library\u003c/a\u003e.\u003c/p\u003e\n\u003cimg src=\"/content/images/2025/03/ollama1-1.png\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2025/03/ollama2.png\" alt=\"\"\u003e","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2026-10-18T18:03:14Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"","projectId":"","tags":[],"createdAt":"2026-10-18T18:03:08Z","updatedAt":"2026-10-18T18:03:14Z"},{"id":"729c9a4edc92eaa4171ac274dda70ca2","siteId":"projectable","slug":"comcast-business-ipv6-on-ubiquiti-unifi","title":"Comcast Business IPv6 on Ubiquiti Unifi","markdown":"If you are reading this it is likely you were like me, on the edge of giving up on IPv6 on your network. After combining a few small pieces from posts outlining **Comcast Business IPv6** using Ubiquiti EdgeRouters along with the [**USG Advanced Configuration**](https://help.ubnt.com/hc/en-us/articles/215458888-UniFi-USG-Advanced-Configuration) guide I was able to get something that not only works correctly, but persists correctly also.\n\nThe trick was getting the right settings defined in the web interface and the one setting not available in the web interface. It's pretty straight forward, so for sake of simplicity I will just tell you what things need to be set. *This configuration has 1 of my internal networks having IPv6, I did not want to spend any more time trying to make this work across multiple internal networks, but it probably isn't hard.*\n\n#### WAN Interface\n![](/content/images/2019/11/Screen-Shot-2019-11-05-at-7-49-35-AM.png)\n\nSet your WAN interface **IPv6 Connection Type** to `Using DHCPv6`. You will need to ensure that your cable modem has DHCPv6 enabled, it usually is by default. The **Prefix Delegation Size** should be set to `59` as 56 didn't seem to work.\n\n\n### LAN Interface\n![](/content/images/2019/11/Screen-Shot-2019-11-05-at-7-52-39-AM.png)\n\n**IPv6 Interface Type** gets set to `Prefix Delegation`, you select the WAN interface you used earlier, and you set the **IPv6 Prefix ID** to `1`. \n\nI suggest setting **DHCPv6/RDNSS DNS Control** to `Auto`, mine is set to `Manual` due to having a [Pi-hole](https://pi-hole.net) on my network that I use for DNS recursion/caching.\n\n\n### The Backend Stuff\nYou will need to follow the **USG Advanced Configuration** guide found here: https://help.ubnt.com/hc/en-us/articles/215458888-UniFi-USG-Advanced-Configuration.\n\nFollowing that guide you create your own `config.gateway.json` file and can paste the following.\n```\n{\n \"interfaces\": {\n \"ethernet\": {\n \"eth2\": {\n \"dhcpv6-pd\": {\n \"rapid-commit\": \"disable\"\n }\n }\n }\n }\n}\n```\nIf you are using **WAN2** instead of **WAN** change `eth2` to `eth3`. \n\n### Finishing Up\nIf you followed the guide and **Force provision**ed your **USG** you should be good to go. \nMy linux hosts picked up the IPv6 IPs automatically, and on my Apple products I just disabled then re-enabled Wifi.","html":"\u003cp\u003eIf you are reading this it is likely you were like me, on the edge of giving up on IPv6 on your network. After combining a few small pieces from posts outlining \u003cstrong\u003eComcast Business IPv6\u003c/strong\u003e using Ubiquiti EdgeRouters along with the \u003ca href=\"https://help.ubnt.com/hc/en-us/articles/215458888-UniFi-USG-Advanced-Configuration\" rel=\"nofollow\"\u003e\u003cstrong\u003eUSG Advanced Configuration\u003c/strong\u003e\u003c/a\u003e guide I was able to get something that not only works correctly, but persists correctly also.\u003c/p\u003e\n\u003cp\u003eThe trick was getting the right settings defined in the web interface and the one setting not available in the web interface. It\u0026#39;s pretty straight forward, so for sake of simplicity I will just tell you what things need to be set. \u003cem\u003eThis configuration has 1 of my internal networks having IPv6, I did not want to spend any more time trying to make this work across multiple internal networks, but it probably isn\u0026#39;t hard.\u003c/em\u003e\u003c/p\u003e\n\u003ch4\u003eWAN Interface\u003c/h4\u003e\n\u003cimg src=\"/content/images/2019/11/Screen-Shot-2019-11-05-at-7-49-35-AM.png\" alt=\"\"\u003e\n\u003cp\u003eSet your WAN interface \u003cstrong\u003eIPv6 Connection Type\u003c/strong\u003e to \u003ccode\u003eUsing DHCPv6\u003c/code\u003e. You will need to ensure that your cable modem has DHCPv6 enabled, it usually is by default. The \u003cstrong\u003ePrefix Delegation Size\u003c/strong\u003e should be set to \u003ccode\u003e59\u003c/code\u003e as 56 didn\u0026#39;t seem to work.\u003c/p\u003e\n\u003ch3\u003eLAN Interface\u003c/h3\u003e\n\u003cimg src=\"/content/images/2019/11/Screen-Shot-2019-11-05-at-7-52-39-AM.png\" alt=\"\"\u003e\n\u003cp\u003e\u003cstrong\u003eIPv6 Interface Type\u003c/strong\u003e gets set to \u003ccode\u003ePrefix Delegation\u003c/code\u003e, you select the WAN interface you used earlier, and you set the \u003cstrong\u003eIPv6 Prefix ID\u003c/strong\u003e to \u003ccode\u003e1\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eI suggest setting \u003cstrong\u003eDHCPv6/RDNSS DNS Control\u003c/strong\u003e to \u003ccode\u003eAuto\u003c/code\u003e, mine is set to \u003ccode\u003eManual\u003c/code\u003e due to having a \u003ca href=\"https://pi-hole.net\" rel=\"nofollow\"\u003ePi-hole\u003c/a\u003e on my network that I use for DNS recursion/caching.\u003c/p\u003e\n\u003ch3\u003eThe Backend Stuff\u003c/h3\u003e\n\u003cp\u003eYou will need to follow the \u003cstrong\u003eUSG Advanced Configuration\u003c/strong\u003e guide found here: \u003ca href=\"https://help.ubnt.com/hc/en-us/articles/215458888-UniFi-USG-Advanced-Configuration\" rel=\"nofollow\"\u003ehttps://help.ubnt.com/hc/en-us/articles/215458888-UniFi-USG-Advanced-Configuration\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eFollowing that guide you create your own \u003ccode\u003econfig.gateway.json\u003c/code\u003e file and can paste the following.\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e{\n \u0026#34;interfaces\u0026#34;: {\n \u0026#34;ethernet\u0026#34;: {\n \u0026#34;eth2\u0026#34;: {\n \u0026#34;dhcpv6-pd\u0026#34;: {\n \u0026#34;rapid-commit\u0026#34;: \u0026#34;disable\u0026#34;\n }\n }\n }\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf you are using \u003cstrong\u003eWAN2\u003c/strong\u003e instead of \u003cstrong\u003eWAN\u003c/strong\u003e change \u003ccode\u003eeth2\u003c/code\u003e to \u003ccode\u003eeth3\u003c/code\u003e.\u003c/p\u003e\n\u003ch3\u003eFinishing Up\u003c/h3\u003e\n\u003cp\u003eIf you followed the guide and \u003cstrong\u003eForce provision\u003c/strong\u003eed your \u003cstrong\u003eUSG\u003c/strong\u003e you should be good to go.\nMy linux hosts picked up the IPv6 IPs automatically, and on my Apple products I just disabled then re-enabled Wifi.\u003c/p\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2019-11-05T13:07:15Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"a89f927e3c656e9526008e3aee6a678d","projectId":"","tags":[{"id":"d35708b28e494df332afc857416da120","name":"Unifi","slug":"unifi"},{"id":"75282f5450b7d8d38ca5570b768f4816","name":"Ubiquiti","slug":"ubiquiti"},{"id":"ef5b5edfc8d3f826a59d61a4be854fd8","name":"Networking","slug":"networking"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"901f2fab2646e83671fe8f6e5500c117","siteId":"projectable","slug":"a-simple-etcher-6-slot-sd-card-jig","title":"A simple Etcher 6 slot SD card jig","markdown":"I've been working with Kubernetes a lot lately, I am using Kubernetes at [Filament](https://filament.com) as a way to manage sandbox blockchain environments, so naturally I wanted to try and replicate this environment using Raspberry Pis. This is actually easier said than done, even though the 3B/3B+ has 1GB of RAM, once you start bringing in persistent storage layers it becomes apparent that it just isn't enough memory to run anything but the simplest of kubernetes containers.\n\n![](/content/images/2018/11/IMG_6776.jpg)\n\nThroughout the testing and validation of Kubernetes on my 6 node 3B cluster I was constantly re-imaging the SD cards. I tested Raspbian and Ubuntu 18 64bit, with various full resets along the way. The process of imaging 6 cards with only 1 SD reader is a bit monotonous, so I set out to find out what options there were for multiple card writing systems. I was very quickly overwhelmed by the $1500+ SD card duplication systems out there and I realized I would have to cobble something together myself.\n\n####Doing the jig\n\nA quick search on Amazon and I found a [USB 3.0 dual SD/Micro SD card reader](http://a.co/d/fkdFMf3), I figured I could get 3 of these and plug them in to a hub to give me the 6 card slots I needed. I was then pleasantly surprised to find the manufacturer of the card readers also had a [4 port USB 3.0 hub](http://a.co/d/bhqes7W) that was the same size! Once I got all the hardware in hand I could see that the hub was almost exactly the same base dimensions as the 3 dual card readers stacked next to each other!\n\n![](/content/images/2018/11/IMG_6730.jpg)\n![](/content/images/2018/11/IMG_6731.jpg)\n\nI designed a simple 3D printable enclosure in Fusion360 and then printed it using Proto-Pasta Metallic Blue HTPLA. It is held together using M3 hardware.\n\n![](/content/images/2018/11/Screen-Shot-2018-11-19-at-12-50-13-PM.png)\n\nThe finished enclosure keeps everything together, and doesn't look half bad!\n\n![](/content/images/2018/11/IMG_6733.jpg)\n![](/content/images/2018/11/IMG_6735.jpg)\n\nThis setup gives you 6 usable SD/Micro SD card slots with 1 USB 3.0 cable, and a spare USB 3.0 port to daisy-chain more of these jigs if needed! [Etcher](https://www.balena.io/etcher/) can write to all of the SD cards at the same time, cutting the burn time significantly!\n\n![](/content/images/2018/11/Screen-Shot-2018-11-13-at-7-58-50-AM.png)\n\nA big thanks to [Balena](https://www.balena.io) (previously Resin.io) for releasing [Etcher](https://www.balena.io/etcher/) to the world, its a fantastic tool that scales well!\n\n####Go make one yourself!\nAll of the STLs and the BOM can be found on Thingiverse: https://www.thingiverse.com/thing:3217069\n\n\n","html":"\u003cp\u003eI\u0026#39;ve been working with Kubernetes a lot lately, I am using Kubernetes at \u003ca href=\"https://filament.com\" rel=\"nofollow\"\u003eFilament\u003c/a\u003e as a way to manage sandbox blockchain environments, so naturally I wanted to try and replicate this environment using Raspberry Pis. This is actually easier said than done, even though the 3B/3B+ has 1GB of RAM, once you start bringing in persistent storage layers it becomes apparent that it just isn\u0026#39;t enough memory to run anything but the simplest of kubernetes containers.\u003c/p\u003e\n\u003cimg src=\"/content/images/2018/11/IMG_6776.jpg\" alt=\"\"\u003e\n\u003cp\u003eThroughout the testing and validation of Kubernetes on my 6 node 3B cluster I was constantly re-imaging the SD cards. I tested Raspbian and Ubuntu 18 64bit, with various full resets along the way. The process of imaging 6 cards with only 1 SD reader is a bit monotonous, so I set out to find out what options there were for multiple card writing systems. I was very quickly overwhelmed by the $1500+ SD card duplication systems out there and I realized I would have to cobble something together myself.\u003c/p\u003e\n\u003ch4\u003eDoing the jig\u003c/h4\u003e\n\u003cp\u003eA quick search on Amazon and I found a \u003ca href=\"http://a.co/d/fkdFMf3\" rel=\"nofollow\"\u003eUSB 3.0 dual SD/Micro SD card reader\u003c/a\u003e, I figured I could get 3 of these and plug them in to a hub to give me the 6 card slots I needed. I was then pleasantly surprised to find the manufacturer of the card readers also had a \u003ca href=\"http://a.co/d/bhqes7W\" rel=\"nofollow\"\u003e4 port USB 3.0 hub\u003c/a\u003e that was the same size! Once I got all the hardware in hand I could see that the hub was almost exactly the same base dimensions as the 3 dual card readers stacked next to each other!\u003c/p\u003e\n\u003cimg src=\"/content/images/2018/11/IMG_6730.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2018/11/IMG_6731.jpg\" alt=\"\"\u003e\n\u003cp\u003eI designed a simple 3D printable enclosure in Fusion360 and then printed it using Proto-Pasta Metallic Blue HTPLA. It is held together using M3 hardware.\u003c/p\u003e\n\u003cimg src=\"/content/images/2018/11/Screen-Shot-2018-11-19-at-12-50-13-PM.png\" alt=\"\"\u003e\n\u003cp\u003eThe finished enclosure keeps everything together, and doesn\u0026#39;t look half bad!\u003c/p\u003e\n\u003cimg src=\"/content/images/2018/11/IMG_6733.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2018/11/IMG_6735.jpg\" alt=\"\"\u003e\n\u003cp\u003eThis setup gives you 6 usable SD/Micro SD card slots with 1 USB 3.0 cable, and a spare USB 3.0 port to daisy-chain more of these jigs if needed! \u003ca href=\"https://www.balena.io/etcher/\" rel=\"nofollow\"\u003eEtcher\u003c/a\u003e can write to all of the SD cards at the same time, cutting the burn time significantly!\u003c/p\u003e\n\u003cimg src=\"/content/images/2018/11/Screen-Shot-2018-11-13-at-7-58-50-AM.png\" alt=\"\"\u003e\n\u003cp\u003eA big thanks to \u003ca href=\"https://www.balena.io\" rel=\"nofollow\"\u003eBalena\u003c/a\u003e (previously Resin.io) for releasing \u003ca href=\"https://www.balena.io/etcher/\" rel=\"nofollow\"\u003eEtcher\u003c/a\u003e to the world, its a fantastic tool that scales well!\u003c/p\u003e\n\u003ch4\u003eGo make one yourself!\u003c/h4\u003e\n\u003cp\u003eAll of the STLs and the BOM can be found on Thingiverse: \u003ca href=\"https://www.thingiverse.com/thing:3217069\" rel=\"nofollow\"\u003ehttps://www.thingiverse.com/thing:3217069\u003c/a\u003e\u003c/p\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2018-11-19T17:53:22Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"453a5a37a265940047559741a496164e","projectId":"","tags":[{"id":"b529314e428273696b02c474dcf56132","name":"Raspberry Pi","slug":"raspberry-pi"},{"id":"1e4c1c80a23c5c7fa3f6f43985fffb50","name":"Kubernetes","slug":"kubernetes"},{"id":"41dfeb58d853ede0e7f6fb6f9e24536c","name":"Etcher","slug":"etcher"},{"id":"e58b4788e99c9f53befd1e47b8073250","name":"3D Printing","slug":"3d-printing"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"7a23b4fc9f63f7327ef52913289d4327","siteId":"projectable","slug":"sim-racing-motion-rig-v2-updates","title":"Sim racing motion rig v2 updates","markdown":"With the rekindled interest in Dirt Rally that my [Car-cade](http://projectable.me/my-dirt-rally-tabletop-car-cade-game/) has given me I had a bit of a yearning to get Dirt Rally working nicely in VR on the motion rig. You can read more about my motion rig here: http://projectable.me/my-sim-racing-motion-rig-version-2/\n\n[![](/content/images/2017/12/IMG_3182.jpg)](http://projectable.me/my-dirt-rally-tabletop-car-cade-game/)\n\n####The problems\nThe issue I had was 2 fold: #1 the motion was too violent, and #2 even with a GTX1080Ti the framerate was really inconsistent, leading to really bad motion sickness. I had put a small amount of time in to trying to figure it out, but in the end I just gave up due to feeling quite ill.\n\n\n####The Fixes\nI tackled the motion aspect first, it took some motion profile tuning inside SimXperience Sim Commander, mainly smoothing for the device and a smoothing filter on acceleration/braking/cornering g-forces. With the heavily smoothed profile things were less back-breaking.\n\nSecondly I dived in to the graphics quality, testing how each change \"felt\" and eventually ending up with a profile that was mostly medium and low settings. The only things left on high were track and car detail. Its a bit of a shame to end up with such low settings on such a high end graphics card, but thats what I ended up with after \"gut checking\" them.\n\nAfter testing and doing a few runs I was quite happy that I no longer wanted to loose my lunch. It shows just how important high FPS without any stutter is to avoid motion sickness in VR.\n\n####Some tweaking\nDuring all the testing I found that the actuator bar was hitting the back of the seat, meaning there was a LOT of flex and disconnect between the seat and the seat platform. I quickly bent up a bracket to fix this. The seat had an M8 bolt at the top that I used to mount back to the top of the seat platform. This extra rigidity helps a LOT! It's not pretty, but it works. I had to use a rubber bushing between the bracket and the seat, as without it there was a lot of actuator noise that was resinating in the seat itself.\n\n![](/content/images/2017/12/IMG_3346-1.JPG)\n![](/content/images/2017/12/IMG_3347.JPG)\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/wZdebttwHCM\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n\n####Final Thoughts\nSo there we have it. Small tweaks and changes to the rig to help enhance the experience, and some game settings tweaks along with motion profile changes to make Dirt Rally a playable experience in motion VR!\n\n![](/content/images/2017/12/IMG_3348-1.JPG)\n![](/content/images/2017/12/IMG_3349.JPG)\n![](/content/images/2017/12/IMG_3350.JPG)\n\n\n####System Specifications\n\n#####PC\n- i7-5820K\n- 32G ram\n- GTX 1080Ti\n- Benq W1080ST projector projecting on the wall\n- Oculus Rift CV1\n\n#####Motion Rig\n- Custom 8020 aluminum extrusion rig\n- SimXperience DIY motion platform\n- Fanatec CSW V2\n- Fanatec CSW Pedals V3\n- Fanatec Sequential Shifter V1.5\n- Fanatec Handbrake","html":"\u003cp\u003eWith the rekindled interest in Dirt Rally that my \u003ca href=\"http://projectable.me/my-dirt-rally-tabletop-car-cade-game/\" rel=\"nofollow\"\u003eCar-cade\u003c/a\u003e has given me I had a bit of a yearning to get Dirt Rally working nicely in VR on the motion rig. You can read more about my motion rig here: \u003ca href=\"http://projectable.me/my-sim-racing-motion-rig-version-2/\" rel=\"nofollow\"\u003ehttp://projectable.me/my-sim-racing-motion-rig-version-2/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://projectable.me/my-dirt-rally-tabletop-car-cade-game/\" rel=\"nofollow\"\u003e\u003cimg src=\"/content/images/2017/12/IMG_3182.jpg\" alt=\"\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch4\u003eThe problems\u003c/h4\u003e\n\u003cp\u003eThe issue I had was 2 fold: #1 the motion was too violent, and #2 even with a GTX1080Ti the framerate was really inconsistent, leading to really bad motion sickness. I had put a small amount of time in to trying to figure it out, but in the end I just gave up due to feeling quite ill.\u003c/p\u003e\n\u003ch4\u003eThe Fixes\u003c/h4\u003e\n\u003cp\u003eI tackled the motion aspect first, it took some motion profile tuning inside SimXperience Sim Commander, mainly smoothing for the device and a smoothing filter on acceleration/braking/cornering g-forces. With the heavily smoothed profile things were less back-breaking.\u003c/p\u003e\n\u003cp\u003eSecondly I dived in to the graphics quality, testing how each change \u0026#34;felt\u0026#34; and eventually ending up with a profile that was mostly medium and low settings. The only things left on high were track and car detail. Its a bit of a shame to end up with such low settings on such a high end graphics card, but thats what I ended up with after \u0026#34;gut checking\u0026#34; them.\u003c/p\u003e\n\u003cp\u003eAfter testing and doing a few runs I was quite happy that I no longer wanted to loose my lunch. It shows just how important high FPS without any stutter is to avoid motion sickness in VR.\u003c/p\u003e\n\u003ch4\u003eSome tweaking\u003c/h4\u003e\n\u003cp\u003eDuring all the testing I found that the actuator bar was hitting the back of the seat, meaning there was a LOT of flex and disconnect between the seat and the seat platform. I quickly bent up a bracket to fix this. The seat had an M8 bolt at the top that I used to mount back to the top of the seat platform. This extra rigidity helps a LOT! It\u0026#39;s not pretty, but it works. I had to use a rubber bushing between the bracket and the seat, as without it there was a lot of actuator noise that was resinating in the seat itself.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/12/IMG_3346-1.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/12/IMG_3347.JPG\" alt=\"\"\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/wZdebttwHCM\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003ch4\u003eFinal Thoughts\u003c/h4\u003e\n\u003cp\u003eSo there we have it. Small tweaks and changes to the rig to help enhance the experience, and some game settings tweaks along with motion profile changes to make Dirt Rally a playable experience in motion VR!\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/12/IMG_3348-1.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/12/IMG_3349.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/12/IMG_3350.JPG\" alt=\"\"\u003e\n\u003ch4\u003eSystem Specifications\u003c/h4\u003e\n\u003ch5\u003ePC\u003c/h5\u003e\n\u003cul\u003e\n\u003cli\u003ei7-5820K\u003c/li\u003e\n\u003cli\u003e32G ram\u003c/li\u003e\n\u003cli\u003eGTX 1080Ti\u003c/li\u003e\n\u003cli\u003eBenq W1080ST projector projecting on the wall\u003c/li\u003e\n\u003cli\u003eOculus Rift CV1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch5\u003eMotion Rig\u003c/h5\u003e\n\u003cul\u003e\n\u003cli\u003eCustom 8020 aluminum extrusion rig\u003c/li\u003e\n\u003cli\u003eSimXperience DIY motion platform\u003c/li\u003e\n\u003cli\u003eFanatec CSW V2\u003c/li\u003e\n\u003cli\u003eFanatec CSW Pedals V3\u003c/li\u003e\n\u003cli\u003eFanatec Sequential Shifter V1.5\u003c/li\u003e\n\u003cli\u003eFanatec Handbrake\u003c/li\u003e\n\u003c/ul\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2017-12-03T02:51:45Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"5dfef4da0e8654d6e59930c9093f63ff","projectId":"","tags":[{"id":"ecaaace3f367d1a9865ae0933d53d715","name":"Sim Racing","slug":"sim-racing"},{"id":"9c4230a56ffd914aade79798824d9d23","name":"SimXperience","slug":"simxperience"},{"id":"ab4bc19e35909615ae7bc6a344a2b50a","name":"Motion Simulator","slug":"motion-simulator"},{"id":"bda7da089cef0417916d7e03950af340","name":"Dirt Rally","slug":"dirt-rally"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"94b2de371382ec793a64ed49343c14c6","siteId":"projectable","slug":"talkiepi-nov2017-updates","title":"talkiepi Updates (November 2017)","markdown":"##Introducing [talkiepi](https://github.com/dchote/talkiepi)\n\n[talkiepi](https://github.com/dchote/talkiepi) is a wifi \"walkie\" talkie for your kids and their friends. It provides a very simple \"push to talk\" interface. When you push the button and talk, all the other talkiepis in the channel will hear what is being said.\n\n##November 2017 Updates\n[talkiepi](https://github.com/dchote/talkiepi) has been out in the world for a little over a year now and it has been quite a successful project! I have seen 4+ different magazine articles (read some: [here](https://www.raspberrypi.org/magpi-issues/MagPi62.pdf), [here](https://issuu.com/futurepublishing/docs/piu02.issuu/2?ff=true), and [here](https://magazinesubscriptionsdigital.zinio.com/browse/issues/index.jsp;jsessionid=FCDE8D752BEF8FE767D9CF82D567CB65.prd-main-news2?skuId=416414901\u0026prnt=\u0026categoryId=cat1960026)), and I have even seen it included in school course curriculum!!\n\nI am getting back in to [Go](https://golang.org) development for work, and the process of working in [Go](https://golang.org) again gave me the hankering to update [talkiepi](https://github.com/dchote/talkiepi) and try and work out some of its kinks. I'll be working on enhancements to talkiepi over the next few weeks when I get the time. My goal is to get talkiepi working flawlessly on a [Raspberry Pi Zero W](https://www.adafruit.com/product/3400).\n\n**Talkiepi can be found over on github: https://github.com/dchote/talkiepi**","html":"\u003ch2\u003eIntroducing \u003ca href=\"https://github.com/dchote/talkiepi\" rel=\"nofollow\"\u003etalkiepi\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/dchote/talkiepi\" rel=\"nofollow\"\u003etalkiepi\u003c/a\u003e is a wifi \u0026#34;walkie\u0026#34; talkie for your kids and their friends. It provides a very simple \u0026#34;push to talk\u0026#34; interface. When you push the button and talk, all the other talkiepis in the channel will hear what is being said.\u003c/p\u003e\n\u003ch2\u003eNovember 2017 Updates\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/dchote/talkiepi\" rel=\"nofollow\"\u003etalkiepi\u003c/a\u003e has been out in the world for a little over a year now and it has been quite a successful project! I have seen 4+ different magazine articles (read some: \u003ca href=\"https://www.raspberrypi.org/magpi-issues/MagPi62.pdf\" rel=\"nofollow\"\u003ehere\u003c/a\u003e, \u003ca href=\"https://issuu.com/futurepublishing/docs/piu02.issuu/2?ff=true\" rel=\"nofollow\"\u003ehere\u003c/a\u003e, and \u003ca href=\"https://magazinesubscriptionsdigital.zinio.com/browse/issues/index.jsp;jsessionid=FCDE8D752BEF8FE767D9CF82D567CB65.prd-main-news2?skuId=416414901\u0026amp;prnt=\u0026amp;categoryId=cat1960026\" rel=\"nofollow\"\u003ehere\u003c/a\u003e), and I have even seen it included in school course curriculum!!\u003c/p\u003e\n\u003cp\u003eI am getting back in to \u003ca href=\"https://golang.org\" rel=\"nofollow\"\u003eGo\u003c/a\u003e development for work, and the process of working in \u003ca href=\"https://golang.org\" rel=\"nofollow\"\u003eGo\u003c/a\u003e again gave me the hankering to update \u003ca href=\"https://github.com/dchote/talkiepi\" rel=\"nofollow\"\u003etalkiepi\u003c/a\u003e and try and work out some of its kinks. I\u0026#39;ll be working on enhancements to talkiepi over the next few weeks when I get the time. My goal is to get talkiepi working flawlessly on a \u003ca href=\"https://www.adafruit.com/product/3400\" rel=\"nofollow\"\u003eRaspberry Pi Zero W\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTalkiepi can be found over on github: \u003ca href=\"https://github.com/dchote/talkiepi\" rel=\"nofollow\"\u003ehttps://github.com/dchote/talkiepi\u003c/a\u003e\u003c/strong\u003e\u003c/p\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2017-11-17T15:15:46Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"f1b2883a1a2e99060f5e4a6a2f8ccebd","projectId":"","tags":[{"id":"b223b3e2ba0e78e7e6a6a8ff4349517d","name":"talkiepi","slug":"talkiepi"},{"id":"b529314e428273696b02c474dcf56132","name":"Raspberry Pi","slug":"raspberry-pi"},{"id":"88aab2a2ba262f200b248f0074011445","name":"WIFI","slug":"wifi"},{"id":"e2e48067ff28749272dbdc37a0f2023d","name":"golang","slug":"golang"},{"id":"8600a98484e169ed96ea6fbe2a034ccc","name":"VOIP","slug":"voip"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"e1df6d8cca38bcc838098d61f321952d","siteId":"projectable","slug":"my-dirt-rally-tabletop-car-cade-game","title":"My Dirt Rally tabletop car-cade game","markdown":"For the longest time I've had the idea to put a Raspberry Pi into one of those kids car toys from the 80s. \n\n![](/content/images/2017/11/05-1.jpg)\n\nIn August 2017 I was beat to the punch by [Matt Brailsford](https://twitter.com/mattbrailsford) when he published his Tomy Turnin' Turbo Dashboard Outrun Arcade on Twitter: https://twitter.com/circuitbeard/status/902513198330499073\n\n\u003cp align=\"center\"\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/r21Zfmw7moI\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\u003c/p\u003e\n\n**His project was so fantastic, I had to come up with something entirely new...**\n\n####The beginning\n\nI already had an Intel Atom powered dev board, the [MinnowBoard](https://minnowboard.org). Surprisingly, SteamOS installed on it without any issues.\n\n![](/content/images/2017/11/IMG_1989.jpg)\n![](/content/images/2017/11/IMG_1988.jpg)\n\nAfter playing around with SteamOS and [Dirt Rally](https://www.dirtgame.com) on the [MinnowBoard](https://minnowboard.org) without much luck (talking in frames per minute, not frames per second), I settled on the idea of building a full Intel powered system running SteamOS. I would then work on designing and 3D printing the entire enclosure from scratch. \n\n\n###The Dirt Rally Car-cade!\n\n####Inspiration\nInitially I was going to design it with cues from the Audi Quattro, but I very quickly switched over to the 1995 Subaru Impreza, which is my preferred car in the game. \n\n\u003cp align=\"center\"\u003e\n![](/content/images/2017/11/IMG_2580.jpg)\n\u003c/p\u003e\n\nI ordered the smallest motherboard I could find that had the features I needed, along with the rest of the components that I didn't already have. \n\n####System Components\n* Motherboard: [Asus H110S2/CSM](https://www.newegg.com/Product/Product.aspx?Item=N82E16813132897)\n* CPU: [Intel G4500](https://www.newegg.com/Product/Product.aspx?Item=N82E16819117624)\n* CPU Cooler: [SILVERSTONE NT07-115X](https://www.newegg.com/Product/Product.aspx?Item=N82E16835220067)\n* Ram: [G.SKILL Ripjaws 8GB](https://www.newegg.com/Product/Product.aspx?Item=N82E16820232146)\n* Storage: [Samsung 950 Pro M.2](https://www.newegg.com/Product/Product.aspx?Item=N82E16820147467)\n\n####Other Components\n* LCD: [7\" 1024x600 capacitive touch LCD](https://www.ebay.com/itm/7-Inch-HDMI-Capacitive-IPS-Display-LCD-for-Raspberry-Pi-1024-600-/262941998848?roken=cUgayN\u0026soutkn=unc8RL)\n* USB Controller: [Pimoroni Picade Controller PCB](https://www.adafruit.com/product/2708)\n* 2x Speakers: [3W enclosed speaker from Adafruit](https://www.adafruit.com/product/3351)\n* Push Buttons: [Pack of 10 black pushbuttons](http://a.co/cee6jZP)\n* Potentiometer: [Pack of 5 10k ohm linear potentiometers](http://a.co/blt4qxJ)\n\n####The Design Process\nThe process of designing and printing was an iterative one. I initially designed and iterated the steering and throttle components until I was happy with how they worked. The USB controller interface is managed by a [Pimoroni Picade PCB](https://shop.pimoroni.com/products/picade-controller-board) (it's basically an arduino with an onboard amplifier for speakers). The steering and throttle are analog inputs using potentiometers. The steering wheel and throttle both self center (kindof) using rubber bands integrated into my design.\n\n![](/content/images/2017/11/IMG_2022.jpg)\n![](/content/images/2017/11/IMG_2047.jpg)\n![](/content/images/2017/11/IMG_2096.jpg)\n![](/content/images/2017/11/IMG_2105.jpg)\n![](/content/images/2017/11/IMG_2106.jpg)\n\nI then went about planning the smallest footprint possible for the Car-cade... Ensuring that I was able to 3D print everything using my Anet A8.\n\n\u003cp align=\"center\"\u003e\n![](/content/images/2017/11/IMG_2114.jpg)\n![](/content/images/2017/11/IMG_2115.jpg)\n\u003c/p\u003e\n\nAs I worked through designing each part and printing it, I got a better picture of how everything would come together. It didn't take much effort once the ball was in motion.\n\n![](/content/images/2017/11/IMG_2182.jpg)\n![](/content/images/2017/11/IMG_2262.jpg)\n\n####Social Media Interest\nI recorded a video of my friend Eric playing on the Car-cade and put it up on Twitter showing off the progress. A few large social media publishers contacted me and asked if they could share the video. It got quite a lot of views on their networks!\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/Ss-si82NqcI\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n####Designing Around the Parts\nEverything was designed around being as small as possible. As you can see, minimal clearance was given around the motherboard. I had a balancing act between the maximum print area on my 3D printer and how much room I needed for cables plugging in to the motherboard.\n\n![](/content/images/2017/11/IMG_2342.jpg)\n![](/content/images/2017/11/IMG_2343.jpg)\n![](/content/images/2017/11/IMG_2344.jpg)\n\nOnce I had all the components finished and the first prototype assembled I went on to experiment with finishing methods.\n\n![](/content/images/2017/11/IMG_2359.jpg)\n![](/content/images/2017/11/IMG_2360.jpg)\n\n\n####Post-Processing\nInitially I thought that I should sand, primer, paint, then clear coat. I managed to pick up a can of World Rally Blue paint. It looks amazing... But after attempting the process I realized it was too much effort to go to for a project of this size.\n\n![](/content/images/2017/11/IMG_2467.jpg)\n![](/content/images/2017/11/IMG_2474.jpg)\n![](/content/images/2017/11/IMG_2526.jpg)\n![](/content/images/2017/11/IMG_2523.jpg)\n\n\n####Project Recognition\nIt was at this time that I received a package from Codemasters!!! I got sent SWAG!!\n\n![](/content/images/2017/11/IMG_2531.jpg)\n![](/content/images/2017/11/IMG_2533.jpg)\n![](/content/images/2017/11/IMG_2534.jpg)\n![](/content/images/2017/11/IMG_2535.jpg)\n\nMany thanks to the Dirt team at Codemasters. It's awesome to see them support the community the way they do!!\n\n\n####Post-Processing, Part 2\nAfter a lot of debating about the pros and cons of extensive post processing to finish 3d prints, I decided to switch to printing the parts using **different colored filament**. This process took a **LONG** time. I experimented with 4 different rolls of blue filament alone. I also spent the time to break up the design so that I could print the rear panel in different pieces and glue them together. I ended up going with [ColorFabb Ultra Marine Blue PLA](https://colorfabb.com/ultra-marine-blue) for the bulk of the enclosure. The dashboard is printed in [ProtoPasta Matte Fiber PLA](https://www.proto-pasta.com/products/high-performance-htpla-matte-fiber), the base, rear panel insert, and all the internal mounts are printed in Hatchbox Black PLA, and the headlights are printed in Hatchbox Glow in the Dark PLA.\n\n![](/content/images/2017/11/IMG_2586.jpg)\n![](/content/images/2017/11/IMG_2587.jpg)\n![](/content/images/2017/11/IMG_2836.jpg)\n\nThe steering wheel and throttle are printed using [ProtoPasta Polishable Stainless Steel PLA](https://www.proto-pasta.com/collections/exotic-composite-pla/products/stainless-steel-pla), the steering wheel rim has been painted with PlastiDip Rubber Paint, and the small stripe is Testors orange.\n\n![](/content/images/2017/11/IMG_3057.jpg)\n![](/content/images/2017/11/IMG_3078.jpg)\n![](/content/images/2017/11/IMG_3092.jpg)\n![](/content/images/2017/11/IMG_3096.jpg)\n\n\n####Final Assembly\nWith all the parts finally printed, I went about assembling the final product!\n\n![](/content/images/2017/11/IMG_3129.jpg)\n![](/content/images/2017/11/IMG_3131.jpg)\n![](/content/images/2017/11/IMG_3132.jpg)\n![](/content/images/2017/11/IMG_3133.jpg)\n![](/content/images/2017/11/IMG_3144.jpg)\n![](/content/images/2017/11/IMG_3145.jpg)\n\n####Final Touches\nAfter assembly, I used my Cricut to cut some vinyl decals, giving us the finished Dirt Rally Car-cade!\n\n![](/content/images/2017/11/IMG_3182-1.jpg)\n![](/content/images/2017/11/IMG_3183.jpg)\n![](/content/images/2017/11/IMG_3184.jpg)\n![](/content/images/2017/11/IMG_3185.jpg)\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RuAd2cMFF6Y\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n###🍌Banana For Scale 🤣\n\n![](/content/images/2017/11/IMG_3187.jpg)\n![](/content/images/2017/11/IMG_3188.jpg)\n\n####Gameplay Videos\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/ieWfV6zoHNw\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n----\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/bi_dIsvflY4\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n----\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/8HmKj4H8PdA\" frameborder=\"0\" gesture=\"media\" allow=\"encrypted-media\" allowfullscreen\u003e\u003c/iframe\u003e\n\n\n####More About the Car-cade\nI have a few more videos of the Car-cade prototype on YouTube: https://www.youtube.com/playlist?list=PLGYb5mIm0WYwEnWkQ1j9M1dFWMHfyMOBq\n\n\n####Build Your OWN Car-cade!\nI have published the 3d objects, and will **SOON** be writing build instructions over on github: https://github.com/dchote/carcade","html":"\u003cp\u003eFor the longest time I\u0026#39;ve had the idea to put a Raspberry Pi into one of those kids car toys from the 80s.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/05-1.jpg\" alt=\"\"\u003e\n\u003cp\u003eIn August 2017 I was beat to the punch by \u003ca href=\"https://twitter.com/mattbrailsford\" rel=\"nofollow\"\u003eMatt Brailsford\u003c/a\u003e when he published his Tomy Turnin\u0026#39; Turbo Dashboard Outrun Arcade on Twitter: \u003ca href=\"https://twitter.com/circuitbeard/status/902513198330499073\" rel=\"nofollow\"\u003ehttps://twitter.com/circuitbeard/status/902513198330499073\u003c/a\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/r21Zfmw7moI\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHis project was so fantastic, I had to come up with something entirely new...\u003c/strong\u003e\u003c/p\u003e\n\u003ch4\u003eThe beginning\u003c/h4\u003e\n\u003cp\u003eI already had an Intel Atom powered dev board, the \u003ca href=\"https://minnowboard.org\" rel=\"nofollow\"\u003eMinnowBoard\u003c/a\u003e. Surprisingly, SteamOS installed on it without any issues.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_1989.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_1988.jpg\" alt=\"\"\u003e\n\u003cp\u003eAfter playing around with SteamOS and \u003ca href=\"https://www.dirtgame.com\" rel=\"nofollow\"\u003eDirt Rally\u003c/a\u003e on the \u003ca href=\"https://minnowboard.org\" rel=\"nofollow\"\u003eMinnowBoard\u003c/a\u003e without much luck (talking in frames per minute, not frames per second), I settled on the idea of building a full Intel powered system running SteamOS. I would then work on designing and 3D printing the entire enclosure from scratch.\u003c/p\u003e\n\u003ch3\u003eThe Dirt Rally Car-cade!\u003c/h3\u003e\n\u003ch4\u003eInspiration\u003c/h4\u003e\n\u003cp\u003eInitially I was going to design it with cues from the Audi Quattro, but I very quickly switched over to the 1995 Subaru Impreza, which is my preferred car in the game.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2580.jpg\" alt=\"\"\u003e\n\u003c/p\u003e\n\u003cp\u003eI ordered the smallest motherboard I could find that had the features I needed, along with the rest of the components that I didn\u0026#39;t already have.\u003c/p\u003e\n\u003ch4\u003eSystem Components\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eMotherboard: \u003ca href=\"https://www.newegg.com/Product/Product.aspx?Item=N82E16813132897\" rel=\"nofollow\"\u003eAsus H110S2/CSM\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eCPU: \u003ca href=\"https://www.newegg.com/Product/Product.aspx?Item=N82E16819117624\" rel=\"nofollow\"\u003eIntel G4500\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eCPU Cooler: \u003ca href=\"https://www.newegg.com/Product/Product.aspx?Item=N82E16835220067\" rel=\"nofollow\"\u003eSILVERSTONE NT07-115X\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eRam: \u003ca href=\"https://www.newegg.com/Product/Product.aspx?Item=N82E16820232146\" rel=\"nofollow\"\u003eG.SKILL Ripjaws 8GB\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eStorage: \u003ca href=\"https://www.newegg.com/Product/Product.aspx?Item=N82E16820147467\" rel=\"nofollow\"\u003eSamsung 950 Pro M.2\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4\u003eOther Components\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eLCD: \u003ca href=\"https://www.ebay.com/itm/7-Inch-HDMI-Capacitive-IPS-Display-LCD-for-Raspberry-Pi-1024-600-/262941998848?roken=cUgayN\u0026amp;soutkn=unc8RL\" rel=\"nofollow\"\u003e7\u0026#34; 1024x600 capacitive touch LCD\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eUSB Controller: \u003ca href=\"https://www.adafruit.com/product/2708\" rel=\"nofollow\"\u003ePimoroni Picade Controller PCB\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e2x Speakers: \u003ca href=\"https://www.adafruit.com/product/3351\" rel=\"nofollow\"\u003e3W enclosed speaker from Adafruit\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePush Buttons: \u003ca href=\"http://a.co/cee6jZP\" rel=\"nofollow\"\u003ePack of 10 black pushbuttons\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003ePotentiometer: \u003ca href=\"http://a.co/blt4qxJ\" rel=\"nofollow\"\u003ePack of 5 10k ohm linear potentiometers\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4\u003eThe Design Process\u003c/h4\u003e\n\u003cp\u003eThe process of designing and printing was an iterative one. I initially designed and iterated the steering and throttle components until I was happy with how they worked. The USB controller interface is managed by a \u003ca href=\"https://shop.pimoroni.com/products/picade-controller-board\" rel=\"nofollow\"\u003ePimoroni Picade PCB\u003c/a\u003e (it\u0026#39;s basically an arduino with an onboard amplifier for speakers). The steering and throttle are analog inputs using potentiometers. The steering wheel and throttle both self center (kindof) using rubber bands integrated into my design.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2022.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2047.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2096.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2105.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2106.jpg\" alt=\"\"\u003e\n\u003cp\u003eI then went about planning the smallest footprint possible for the Car-cade... Ensuring that I was able to 3D print everything using my Anet A8.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2114.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2115.jpg\" alt=\"\"\u003e\n\u003c/p\u003e\n\u003cp\u003eAs I worked through designing each part and printing it, I got a better picture of how everything would come together. It didn\u0026#39;t take much effort once the ball was in motion.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2182.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2262.jpg\" alt=\"\"\u003e\n\u003ch4\u003eSocial Media Interest\u003c/h4\u003e\n\u003cp\u003eI recorded a video of my friend Eric playing on the Car-cade and put it up on Twitter showing off the progress. A few large social media publishers contacted me and asked if they could share the video. It got quite a lot of views on their networks!\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/Ss-si82NqcI\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003ch4\u003eDesigning Around the Parts\u003c/h4\u003e\n\u003cp\u003eEverything was designed around being as small as possible. As you can see, minimal clearance was given around the motherboard. I had a balancing act between the maximum print area on my 3D printer and how much room I needed for cables plugging in to the motherboard.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2342.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2343.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2344.jpg\" alt=\"\"\u003e\n\u003cp\u003eOnce I had all the components finished and the first prototype assembled I went on to experiment with finishing methods.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2359.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2360.jpg\" alt=\"\"\u003e\n\u003ch4\u003ePost-Processing\u003c/h4\u003e\n\u003cp\u003eInitially I thought that I should sand, primer, paint, then clear coat. I managed to pick up a can of World Rally Blue paint. It looks amazing... But after attempting the process I realized it was too much effort to go to for a project of this size.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2467.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2474.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2526.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2523.jpg\" alt=\"\"\u003e\n\u003ch4\u003eProject Recognition\u003c/h4\u003e\n\u003cp\u003eIt was at this time that I received a package from Codemasters!!! I got sent SWAG!!\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2531.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2533.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2534.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2535.jpg\" alt=\"\"\u003e\n\u003cp\u003eMany thanks to the Dirt team at Codemasters. It\u0026#39;s awesome to see them support the community the way they do!!\u003c/p\u003e\n\u003ch4\u003ePost-Processing, Part 2\u003c/h4\u003e\n\u003cp\u003eAfter a lot of debating about the pros and cons of extensive post processing to finish 3d prints, I decided to switch to printing the parts using \u003cstrong\u003edifferent colored filament\u003c/strong\u003e. This process took a \u003cstrong\u003eLONG\u003c/strong\u003e time. I experimented with 4 different rolls of blue filament alone. I also spent the time to break up the design so that I could print the rear panel in different pieces and glue them together. I ended up going with \u003ca href=\"https://colorfabb.com/ultra-marine-blue\" rel=\"nofollow\"\u003eColorFabb Ultra Marine Blue PLA\u003c/a\u003e for the bulk of the enclosure. The dashboard is printed in \u003ca href=\"https://www.proto-pasta.com/products/high-performance-htpla-matte-fiber\" rel=\"nofollow\"\u003eProtoPasta Matte Fiber PLA\u003c/a\u003e, the base, rear panel insert, and all the internal mounts are printed in Hatchbox Black PLA, and the headlights are printed in Hatchbox Glow in the Dark PLA.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2586.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2587.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_2836.jpg\" alt=\"\"\u003e\n\u003cp\u003eThe steering wheel and throttle are printed using \u003ca href=\"https://www.proto-pasta.com/collections/exotic-composite-pla/products/stainless-steel-pla\" rel=\"nofollow\"\u003eProtoPasta Polishable Stainless Steel PLA\u003c/a\u003e, the steering wheel rim has been painted with PlastiDip Rubber Paint, and the small stripe is Testors orange.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3057.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3078.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3092.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3096.jpg\" alt=\"\"\u003e\n\u003ch4\u003eFinal Assembly\u003c/h4\u003e\n\u003cp\u003eWith all the parts finally printed, I went about assembling the final product!\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3129.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3131.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3132.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3133.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3144.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3145.jpg\" alt=\"\"\u003e\n\u003ch4\u003eFinal Touches\u003c/h4\u003e\n\u003cp\u003eAfter assembly, I used my Cricut to cut some vinyl decals, giving us the finished Dirt Rally Car-cade!\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3182-1.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3183.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3184.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3185.jpg\" alt=\"\"\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/RuAd2cMFF6Y\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003ch3\u003e🍌Banana For Scale 🤣\u003c/h3\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3187.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/11/IMG_3188.jpg\" alt=\"\"\u003e\n\u003ch4\u003eGameplay Videos\u003c/h4\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/ieWfV6zoHNw\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003chr\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/bi_dIsvflY4\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003chr\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/8HmKj4H8PdA\" frameborder=\"0\" allow=\"encrypted-media\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003ch4\u003eMore About the Car-cade\u003c/h4\u003e\n\u003cp\u003eI have a few more videos of the Car-cade prototype on YouTube: \u003ca href=\"https://www.youtube.com/playlist?list=PLGYb5mIm0WYwEnWkQ1j9M1dFWMHfyMOBq\" rel=\"nofollow\"\u003ehttps://www.youtube.com/playlist?list=PLGYb5mIm0WYwEnWkQ1j9M1dFWMHfyMOBq\u003c/a\u003e\u003c/p\u003e\n\u003ch4\u003eBuild Your OWN Car-cade!\u003c/h4\u003e\n\u003cp\u003eI have published the 3d objects, and will \u003cstrong\u003eSOON\u003c/strong\u003e be writing build instructions over on github: \u003ca href=\"https://github.com/dchote/carcade\" rel=\"nofollow\"\u003ehttps://github.com/dchote/carcade\u003c/a\u003e\u003c/p\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":true,"publishedAt":"2017-11-14T23:38:05Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"191f45e4117fe940fb1789d761ca0c73","projectId":"","tags":[{"id":"ecaaace3f367d1a9865ae0933d53d715","name":"Sim Racing","slug":"sim-racing"},{"id":"bda7da089cef0417916d7e03950af340","name":"Dirt Rally","slug":"dirt-rally"},{"id":"da38acfa5fecf65300448f0e5e3df9f2","name":"Car-Cade","slug":"car-cade"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"72b96875d26f256ca5a8e7bea23a0319","siteId":"projectable","slug":"raspberry-pi-touchscreen-octoprint-controller","title":"Raspberry Pi Touchscreen Octoprint Controller","markdown":"As everyone knows I love my Raspberry Pis. I'll put them in whatever I can fit them in. I am in the process of finishing my 3D printer rack and I wanted to get my new Anet A8 printer on wifi so that I didn't need to shuffle the difficult to remove SD card from it when I wanted to print something.\n\n![](/content/images/2017/07/IMG_1559.jpg)\n\nAlong comes [Octoprint](http://octoprint.org)... Now, there are plenty of \"how to install octoprint on a Raspberry Pi\" documents out there, but nothing quite as pedantic as I would have liked. So I set off to do it my way.\n\nThis project uses a fantastic Adafruit designed 3D printed case: https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/3d-printed-case to wrap a [Raspberry Pi 3](https://www.adafruit.com/product/3055) + [Adafruit PiTFT Plus 3.5\" touch screen](https://www.adafruit.com/product/2441).\n\n![](/content/images/2017/07/IMG_1532.jpg)\n![](/content/images/2017/07/IMG_1529.jpg)\n![](/content/images/2017/07/IMG_1531.jpg)\n![](/content/images/2017/07/IMG_1530.jpg)\n\n\n### Getting Started\n\nThis is a very simple project. Here are the things you will need:\n\n* Raspberry Pi 3\n* PiTFT Plus 3.5\"\n* SD Card\n* 3D Printer\n\nMost of this is already covered in Adafruit's fantastic guide: https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/overview.\n\nMy approach has been updated and is a bit more bare bones... You will download the latest **Raspbian Jessie Lite** from https://www.raspberrypi.org/downloads/raspbian/, and burn it to your SD card. \n\nDo the usual Raspberry Pi setup process... Change the default password, enable SSH, get on to your wifi, etc. Once raspbian is running and secured on your Pi3 you can proceed with this guide.\n\n---\n\n### Install required packages\n\nAs root (`sudo -i`), please do the following:\n```\napt-get install python-pip python-dev python-setuptools python-virtualenv git libyaml-dev build-essential chromium-browser raspi-gpio xcompmgr dbus-x11 libgl1-mesa-dri xserver-xorg xserver-xorg-video-fbdev xserver-xorg-input-evdev xinit xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable xinput ttf-mscorefonts-installer xinput-calibrator\n```\n---\n\n### Base setup\n\nCreate the octoprint user. This user will be used to run both the backend and the frontend of octoprint:\n\n```\nadduser --disabled-password --disabled-login --gecos \"\" octoprint \n\nusermod -a -G cdrom,audio,video,render,plugdev,users,dialout,dip,input,tty octoprint \n```\n\nFix the xorg config permissions so that a non-root user can run X correctly:\n\n```\nchmod ug+s /usr/lib/xorg/Xorg\n```\n\nNow we will update a few X config files to optimize for this use case:\n\n**edit: `/etc/X11/Xwrapper.config`**\n```\nallowed_users=anybody\nneeds_root_rights=no\n```\n\n**edit: `/etc/kbd/config`**\n```\nBLANK_TIME=0 \nBLANK_DPMS=off \nPOWERDOWN_TIME=0 \n```\n\n**edit: `/etc/X11/xinit/xinitrc`**\n```\nxset s noblank \nxset s off \nxset -dpms \n```\n\n---\n\n### Install Octoprint\n\nSwitch from root to the octoprint user `su octoprint`:\n\n```\ncd /home/octoprint\n\ngit clone https://github.com/foosel/OctoPrint.git\n\ncd OctoPrint\n\nvirtualenv venv\n./venv/bin/pip install pip --upgrade\n./venv/bin/pip install setuptools==7.0\n./venv/bin/python setup.py install\n\nmkdir ~/.octoprint\n```\n\nThis should leave you with a happy install of octoprint located at `/home/octoprint/Octoprint`.\n\n### Setup systemd services\n\n**edit: `/etc/systemd/system/octoprint-backend.service`**\n```\n[Unit]\n Description=OctoPrint service\n\n[Service]\n User=octoprint\n ExecStart=/home/octoprint/OctoPrint/venv/bin/octoprint\n\n[Install]\n WantedBy=multi-user.target\n```\n\n\n**edit: `/etc/systemd/system/octoprint-frontend.service`**\n```\n[Unit]\nDescription = Octoprint Frontend \nAfter = systemd-user-sessions.service network.target sound.target\n\n[Service]\nUser = octoprint \nGroup = octoprint \nType = simple \nExecStart = /usr/bin/xinit /usr/bin/dbus-launch --exit-with-session /usr/bin/chromium-browser --start-maximized --window-size=480,320 --window-position=0,0 --disable-restore-background-contents --noerordialogs --disable-session-crashed-bubble --disable-infobars --disable-pinch --overscroll-history-navigation=0 --incognito --kiosk http://127.0.0.1:5000 -- :0 -s 0 dpms -nocursor -nolisten tcp vt7 \nRestart = on-abort \nRestartSec = 5\n\n[Install]\nWantedBy = multi-user.target\n```\n\nEnable both services to start at boot:\n```\nsystemctl enable octoprint-backend.service\nsystemctl enable octoprint-frontend.service\n```\n\n---\n\n### Octoprint setup\n\nLog in to your octoprint instance using a browser on your computer. It should be something like http://**YOUR___PI___IP**:5000. You can find your Pi's ip address by running `ifconfig` as root. You will be presented with the \"Setup Wizard\". Follow the instructions to complete the setup process. \n \n*To keep things simple I recommend **DISABLING** access control. I would not recommend this if you are putting your Raspberry Pi on a public network.*\n\n--- \n### TouchUI plugin\n\nTo best fit on the 480x320 screen, you should enable the TouchUI plugin. On your computer connect to the octoprint instance running on the Raspberry Pi (*instructions above*). \"Under the settings section, goto the plugin manager and search for \"Touch UI\", then click the install button.\" --[Adafruit](https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/software)\n\n---\n\n### Enable the PiTFT\n\nAdafruit has a guide: https://learn.adafruit.com/adafruit-pitft-3-dot-5-touch-screen-for-raspberry-pi/easy-install, but it doesnt seem to play nice with the latest Raspbian.\n\nRun the following as root (`sudo -i`):\n```\necho \"deb http://apt.adafruit.com/raspbian/ jessie main\" \u003e\u003e /etc/apt/sources.list\n\nwget -O - -q https://apt.adafruit.com/apt.adafruit.com.gpg.key | apt-key add -\n\napt-get update\napt-get install -y adafruit-pitft-helper\n```\n\nThen run adafruit-pitft-helper:\n```\nadafruit-pitft-helper -t 35r\n```\n\nCheck `/boot/config.txt` to ensure the defined orientation will work for you. The line to review should look like:\n```\ndtoverlay=pitft35r,rotate=90,speed=42000000,fps=20\n```\n\nThe rotate= variable tells the driver to rotate the screen 0, 90, 180, or 270 degrees. \n\n * **0** is portrait, with the bottom near the USB jacks.\n * **90** is landscape, with the bottom of the screen near the headphone jack.\n * **180** is portrait, with the top near the USB jacks.\n * **270** is landscape, with the top of the screen near the headphone jack.\n\nNow reboot (`reboot`).\n\nAfter the reboot (in theory) you will see the octoprint web interface on your PiTFT. But you will need to calibrate the touchscreen before you can interact with it.\n\n---\n\n### Touch calibration\n\nAs root (`sudo -i`) run the following:\n```\nDISPLAY=:0.0 xinput_calibrator\n```\n\nFollow the onscreen calibration process:\n\u003cp align=\"center\"\u003e\n![](/content/images/2017/07/raspberry_pi_xinput.png)\n\u003c/p\u003e\n\nOnce complete you should have a snippet of config to paste relevant to your touch screen.\n\n\n**edit: `/etc/X11/xorg.conf.d/99-calibration.conf`** and paste the output you got from xinput_calibrator.\n\n**Example output:** \n```\nSection \"InputClass\"\n\tIdentifier\t\"calibration\"\n\tMatchProduct\t\"stmpe-ts\"\n\tOption\t\"Calibration\"\t\"3932 82 141 3877\"\n\tOption\t\"SwapAxes\"\t\"1\"\n\tOption \"InvertX\" \"1\"\n\tOption \"InvertY\" \"1\"\nEndSection\n```\n\nIf your config does not contain **InvertX** or **InvertY** (*mine didn't*), you can add it manually to fix input inversion problems you may have.\n\nReboot (`reboot`), and enjoy your octoprint rig!.\n\n---\n\n### My Octoprint controller\n\nI mounted my octoprint controller to the shelving that I have my 3D printers on using double sided adhesive. Overall I am very impressed with how simple octoprint is and how well it works with my Anet A8 3D printer. \n\n![](/content/images/2017/07/IMG_1557.jpg)\n![](/content/images/2017/07/IMG_1555.jpg)\n![](/content/images/2017/07/IMG_1556.jpg)\n","html":"\u003cp\u003eAs everyone knows I love my Raspberry Pis. I\u0026#39;ll put them in whatever I can fit them in. I am in the process of finishing my 3D printer rack and I wanted to get my new Anet A8 printer on wifi so that I didn\u0026#39;t need to shuffle the difficult to remove SD card from it when I wanted to print something.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1559.jpg\" alt=\"\"\u003e\n\u003cp\u003eAlong comes \u003ca href=\"http://octoprint.org\" rel=\"nofollow\"\u003eOctoprint\u003c/a\u003e... Now, there are plenty of \u0026#34;how to install octoprint on a Raspberry Pi\u0026#34; documents out there, but nothing quite as pedantic as I would have liked. So I set off to do it my way.\u003c/p\u003e\n\u003cp\u003eThis project uses a fantastic Adafruit designed 3D printed case: \u003ca href=\"https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/3d-printed-case\" rel=\"nofollow\"\u003ehttps://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/3d-printed-case\u003c/a\u003e to wrap a \u003ca href=\"https://www.adafruit.com/product/3055\" rel=\"nofollow\"\u003eRaspberry Pi 3\u003c/a\u003e + \u003ca href=\"https://www.adafruit.com/product/2441\" rel=\"nofollow\"\u003eAdafruit PiTFT Plus 3.5\u0026#34; touch screen\u003c/a\u003e.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1532.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1529.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1531.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1530.jpg\" alt=\"\"\u003e\n\u003ch3\u003eGetting Started\u003c/h3\u003e\n\u003cp\u003eThis is a very simple project. Here are the things you will need:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRaspberry Pi 3\u003c/li\u003e\n\u003cli\u003ePiTFT Plus 3.5\u0026#34;\u003c/li\u003e\n\u003cli\u003eSD Card\u003c/li\u003e\n\u003cli\u003e3D Printer\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eMost of this is already covered in Adafruit\u0026#39;s fantastic guide: \u003ca href=\"https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/overview\" rel=\"nofollow\"\u003ehttps://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/overview\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eMy approach has been updated and is a bit more bare bones... You will download the latest \u003cstrong\u003eRaspbian Jessie Lite\u003c/strong\u003e from \u003ca href=\"https://www.raspberrypi.org/downloads/raspbian/\" rel=\"nofollow\"\u003ehttps://www.raspberrypi.org/downloads/raspbian/\u003c/a\u003e, and burn it to your SD card.\u003c/p\u003e\n\u003cp\u003eDo the usual Raspberry Pi setup process... Change the default password, enable SSH, get on to your wifi, etc. Once raspbian is running and secured on your Pi3 you can proceed with this guide.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3\u003eInstall required packages\u003c/h3\u003e\n\u003cp\u003eAs root (\u003ccode\u003esudo -i\u003c/code\u003e), please do the following:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eapt-get install python-pip python-dev python-setuptools python-virtualenv git libyaml-dev build-essential chromium-browser raspi-gpio xcompmgr dbus-x11 libgl1-mesa-dri xserver-xorg xserver-xorg-video-fbdev xserver-xorg-input-evdev xinit xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable xinput ttf-mscorefonts-installer xinput-calibrator\n\u003c/code\u003e\u003c/pre\u003e\n\u003chr\u003e\n\u003ch3\u003eBase setup\u003c/h3\u003e\n\u003cp\u003eCreate the octoprint user. This user will be used to run both the backend and the frontend of octoprint:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eadduser --disabled-password --disabled-login --gecos \u0026#34;\u0026#34; octoprint \n\nusermod -a -G cdrom,audio,video,render,plugdev,users,dialout,dip,input,tty octoprint \n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFix the xorg config permissions so that a non-root user can run X correctly:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003echmod ug+s /usr/lib/xorg/Xorg\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNow we will update a few X config files to optimize for this use case:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/X11/Xwrapper.config\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eallowed_users=anybody\nneeds_root_rights=no\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/kbd/config\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eBLANK_TIME=0 \nBLANK_DPMS=off \nPOWERDOWN_TIME=0 \n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/X11/xinit/xinitrc\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003exset s noblank \nxset s off \nxset -dpms \n\u003c/code\u003e\u003c/pre\u003e\n\u003chr\u003e\n\u003ch3\u003eInstall Octoprint\u003c/h3\u003e\n\u003cp\u003eSwitch from root to the octoprint user \u003ccode\u003esu octoprint\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003ecd /home/octoprint\n\ngit clone https://github.com/foosel/OctoPrint.git\n\ncd OctoPrint\n\nvirtualenv venv\n./venv/bin/pip install pip --upgrade\n./venv/bin/pip install setuptools==7.0\n./venv/bin/python setup.py install\n\nmkdir ~/.octoprint\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThis should leave you with a happy install of octoprint located at \u003ccode\u003e/home/octoprint/Octoprint\u003c/code\u003e.\u003c/p\u003e\n\u003ch3\u003eSetup systemd services\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/systemd/system/octoprint-backend.service\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e[Unit]\n Description=OctoPrint service\n\n[Service]\n User=octoprint\n ExecStart=/home/octoprint/OctoPrint/venv/bin/octoprint\n\n[Install]\n WantedBy=multi-user.target\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/systemd/system/octoprint-frontend.service\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003e[Unit]\nDescription = Octoprint Frontend \nAfter = systemd-user-sessions.service network.target sound.target\n\n[Service]\nUser = octoprint \nGroup = octoprint \nType = simple \nExecStart = /usr/bin/xinit /usr/bin/dbus-launch --exit-with-session /usr/bin/chromium-browser --start-maximized --window-size=480,320 --window-position=0,0 --disable-restore-background-contents --noerordialogs --disable-session-crashed-bubble --disable-infobars --disable-pinch --overscroll-history-navigation=0 --incognito --kiosk http://127.0.0.1:5000 -- :0 -s 0 dpms -nocursor -nolisten tcp vt7 \nRestart = on-abort \nRestartSec = 5\n\n[Install]\nWantedBy = multi-user.target\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eEnable both services to start at boot:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003esystemctl enable octoprint-backend.service\nsystemctl enable octoprint-frontend.service\n\u003c/code\u003e\u003c/pre\u003e\n\u003chr\u003e\n\u003ch3\u003eOctoprint setup\u003c/h3\u003e\n\u003cp\u003eLog in to your octoprint instance using a browser on your computer. It should be something like http://\u003cstrong\u003eYOUR___PI___IP\u003c/strong\u003e:5000. You can find your Pi\u0026#39;s ip address by running \u003ccode\u003eifconfig\u003c/code\u003e as root. You will be presented with the \u0026#34;Setup Wizard\u0026#34;. Follow the instructions to complete the setup process.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eTo keep things simple I recommend \u003cstrong\u003eDISABLING\u003c/strong\u003e access control. I would not recommend this if you are putting your Raspberry Pi on a public network.\u003c/em\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch3\u003eTouchUI plugin\u003c/h3\u003e\n\u003cp\u003eTo best fit on the 480x320 screen, you should enable the TouchUI plugin. On your computer connect to the octoprint instance running on the Raspberry Pi (\u003cem\u003einstructions above\u003c/em\u003e). \u0026#34;Under the settings section, goto the plugin manager and search for \u0026#34;Touch UI\u0026#34;, then click the install button.\u0026#34; --\u003ca href=\"https://learn.adafruit.com/3-dot-5-pitft-octoprint-rig/software\" rel=\"nofollow\"\u003eAdafruit\u003c/a\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch3\u003eEnable the PiTFT\u003c/h3\u003e\n\u003cp\u003eAdafruit has a guide: \u003ca href=\"https://learn.adafruit.com/adafruit-pitft-3-dot-5-touch-screen-for-raspberry-pi/easy-install\" rel=\"nofollow\"\u003ehttps://learn.adafruit.com/adafruit-pitft-3-dot-5-touch-screen-for-raspberry-pi/easy-install\u003c/a\u003e, but it doesnt seem to play nice with the latest Raspbian.\u003c/p\u003e\n\u003cp\u003eRun the following as root (\u003ccode\u003esudo -i\u003c/code\u003e):\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eecho \u0026#34;deb http://apt.adafruit.com/raspbian/ jessie main\u0026#34; \u0026gt;\u0026gt; /etc/apt/sources.list\n\nwget -O - -q https://apt.adafruit.com/apt.adafruit.com.gpg.key | apt-key add -\n\napt-get update\napt-get install -y adafruit-pitft-helper\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThen run adafruit-pitft-helper:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eadafruit-pitft-helper -t 35r\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eCheck \u003ccode\u003e/boot/config.txt\u003c/code\u003e to ensure the defined orientation will work for you. The line to review should look like:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003edtoverlay=pitft35r,rotate=90,speed=42000000,fps=20\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThe rotate= variable tells the driver to rotate the screen 0, 90, 180, or 270 degrees.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e0\u003c/strong\u003e is portrait, with the bottom near the USB jacks.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e90\u003c/strong\u003e is landscape, with the bottom of the screen near the headphone jack.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e180\u003c/strong\u003e is portrait, with the top near the USB jacks.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e270\u003c/strong\u003e is landscape, with the top of the screen near the headphone jack.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eNow reboot (\u003ccode\u003ereboot\u003c/code\u003e).\u003c/p\u003e\n\u003cp\u003eAfter the reboot (in theory) you will see the octoprint web interface on your PiTFT. But you will need to calibrate the touchscreen before you can interact with it.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3\u003eTouch calibration\u003c/h3\u003e\n\u003cp\u003eAs root (\u003ccode\u003esudo -i\u003c/code\u003e) run the following:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eDISPLAY=:0.0 xinput_calibrator\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eFollow the onscreen calibration process:\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/content/images/2017/07/raspberry_pi_xinput.png\" alt=\"\"\u003e\n\u003c/p\u003e\n\u003cp\u003eOnce complete you should have a snippet of config to paste relevant to your touch screen.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eedit: \u003ccode\u003e/etc/X11/xorg.conf.d/99-calibration.conf\u003c/code\u003e\u003c/strong\u003e and paste the output you got from xinput_calibrator.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eExample output:\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eSection \u0026#34;InputClass\u0026#34;\n\tIdentifier\t\u0026#34;calibration\u0026#34;\n\tMatchProduct\t\u0026#34;stmpe-ts\u0026#34;\n\tOption\t\u0026#34;Calibration\u0026#34;\t\u0026#34;3932 82 141 3877\u0026#34;\n\tOption\t\u0026#34;SwapAxes\u0026#34;\t\u0026#34;1\u0026#34;\n\tOption \u0026#34;InvertX\u0026#34; \u0026#34;1\u0026#34;\n\tOption \u0026#34;InvertY\u0026#34; \u0026#34;1\u0026#34;\nEndSection\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eIf your config does not contain \u003cstrong\u003eInvertX\u003c/strong\u003e or \u003cstrong\u003eInvertY\u003c/strong\u003e (\u003cem\u003emine didn\u0026#39;t\u003c/em\u003e), you can add it manually to fix input inversion problems you may have.\u003c/p\u003e\n\u003cp\u003eReboot (\u003ccode\u003ereboot\u003c/code\u003e), and enjoy your octoprint rig!.\u003c/p\u003e\n\u003chr\u003e\n\u003ch3\u003eMy Octoprint controller\u003c/h3\u003e\n\u003cp\u003eI mounted my octoprint controller to the shelving that I have my 3D printers on using double sided adhesive. Overall I am very impressed with how simple octoprint is and how well it works with my Anet A8 3D printer.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1557.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1555.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/07/IMG_1556.jpg\" alt=\"\"\u003e\n","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2017-07-21T02:18:30Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"51fc6de0bddbd56cfebbf24db5659465","projectId":"","tags":[{"id":"b529314e428273696b02c474dcf56132","name":"Raspberry Pi","slug":"raspberry-pi"},{"id":"f9ecad390ed765b2bb4ae55d9faa7311","name":"Octoprint","slug":"octoprint"},{"id":"e58b4788e99c9f53befd1e47b8073250","name":"3D Printing","slug":"3d-printing"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"},{"id":"bfd1ec8875b9ff5807a23c1e5275e668","siteId":"projectable","slug":"my-sim-racing-motion-rig-version-2","title":"My sim racing motion rig version 2","markdown":"I have really enjoyed having a motion simulator platform for sim racing. It's fairly close to real world racing, but costs a LOT less money, and there isn't that risk of serious injury, or death ☠️\n\nI started down this path almost 3 years ago, and with the Oculus Rift bringing VR in to the picture, I am truly hooked.\n\nVersion 1 of the motion rig was thrown together using 80/20 extrusion that I already had, and it was pieced together without any real planning. One of the biggest drawbacks of version 1 was its inability to easily adjust for other drivers, especially my kids. There were a few other shortcomings: it was uncomfortable, it flexed and squeaked, the rear traction loss wasn't smooth, the rear speakers flopped around like crazy, and so on...\n\n![](/content/images/2017/06/IMG_0349.jpg)\n\nI decided to spend a little while thinking about how to best resolve the big issues, and turned to Fusion360 to design a quick mockup of the main features.\n\n\u003cp align=\"center\"\u003e\n![](/content/images/2017/06/IMG_0607.JPG)\n\u003c/p\u003e\n\nThe new design became the basis of what I ordered from [80/20 Inc](https://8020.net): Extrusion, linear movement components for the sliding top frame, and the hinges for the steering bracket.\n\nOnce the extrusion arrived, I quickly mocked up how everything would fit together and came up with an implementation plan.\n\n![](/content/images/2017/06/IMG_0855.jpg)\n![](/content/images/2017/06/IMG_0856.jpg)\n\nStarting with the lower frame, I came up with a process of thread tapping, drilling, and milling to piece everything together.\n\n![](/content/images/2017/06/IMG_0876.JPG)\n![](/content/images/2017/06/IMG_0877.jpg)\n\nUsing a mill bit in my drill press, I was able to notch out the recesses so that the bolt heads sat flush to the edge of the extrusion.\n\n![](/content/images/2017/06/IMG_0881.jpg)\n![](/content/images/2017/06/IMG_0880.jpg)\n\nThis worked out nicely, although my drill press was a little too loose to provide the most accurate cutting. The drill shaft moved all over the place, leaving some of the recesses a little out of alignment.\n\nNext was building the mid frame joint. The lower and mid frames were attached together using a GM wheel hub that I picked up on eBay for $20 shipped.\n\n![](/content/images/2017/06/IMG_0879.jpg)\n![](/content/images/2017/06/IMG_0886.jpg)\n\nI designed this in Fusion360 and milled it using the CNC that I built.\n\n![](/content/images/2017/06/IMG_0888.JPG)\n![](/content/images/2017/06/IMG_0890.jpg)\n![](/content/images/2017/06/IMG_0891.JPG)\n\nOnce that was done, I was able to thread tap the extrusion for the mid frame and pre-assemble it.\n\n![](/content/images/2017/06/IMG_0892.jpg)\n![](/content/images/2017/06/IMG_0894.jpg)\n\nI then attached this section of the mid frame to the lower frame. I used long threaded bolts so that I could adjust the height that the mid frame sat on the lower frame.\n\n![](/content/images/2017/06/IMG_0895.jpg)\n![](/content/images/2017/06/IMG_0897.jpg)\n![](/content/images/2017/06/IMG_0900.jpg)\n![](/content/images/2017/06/IMG_0902.jpg)\n![](/content/images/2017/06/IMG_0903.jpg)\n\nThe top frame was then mocked up. The top frame sits on linear sliders to allow it to slide back and forward. This was the biggest improvement over version 1.\n\n![](/content/images/2017/06/IMG_0912.jpg)\n![](/content/images/2017/06/IMG_0917.jpg)\n\nThere was a lot of drilling and thread tapping to get all the pieces of the top frame together.\n\n![](/content/images/2017/06/IMG_0920.jpg)\n![](/content/images/2017/06/IMG_0930.jpg)\n![](/content/images/2017/06/IMG_0931.jpg)\n![](/content/images/2017/06/IMG_0936.jpg)\n\nI pieced together a seat mount using 80/20, rather than using the SimXperience DIY seat kit that I had for version 1. I did this so that I could get the seat sitting lower in the frame.\n\n![](/content/images/2017/06/IMG_0941.jpg)\n![](/content/images/2017/06/IMG_0946.jpg)\n\nI found a great universal joint on eBay for $30. With this wing style U-Joint, I had a lot more flexibility with how I mounted things. I had to make a quick and dirty jig to get the hole spacing correct as the holes ended up being right along the edge of an extrusion.\n\n![](/content/images/2017/06/IMG_0944.jpg)\n![](/content/images/2017/06/IMG_0947.jpg)\n![](/content/images/2017/06/IMG_0949.jpg)\n\nI also had to notch out part of the extrusion on the mid frame to allow the U-Joint bolts to sit down further at the extreme angles.\n\n![](/content/images/2017/06/IMG_0950.jpg)\n![](/content/images/2017/06/IMG_0951.jpg)\n![](/content/images/2017/06/IMG_0952.jpg)\n![](/content/images/2017/06/IMG_0953.jpg)\n\nWith the seat mounted, I then focused on the rear rollers for the traction loss mechanism. These rollers ultimately set the height of the mid frame from the lower frame. I designed the brackets in Fusion360 and milled them on my CNC.\n\n![](/content/images/2017/06/IMG_0988.jpg)\n\nI used track rollers that I found on eBay. They were called LR200NPPU Track Roller Double Row Bearing Sealed 10x32x9 Track Bearings 18165. I got 4 for $20.\n\n![](/content/images/2017/06/IMG_0986.jpg)\n![](/content/images/2017/06/IMG_0992.jpg)\n![](/content/images/2017/06/IMG_0993.jpg)\n![](/content/images/2017/06/IMG_0994.jpg)\n\nI then mounted them on the cross member of the mid frame.\n\n![](/content/images/2017/06/IMG_0995.jpg)\n![](/content/images/2017/06/IMG_0996.jpg)\n![](/content/images/2017/06/IMG_0997.jpg)\n\nWith the mid frame leveled, I went back to the seat to mount the actuator mount bracket. This was tricky. I had to notch and drill at an angle in the extrusion (98 degrees).\n\n![](/content/images/2017/06/IMG_1007.jpg)\n\nI then designed and fabricated some side support brackets to help relieve the 3 bolts that went into the base extrusion on the seat.\n\n![](/content/images/2017/06/IMG_1011.jpg)\n![](/content/images/2017/06/IMG_1012.jpg)\n![](/content/images/2017/06/IMG_1013.jpg)\n\nI had to design and fabricate end caps for the extrusion that would allow me to thread tap for the actuators. This was the thickest aluminum stock that I had milled on my CNC at the time. Everything went ok-ish... Mid job the x-axis coupler came loose and the CNC started to dig into the piece. I was able to stop it and recover the job without any major damage.\n\n![](/content/images/2017/06/IMG_1015.jpg)\n![](/content/images/2017/06/IMG_1016.jpg)\n![](/content/images/2017/06/IMG_1020.jpg)\n![](/content/images/2017/06/IMG_1023.jpg)\n![](/content/images/2017/06/IMG_1027.jpg)\n![](/content/images/2017/06/IMG_1028.jpg)\n![](/content/images/2017/06/IMG_1029.jpg)\n![](/content/images/2017/06/IMG_1032.jpg)\n![](/content/images/2017/06/IMG_1033.jpg)\n![](/content/images/2017/06/IMG_1034.jpg)\n![](/content/images/2017/06/IMG_1035.jpg)\n\nThe rear traction loss actuator needed a pair of brackets. Again, designed in Fusion360, then milled on my CNC.\n\n\u003cp align=\"center\"\u003e\n![](/content/images/2017/06/IMG_1044.JPG)\n\u003c/p\u003e\n\n![](/content/images/2017/06/IMG_1049.jpg)\n![](/content/images/2017/06/IMG_1046.jpg)\n![](/content/images/2017/06/IMG_1051.jpg)\n![](/content/images/2017/06/IMG_1052.jpg)\n![](/content/images/2017/06/IMG_1053.jpg)\n\nI marked and drilled out the mounting plate for the steering wheel. This was just a piece of stock that I purchased from [80/20 Inc](https://8020.net).\n\n![](/content/images/2017/06/IMG_1037.jpg)\n\nThen designed and milled the brackets for the steering height adjustment.\n\n![](/content/images/2017/06/IMG_1055.jpg)\n![](/content/images/2017/06/IMG_1056.jpg)\n![](/content/images/2017/06/IMG_1060.jpg)\n![](/content/images/2017/06/IMG_1061.jpg)\n\nMounting the shifter and handbrake was pretty straight forward. I was able to use 80/20 components for the shifter and I re-used the version 1 handbrake mount with slight modification.\n\n![](/content/images/2017/06/IMG_1075.jpg)\n![](/content/images/2017/06/IMG_1076.jpg)\n![](/content/images/2017/06/IMG_1077.jpg)\n![](/content/images/2017/06/IMG_1079.jpg)\n\nThe transducers mounted directly using 80/20 components.\n\n![](/content/images/2017/06/IMG_1080.jpg)\n![](/content/images/2017/06/IMG_1081.jpg)\n![](/content/images/2017/06/IMG_1082.jpg)\n![](/content/images/2017/06/IMG_1083.jpg)\n\nThe final finishing parts came in from [80/20 Inc](https://8020.net): some HDPE for the backend to roll on, plastic end caps, and cable management mounts. I had to make a few minor adjustments to things, but in the end it all came together nicely!\n\n![](/content/images/2017/06/IMG_1135.jpg)\n![](/content/images/2017/06/IMG_1136-1.jpg)\n![](/content/images/2017/06/IMG_1137.jpg)\n![](/content/images/2017/06/IMG_1138.jpg)\n\n\nHere is the first video of the new rig in action. This is me playing Assetto Corsa in VR.\n\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/-HftO5CsJCQ\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e\n\n\n----\n\n#### Update 6/25/2017: 4 point racing harness.\n\n![](/content/images/2017/06/IMG_1243.jpg)\n\nI decided that I needed a racing harness to add to the realism in VR. The harness is mounted to the mid frame with some spring tensioning. When you brake, the seat moves forward, but the harness stays in place, so you feel as if you are being held back by the harness, as you would in a real car. Its a really great experience.\n\n![](/content/images/2017/06/IMG_1244.jpg)\n![](/content/images/2017/06/IMG_1247.jpg)\n\nI CNCed a small bracket to mount the springs to the 80/20. The other side of the springs went on to the harness rear mounts, and the harness side mounts went directly on to the seat side brackets.\n\n![](/content/images/2017/06/IMG_1246.jpg)","html":"\u003cp\u003eI have really enjoyed having a motion simulator platform for sim racing. It\u0026#39;s fairly close to real world racing, but costs a LOT less money, and there isn\u0026#39;t that risk of serious injury, or death ☠️\u003c/p\u003e\n\u003cp\u003eI started down this path almost 3 years ago, and with the Oculus Rift bringing VR in to the picture, I am truly hooked.\u003c/p\u003e\n\u003cp\u003eVersion 1 of the motion rig was thrown together using 80/20 extrusion that I already had, and it was pieced together without any real planning. One of the biggest drawbacks of version 1 was its inability to easily adjust for other drivers, especially my kids. There were a few other shortcomings: it was uncomfortable, it flexed and squeaked, the rear traction loss wasn\u0026#39;t smooth, the rear speakers flopped around like crazy, and so on...\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0349.jpg\" alt=\"\"\u003e\n\u003cp\u003eI decided to spend a little while thinking about how to best resolve the big issues, and turned to Fusion360 to design a quick mockup of the main features.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0607.JPG\" alt=\"\"\u003e\n\u003c/p\u003e\n\u003cp\u003eThe new design became the basis of what I ordered from \u003ca href=\"https://8020.net\" rel=\"nofollow\"\u003e80/20 Inc\u003c/a\u003e: Extrusion, linear movement components for the sliding top frame, and the hinges for the steering bracket.\u003c/p\u003e\n\u003cp\u003eOnce the extrusion arrived, I quickly mocked up how everything would fit together and came up with an implementation plan.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0855.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0856.jpg\" alt=\"\"\u003e\n\u003cp\u003eStarting with the lower frame, I came up with a process of thread tapping, drilling, and milling to piece everything together.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0876.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0877.jpg\" alt=\"\"\u003e\n\u003cp\u003eUsing a mill bit in my drill press, I was able to notch out the recesses so that the bolt heads sat flush to the edge of the extrusion.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0881.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0880.jpg\" alt=\"\"\u003e\n\u003cp\u003eThis worked out nicely, although my drill press was a little too loose to provide the most accurate cutting. The drill shaft moved all over the place, leaving some of the recesses a little out of alignment.\u003c/p\u003e\n\u003cp\u003eNext was building the mid frame joint. The lower and mid frames were attached together using a GM wheel hub that I picked up on eBay for $20 shipped.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0879.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0886.jpg\" alt=\"\"\u003e\n\u003cp\u003eI designed this in Fusion360 and milled it using the CNC that I built.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0888.JPG\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0890.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0891.JPG\" alt=\"\"\u003e\n\u003cp\u003eOnce that was done, I was able to thread tap the extrusion for the mid frame and pre-assemble it.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0892.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0894.jpg\" alt=\"\"\u003e\n\u003cp\u003eI then attached this section of the mid frame to the lower frame. I used long threaded bolts so that I could adjust the height that the mid frame sat on the lower frame.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0895.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0897.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0900.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0902.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0903.jpg\" alt=\"\"\u003e\n\u003cp\u003eThe top frame was then mocked up. The top frame sits on linear sliders to allow it to slide back and forward. This was the biggest improvement over version 1.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0912.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0917.jpg\" alt=\"\"\u003e\n\u003cp\u003eThere was a lot of drilling and thread tapping to get all the pieces of the top frame together.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0920.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0930.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0931.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0936.jpg\" alt=\"\"\u003e\n\u003cp\u003eI pieced together a seat mount using 80/20, rather than using the SimXperience DIY seat kit that I had for version 1. I did this so that I could get the seat sitting lower in the frame.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0941.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0946.jpg\" alt=\"\"\u003e\n\u003cp\u003eI found a great universal joint on eBay for $30. With this wing style U-Joint, I had a lot more flexibility with how I mounted things. I had to make a quick and dirty jig to get the hole spacing correct as the holes ended up being right along the edge of an extrusion.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0944.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0947.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0949.jpg\" alt=\"\"\u003e\n\u003cp\u003eI also had to notch out part of the extrusion on the mid frame to allow the U-Joint bolts to sit down further at the extreme angles.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0950.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0951.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0952.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0953.jpg\" alt=\"\"\u003e\n\u003cp\u003eWith the seat mounted, I then focused on the rear rollers for the traction loss mechanism. These rollers ultimately set the height of the mid frame from the lower frame. I designed the brackets in Fusion360 and milled them on my CNC.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0988.jpg\" alt=\"\"\u003e\n\u003cp\u003eI used track rollers that I found on eBay. They were called LR200NPPU Track Roller Double Row Bearing Sealed 10x32x9 Track Bearings 18165. I got 4 for $20.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0986.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0992.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0993.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0994.jpg\" alt=\"\"\u003e\n\u003cp\u003eI then mounted them on the cross member of the mid frame.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0995.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0996.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_0997.jpg\" alt=\"\"\u003e\n\u003cp\u003eWith the mid frame leveled, I went back to the seat to mount the actuator mount bracket. This was tricky. I had to notch and drill at an angle in the extrusion (98 degrees).\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1007.jpg\" alt=\"\"\u003e\n\u003cp\u003eI then designed and fabricated some side support brackets to help relieve the 3 bolts that went into the base extrusion on the seat.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1011.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1012.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1013.jpg\" alt=\"\"\u003e\n\u003cp\u003eI had to design and fabricate end caps for the extrusion that would allow me to thread tap for the actuators. This was the thickest aluminum stock that I had milled on my CNC at the time. Everything went ok-ish... Mid job the x-axis coupler came loose and the CNC started to dig into the piece. I was able to stop it and recover the job without any major damage.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1015.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1016.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1020.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1023.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1027.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1028.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1029.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1032.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1033.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1034.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1035.jpg\" alt=\"\"\u003e\n\u003cp\u003eThe rear traction loss actuator needed a pair of brackets. Again, designed in Fusion360, then milled on my CNC.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1044.JPG\" alt=\"\"\u003e\n\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1049.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1046.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1051.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1052.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1053.jpg\" alt=\"\"\u003e\n\u003cp\u003eI marked and drilled out the mounting plate for the steering wheel. This was just a piece of stock that I purchased from \u003ca href=\"https://8020.net\" rel=\"nofollow\"\u003e80/20 Inc\u003c/a\u003e.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1037.jpg\" alt=\"\"\u003e\n\u003cp\u003eThen designed and milled the brackets for the steering height adjustment.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1055.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1056.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1060.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1061.jpg\" alt=\"\"\u003e\n\u003cp\u003eMounting the shifter and handbrake was pretty straight forward. I was able to use 80/20 components for the shifter and I re-used the version 1 handbrake mount with slight modification.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1075.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1076.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1077.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1079.jpg\" alt=\"\"\u003e\n\u003cp\u003eThe transducers mounted directly using 80/20 components.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1080.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1081.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1082.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1083.jpg\" alt=\"\"\u003e\n\u003cp\u003eThe final finishing parts came in from \u003ca href=\"https://8020.net\" rel=\"nofollow\"\u003e80/20 Inc\u003c/a\u003e: some HDPE for the backend to roll on, plastic end caps, and cable management mounts. I had to make a few minor adjustments to things, but in the end it all came together nicely!\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1135.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1136-1.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1137.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1138.jpg\" alt=\"\"\u003e\n\u003cp\u003eHere is the first video of the new rig in action. This is me playing Assetto Corsa in VR.\u003c/p\u003e\n\u003ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/-HftO5CsJCQ\" frameborder=\"0\" allowfullscreen=\"\"\u003e\u003c/iframe\u003e\n\u003chr\u003e\n\u003ch4\u003eUpdate 6/25/2017: 4 point racing harness.\u003c/h4\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1243.jpg\" alt=\"\"\u003e\n\u003cp\u003eI decided that I needed a racing harness to add to the realism in VR. The harness is mounted to the mid frame with some spring tensioning. When you brake, the seat moves forward, but the harness stays in place, so you feel as if you are being held back by the harness, as you would in a real car. Its a really great experience.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1244.jpg\" alt=\"\"\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1247.jpg\" alt=\"\"\u003e\n\u003cp\u003eI CNCed a small bracket to mount the springs to the 80/20. The other side of the springs went on to the harness rear mounts, and the harness side mounts went directly on to the seat side brackets.\u003c/p\u003e\n\u003cimg src=\"/content/images/2017/06/IMG_1246.jpg\" alt=\"\"\u003e","excerpt":"","metaTitle":"","metaDescription":"","status":"published","featured":false,"publishedAt":"2017-06-19T17:18:00Z","authorId":"190160de54f2192bd5b8734ec8808086","authorName":"Daniel Chote","authorSlug":"daniel","heroMediaId":"11d29d0c27b5c5d2beab0028e2225574","projectId":"","tags":[{"id":"ecaaace3f367d1a9865ae0933d53d715","name":"Sim Racing","slug":"sim-racing"},{"id":"9c4230a56ffd914aade79798824d9d23","name":"SimXperience","slug":"simxperience"},{"id":"ab4bc19e35909615ae7bc6a344a2b50a","name":"Motion Simulator","slug":"motion-simulator"},{"id":"2a3f03a7e12b72da604fe14c788b2d6a","name":"Oculus Rift","slug":"oculus-rift"},{"id":"928d2c45771da339c0d53b265eb1000f","name":"Assetto Corsa","slug":"assetto-corsa"},{"id":"6c984eeb13d39eab0477f9c4ac9ae137","name":"Fanatec","slug":"fanatec"},{"id":"6c42680dd910bc849c96e14d4af5b659","name":"Transducer","slug":"transducer"}],"createdAt":"2026-10-18T13:16:27Z","updatedAt":"2026-10-18T13:16:27Z"}],"site":{"id":"projectable","theme":"projectable","title":"Daniel Chote's Project Blog","description":"Software Development, Game Development, Hardware Hacking, Sim Racing, Multi-rotors and Robots!","timezone":"America/New_York","postsPerPage":10,"logoMediaId":"21557257b3f2ecc4b3fa875b808097a7","coverMediaId":"6d7e99f0997d13aac98da38677ca7064","copyright":"© Daniel Chote","twitterUrl":"https://twitter.com/dchote","linkedinUrl":"https://www.linkedin.com/in/dchote","googleTagId":"G-07GJBQVM38","hosts":[{"host":"new.projectable.me","canonical":false},{"host":"projectable.me","canonical":true},{"host":"www.projectable.me","canonical":false}]},"tagId":"","total":154}