This repository contains the 3D model source files for a four-wheeled robot chassis and steering system, written entirely in OpenSCAD. The design supports 3D printing and does not rely on external libraries.
Table of Contents
- About
- Overview
- Ackermann Geometry
- Structure
- External Details
The robot model is designed around the following core elements:
- Ackermann Steering: This design implements Ackermann steering and computes the steering radii from the robot parameters (not just by making the inner wheel turn more). The model calculates the trapezoid geometry automatically so you usually don’t need to tweak Ackermann-specific variables by hand.
- Rear-Wheel Drive: Two individual motors drive the rear wheels. Both standard yellow DC motors and N20-type motors are supported.
- Modular Head Mount: The head mount is designed to accommodate two Raspberry Pi Camera Module 3 or more sensors (e.g., day/night configuration).
- Extendable Power Tiers: Side and center slots allow for independent modules for power management: servo driver HAT, motor driver HAT, UPS for Raspberry Pi 5, etc.
- Raspberry Pi: The chassis includes placements and screw holes for the Raspberry Pi 5 and multiple 18650 battery holders.
Ackermann steering is implemented with a rack-and-pinion mechanism that drives a single L-link (rack_link) mounted to one knuckle. That knuckle rotates when the rack moves, the opposite knuckle follows through a tie rod. The knuckles and tie rod form the Ackermann trapezoid, so the inside wheel turns more than the outside wheel.
Note
Install the rack_link on only one side and on only one of the knuckles - it doesn't matter which. Movement of the rack will cause that "leading" knuckle to rotate. The leading knuckle is then connected to the second, "driven" knuckle via a tie rod.
Most parameters live in scad/parameters.scad, but the actual Ackermann geometry (angles and the required tie-rod top width) is calculated automatically from core robot dimensions such as chassis length, steering panel placement and knuckle geometry. Because of that, you will rarely need to edit Ackermann-specific variables manually - especially steering_angle_deg, which is derived from the layout.
The project is organized into several reusable modules under the scad/ directory:
parameters.scad: Central configuration file containing physical dimensions (units are in millimeters).printable.scad: Contains all printable parts in one place. You can print all the parts except the tires using either PETG (recommended) or PLA. For the tires, use TPU (e.g., TPU 95A).
assembly.scad: Fully assembled view of the robot.
steering_system/: Rack-and-pinion steering system based on Ackermann geometry.head/: Mounting system for dual Raspberry Pi cameras.motor_brackets/: Brackets for both standard (yellow) and N20-style motors.wheels/: Components for rear and front wheels, including hubs and tires.placeholders/: Placeholder geometry for components such as the Raspberry Pi, servos, DC motors, battery holders, and HATs.
All these details are just recommendations, you can use any other details, just don't forget to specify corresponding dimensions in parameters.scad.
- Four 685 (5x11x5) bearings: two are inserted into the steering knuckles and mounted on kingpin posts. To use different sizes, modify the variables
knuckle_bearing_outer_dia,knuckle_bearing_inner_dia, and other relevant variables. The other two are inserted into the tie rod; the corresponding variables aretie_rod_bearing_outer_dia,tie_rod_bearing_inner_dia, and others. - Two 693 (3x8x4) bearings are inserted into the rack link and into the knuckle arm that connects to the rack link. Both flanged and standard versions are supported.
- Two 608 (8x22x7) bearings are inserted into the front wheels.
This project supports three EMAX ES08MA II servos by default. If using different models, update the following variables in parameters.scad:
steering_servo_slot_widthandsteering_servo_slot_heightfor the steering servohead_neck_pan_servo_slot_widthandhead_neck_pan_servo_slot_heightfor the pan servohead_neck_tilt_servo_slot_widthandhead_neck_tilt_servo_slot_heightfor the tilt servo
Raspberry Pi 5 is supported by default. To use a different model, adjust the relevant variables prefixed with rpi_ (e.g., rpi_screws_size).
You can use battery holders, a UPS module S3, or both. The default configuration supports two 18650 battery holders along with an S3 UPS module.
Two rear motors are supported-either standard or N20-type:
- The "N20" type refers to motors like the GA12-N20 with a 3 mm shaft.
- The "standard" type refers to widely available yellow gear motors with a 5 mm shaft.
Rear wheel shaft size depends on the motor type. Use the variable motor_type in parameters.scad to set the proper shaft diameter.
The design supports one or two camera modules. The default dimensions are compatible with the Raspberry Pi Camera Module 3.
The model supports Ultrasonic HC-SR04.
The design also supports case for IR Waveshare Infrared LED Light Board Module.
The original LED board is incompatible with the Raspberry Camera Module 3, and the quality of Waveshare’s original camera is unsatisfactory.
Nevertheless, this LED board can be used with Camera Module 3 and other Raspberry Pi cameras. To do so, solder two wires (GND and V+) to the screw holes on the LED board (the screw holes serve both for mechanical attachment and for power). Then connect the positive wire to 3.3V and the ground wire to GND.
Since the default chassis thickness is 4 mm (changeable via the variable chassis_thickness), use screws at least 8 mm long for fastenings that go through the chassis, depending on the nuts. I suggest using lock nuts for these screws, but plain nuts are also acceptable.
The tables below are grouped by component. I haven't combined them into a single table with total quantities because totals depend on which components you use - for example, you may or may not include the UPS Module S3.
Each table includes a "Variable" column that refers to a configurable variable in parameters.scad. You can change it to the screw diameter you want to use.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 | 8 | 4 | 2 | steering_panel_hinge_screw_dia |
| M2 | 8 | 2 | 2 | steering_servo_screw_dia |
| M3 | 20 | 2 | 2 | steering_servo_mount_connector_screw_dia |
| M2 or M2.5 for tight fit | 10 | 4 | 4 | steering_kingpin_post_screw_dia |
Your servo pack should already include screws, a servo arm, and self-tapping screws to secure the servo arm, but I'll list them here for reference as well.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2 | 4 | 1 | 0 | steering_servo_screw_dia |
Tip
The variable steering_servo_screw_dia is used only in assembly views, but there are useful variables that define the diameter of the hole at the center of the pinion where you insert the servo's gearbox - steering_pinion_center_hole_dia. Its default size is 6.5 mm.
Self-tapping screws should also be included in your pack. The diameter may differ slightly, but the screws should still fit due to the nature of self-tapping screws.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M1.5 | 4 | 2 or more | 0 | steering_pinion_screw_dia |
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 | 10 | 4 (2 per knuckle) | 0 | knuckle_shaft_screw_dia |
| M2 or M2.5 for tight fit | 10 | 4 (2 per knuckle) | 0 | tie_rod_shaft_screw_dia |
The exact screw length depends on the standoffs you use. Since the default chassis thickness is 4 mm, you should use screws that are at least 6 mm long.
| Size | Length (mm) | Amount | Nuts/Standoffs | Variable |
|---|---|---|---|---|
| M2 | 6 or higher | 4 | 4 | rpi_screw_hole_dia |
You can attach one or two battery holders to the bottom of the chassis.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 | 8 or higher | 2 | 1 | battery_holder_screw_dia |
You should use either 4 or 8 M3 standoffs. If you use 8 standoffs, the nuts listed below are not needed.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M3 | 8 or higher | 4 | 4 | battery_ups_screw_dia |
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 | 8 or higher | 4 | 4 | n20_motor_screw_dia |
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M3 | 28 | 4 | 4 | standard_motor_bracket_motor_screw_hole |
| M2 | 8 or higher | 4 | 4 | standard_motor_bracket_chassis_screw_hole |
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2 | 4 or higher | 8 (4 for each camera) | 8 | head_camera_screw_dia |
As with the steering servo, your servo pack should already include screws, a servo arm, and self-tapping screws to secure the servo arm. The diameter of the hole on the head where the tilt-servo gearbox mounts is defined by head_servo_mount_dia.
The corresponding hole for the pan servo on the chassis is controlled by chassis_pan_servo_slot_dia.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2 | 6 or higher | 2 | 2 | head_neck_pan_servo_screw_dia |
| M2 | 6 or higher | 2 | 2 | head_neck_tilt_servo_screw_dia |
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2 | 6 or higher | 2 | 2 | ir_case_screw_dia |
| M2 | 6 or higher | 2 | 2 | ir_case_rail_screw_dia |
Variable ir_case_screw_dia defines the diameter of the screw holes that attach the case to the head; ir_case_rail_screw_dia defines the diameter of the rail holes that secure the IR LED to the case itself.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 | 10 or higher | 2 or 3 | 2 | front_panel_connector_screw_dia |
| M2.5 | 10 or higher | 2 | 2 | front_panel_screw_dia |
front_panel_connector_screw_dia defines the diameter of the screw hole on the bracket that connects to the chassis, and front_panel_screw_dia defines the diameter of the screw hole on the front panel that secures the ultrasonic sensor, which is placed between the front panel and the bracket.
Each wheel hub requires 6 M2.5 (or M3 for a very tight fit) screws and nuts.
| Size | Length (mm) | Amount | Nuts | Variable |
|---|---|---|---|---|
| M2.5 or M3 for tight fit | 12 or higher | 12 (6 per wheel hub) | 12 | wheel_hub_screw_dia |


