Read this model as text
A printable wheeled bipedal balancer with two straight legs and six bus servos: per leg a roll joint low in the chassis, a pitch joint below it, and a wheel drive in the ankle. Two-shell chassis with closed hip pods, a wrap-around hip yoke per leg, hourglass leg plates, and spoked hubs with click-on TPU tyres.
The image shows the solid OpenSCAD renders at part assembly · hip_actuator STS3250 · wheel_actuator STS3215 · leg_length 140 · wheel_diameter 140 · wheel_width 26 · body_length 150 · body_width 80 · body_height 72 · mass_g 1200 · leg_pitch 0 · leg_roll 0 · sensor lidar.
Wheeled bipedal balancer
mick/wheeled-biped-balancer@0.5.0
Report
For a legal or policy problem: a license violation, personal data, somebody else’s work republished as their own. A model that prints badly is a comment, not a report.
Parameters
from sourceDescription
What is this
A printable wheeled bipedal balancer with two straight legs and six bus servos: per leg a roll joint low in the chassis, a pitch joint below it, and a wheel drive in the ankle. Two-shell chassis with closed hip pods, a wrap-around hip yoke per leg, hourglass leg plates, and spoked hubs with click-on TPU tyres.
`part` gives the assembly or one printable part in its print orientation: body_tray, body_lid, hip_yoke, leg, wheel_hub, tire. Print two of everything except the body.
What you use it for
Building it, and checking it first. Pose the legs with leg_pitch and leg_roll; the console reports stance height, track width, the torque on each hip joint against the servo's rated torque, how far the legs can swing inward before the wheels meet, and a bed check.
Design notes
No joint hangs on a servo horn. Every joint runs on a printed collar or stub concentric with the servo axis: the driven part has a matching bore and rides on it, so the collar carries the bending and the horn only carries torque. The roll joint gets a collar in front and a stub behind, so the yoke is journaled at both ends.
Every servo sits in a closed pocket with 0.3 mm clearance, loaded through one opening that faces away from the outside of the robot, and retained by its own M2 screws. Nothing is open to view: the hip pods take their servo from inside the chassis before the lid goes on and present a smooth closed surface outboard, and the ankle servo drops into a walled cradle that is part of the leg plate.
The roll axis sits low, just above the tray floor, with the servo case standing above the axis inside the chassis. That is what lets the legs swing inward as far as they swing outward: the yoke and leg sweep under the body instead of into it, and the range is symmetric at plus and minus 45 degrees. The inward limit is the two wheels meeting at the centreline, which the console reports for the current geometry.
Print orientation, no supports: tray upright, lid upside down, yoke standing on the bucket floor, leg flat with the outboard face down so layer lines run in the bending plane, hub flat, tyre flat in TPU. Every pocket and cradle opens upward in its print orientation, and the cradle caps run perpendicular to the plate so nothing bridges.
Character is kept to what the geometry already wants: a visor band with the camera window across the chassis front, the lidar in a cap on top, hip pods that read as hips, shoulder-shaped yoke arms, and legs that narrow at the shin.
Measure before printing structural parts: servo case dimensions and shaft offset, mounting-hole positions, and the horn bolt circle. All are named constants at the top of the hidden section.
Parameters
part picks what to render. hip_actuator and wheel_actuator pick the servo. leg_length, wheel_diameter and wheel_width size the leg and wheel. body_length, body_width and body_height size the chassis, mass_g feeds the torque check. leg_pitch and leg_roll pose the legs. sensor picks none, lidar, camera or both.
Use with your agent
{
"mcpServers": {
"remixcad": {
"type": "http",
"url": "https://remix-cad.vercel.app/api/mcp"
}
}
}get_model("mick/wheeled-biped-balancer@0.5.0")Returns the manifest, the source, the import closure and the license obligations. Full MCP setup.
Parameter table
Parsed from the Customizer annotations in main.scad| Name | Default | Range | Unit | Description |
|---|---|---|---|---|
| part | "assembly" | assembly, body_tray, body_lid, hip_yoke, leg, wheel_hub, tire | ||
| hip_actuator | "STS3250" | STS3215, STS3250 | ||
| wheel_actuator | "STS3215" | STS3215, STS3250 | ||
| leg_length | 140 | 80 to 260 step 1 | ||
| wheel_diameter | 140 | 60 to 240 step 5 | ||
| wheel_width | 26 | 14 to 60 step 1 | ||
| body_length | 150 | 130 to 200 step 1 | ||
| body_width | 80 | 70 to 140 step 1 | ||
| body_height | 72 | 64 to 120 step 1 | ||
| mass_g | 1200 | 400 to 3000 step 50 | ||
| leg_pitch | 0 | -60 to 60 step 1 | ||
| leg_roll | 0 | -45 to 45 step 1 | ||
| sensor | "lidar" | none, lidar, camera, both |
Lineage
0 models depend on this oneOnly what this model came from and what came from it.
License
Whoever downloads this takes these obligations along- mick/wheeled-biped-balancer@0.5.0 is MIT
Source
main.scad is the entrypointmain.scad
// Wheeled bipedal balancer, printable parts.
// Per leg: roll servo in a closed hip pod low in the chassis, hip yoke
// journaled on printed collars either side of that pod, pitch servo in the
// yoke bucket, leg plate journaled on the bucket collar, wheel servo in a
// walled ankle cradle, hub journaled on the ankle collar, TPU tyre clicked on.
/* [Part] */
// What to render: the assembly, or one printable part in print orientation.
part = "assembly"; // [assembly, body_tray, body_lid, hip_yoke, leg, wheel_hub, tire]
/* [Actuators] */
// Hip actuator, used for both the roll and the pitch joint.
hip_actuator = "STS3250"; // [STS3215, STS3250]
// Wheel drive actuator, one per wheel.
wheel_actuator = "STS3215"; // [STS3215, STS3250]
/* [Leg] */
// Pitch pivot to wheel axle.
leg_length = 140; // [80:1:260]
// Diameter measured over the tyre tread.
wheel_diameter = 140; // [60:5:240]
// Width across the tyre.
wheel_width = 26; // [14:1:60]
/* [Body] */
// Fore-aft length of the chassis.
body_length = 150; // [130:1:200]
// Width of the chassis between the hip pods.
body_width = 80; // [70:1:140]
// Height of the chassis, tray plus lid.
body_height = 72; // [64:1:120]
// All-up mass for the torque check. Changes no geometry.
mass_g = 1200; // [400:50:3000]
/* [Pose] */
// Leg swung forward from vertical, degrees. Negative is back.
leg_pitch = 0; // [-60:1:60]
// Leg swung outward from vertical, degrees. Negative is inward.
leg_roll = 0; // [-45:1:45]
/* [Sensor] */
// What sits on the body.
sensor = "lidar"; // [none, lidar, camera, both]
/* [Hidden] */
$fn = 36;
wall = 2.4;
corner_r = 12;
corner_in = 10;
split_z = 50;
hip_z = 13; // roll axis above the tray floor -- kept low on purpose
cl = 0.3;
sp = 2.5; // pocket wall thickness
insert_d = 4.0;
m3_clear = 3.4;
m3_head = 6.4;
m2_hole = 2.2;
horn_circle = 14; // horn bolt circle, 4 holes -- measure your horn
horn_hole = 2.2;
horn_boss = 21; // horn seating recess diameter -- measure
shaft_off = 10; // shaft centre from the near end of the case -- check
shi = 6; // mounting holes inset from case ends and faces -- measure
col_d = 24; // journal collar outer diameter
col_h = 3;
arm_t = 4; // yoke arm thickness
stub_d = 8;
lt = 6; // leg plate thickness
tire_t = 12;
tread_n = 28;
function act_size(n) = n == "STS3250" ? [45.2, 24.7, 35.0] : [44.8, 24.0, 35.5];
function act_stall(n) = n == "STS3250" ? 50 : 30;
hip_size = act_size(hip_actuator);
whl_size = act_size(wheel_actuator);
hip_stall = act_stall(hip_actuator);
whl_stall = act_stall(wheel_actuator);
hip_rated = hip_stall * 0.25;
rL = hip_size[0]; rW = hip_size[1]; rH = hip_size[2];
wL = whl_size[0]; wW = whl_size[1]; wH = whl_size[2];
wheel_r = wheel_diameter / 2;
mass_kg = mass_g / 1000;
lid_h = body_height - split_z;
lidar_x = body_length / 4;
// ---- hip pod, right side. Frame origin on the roll axis, shaft +x.
// Roll servo flipped so the case stands ABOVE the axis: x [-rH,0], z [-so, rL-so].
pod_x0 = -rH - cl - sp; pod_x1 = cl + sp;
pod_y0 = -rW / 2 - cl; pod_y1 = rW / 2 + cl + sp;
pod_z0 = -shaft_off - cl - sp; pod_z1 = rL - shaft_off + cl + sp;
roll_y = body_width / 2 + 4 + rW / 2;
arm_r = 14;
arm_f0 = pod_x1 + cl; arm_f1 = arm_f0 + arm_t;
arm_r1 = pod_x0 - cl; arm_r0 = arm_r1 - arm_t;
// ---- yoke bucket, hanging below the pod. Pitch servo shaft +y.
pitch_face_y = 14;
pitch_z = pod_z0 - 12.35 - cl - sp - 1;
bk_x0 = -(rL - shaft_off) - cl - sp; bk_x1 = shaft_off + cl + sp;
bk_y0 = pitch_face_y - rH - cl - sp; bk_y1 = pitch_face_y + cl + sp;
bk_z0 = pitch_z - rW / 2 - cl - sp; bk_z1 = pitch_z + rW / 2 + cl;
leg_y_in = bk_y1;
hub_y = leg_y_in + lt + col_h + 0.5;
wheel_yl = hub_y + wheel_width / 2;
zz = pitch_z - leg_length * cos(leg_pitch);
wy_r = wheel_yl * cos(leg_roll) - zz * sin(leg_roll);
wz_r = wheel_yl * sin(leg_roll) + zz * cos(leg_roll);
wc_y = roll_y + wy_r;
wc_z = hip_z + wz_r;
ground_z = wc_z - wheel_r * cos(leg_roll);
stance_h = -ground_z;
track_w = 2 * wc_y + wheel_width * cos(leg_roll);
sensor_h = (sensor == "lidar" || sensor == "both") ? 36 : 0;
total_h = stance_h + body_height + sensor_h;
// Inward roll until the two wheels meet at the centreline.
function wy_at(a) = roll_y + wheel_yl * cos(a) - (pitch_z - leg_length) * sin(a);
in_lim = [for (a = [0 : -1 : -45]) if (wy_at(a) > wheel_width / 2 + 2) a];
roll_in = len(in_lim) > 0 ? in_lim[len(in_lim) - 1] : 0;
pitch_need = abs(mass_kg / 2 * leg_length * sin(leg_pitch) / 10);
roll_need = abs(mass_kg / 2 * wy_r / 10);
roll_stand = mass_kg / 2 * wheel_yl / 10;
arm_lim = hip_rated / (mass_kg / 2);
pitch_max = arm_lim >= leg_length / 10 ? 90 : asin(arm_lim / (leg_length / 10));
rim_force = whl_stall / (wheel_r / 10);
leg_print = leg_length + 38;
body_print = body_width + 2 * (pod_y1 - body_width / 2 + roll_y - body_width / 2);
echo(str("stance ", round(stance_h), " mm, overall ", round(total_h), " mm, track ", round(track_w), " mm"));
echo(str("roll range: -45 to +45 deg mechanically; wheels meet at ", round(roll_in), " deg inward"));
echo(str("pitch joint ", round(pitch_need*10)/10, " kg.cm now, holds up to ", round(pitch_max), " deg on ", hip_rated, " kg.cm rated"));
echo(str("roll joint ", round(roll_need*10)/10, " kg.cm now, ", round(roll_stand*10)/10, " kg.cm just standing"));
echo(str("wheel rim force at stall ", round(rim_force*10)/10, " kg against ", mass_kg, " kg"));
echo(str("bed check 180 mm: body ", body_length, ", wheel ", wheel_diameter, ", leg ", leg_print, leg_print > 180 ? " -- lay the leg diagonally" : ""));
echo("print: tray upright, lid upside down, yoke on bucket floor, leg outboard face down, hub flat, tyre in TPU; no supports");
echo("fasteners: 4x M3 insert + 4x M3x10 for the lid; servo M2 screws elsewhere; tyre snaps on");
// ---------- outlines ----------
module main_2d(o = 0) {
offset(r = corner_r + o) square([body_length - 2 * corner_r, body_width - 2 * corner_r], center = true);
}
module pod_2d(o = 0) {
for (side = [-1, 1])
translate([(pod_x0 + pod_x1) / 2, side * (roll_y + pod_y1 - 12) / 1])
offset(r = 7 + o) square([pod_x1 - pod_x0 - 14, 10], center = true);
}
module body_2d(o = 0) { offset(r = o) offset(r = 3) offset(delta = -3) union() { main_2d(); pod_2d(); } }
// ---------- primitives ----------
module servo(sz) {
color("Goldenrod") {
translate([-shaft_off, -sz[1] / 2, -sz[2]]) cube([sz[0], sz[1], sz[2]]);
cylinder(h = 4, d = 6);
}
}
module horn_holes(h) {
for (a = [0 : 90 : 270]) rotate([0, 0, a]) translate([horn_circle / 2, 0, 0]) cylinder(h = h, d = horn_hole, center = true);
}
// Roll servo: shaft +x, case above and behind the axis.
module roll_servo() { rotate([0, 90, 0]) rotate([0, 0, 180]) servo(hip_size); }
// Pitch servo: shaft +y, case inboard, length fore-aft.
module pitch_servo() { rotate([-90, 0, 0]) rotate([0, 0, 180]) servo(hip_size); }
// Wheel servo: shaft +y, case inboard, length up the leg.
module wheel_servo() { rotate([-90, 0, 0]) rotate([0, 0, -90]) servo(whl_size); }
// ---------- body tray ----------
pi_x = body_length / 2 - wall - 4 - 32.5;
bat_x = -body_length / 2 + wall + 4 + 20.5;
drv_x = ((pi_x - 32.5) + (bat_x + 20.5)) / 2;
module battery_rib() {
difference() {
translate([-23, -1.5, 0]) cube([46, 3, wall + 14]);
for (i = [-1, 1]) translate([i * 10.5, 0, wall + 11]) rotate([90, 0, 0]) cylinder(h = 5, d = 19, center = true);
}
}
module hip_pod_solid() {
hull() {
translate([pod_x0, 0, hip_z + pod_z0]) cube([pod_x1 - pod_x0, roll_y + pod_y1, 4]);
translate([pod_x0 + 3, 0, hip_z + pod_z1 - 4]) cube([pod_x1 - pod_x0 - 6, roll_y + pod_y1 - 4, 4]);
}
}
module hip_pod_cut() {
translate([pod_x0 + sp, body_width / 2 - wall - 1, hip_z + pod_z0 + sp])
cube([rH + 2 * cl, roll_y + pod_y1 - sp - (body_width / 2 - wall - 1), rL + 2 * cl]);
translate([-1, roll_y, hip_z]) rotate([0, 90, 0]) cylinder(h = pod_x1 + 2, d = 10);
translate([pod_x0 - 1, roll_y, hip_z]) rotate([0, 90, 0]) cylinder(h = sp + 2, d = 4.5);
for (hz = [shaft_off - shi, -(rL - shaft_off - shi)], hx = [-shi, -(rH - shi)])
translate([hx, roll_y + rW / 2, hip_z + hz]) rotate([-90, 0, 0]) cylinder(h = sp + cl + 2, d = m2_hole);
}
module hip_collars() {
translate([pod_x1, roll_y, hip_z]) rotate([0, 90, 0]) difference() {
cylinder(h = col_h, d = col_d);
translate([0, 0, -1]) cylinder(h = col_h + 2, d = horn_boss + 2);
}
translate([pod_x0 - col_h, roll_y, hip_z]) rotate([0, 90, 0]) cylinder(h = col_h, d = stub_d);
}
module body_tray() {
difference() {
union() {
linear_extrude(split_z) body_2d();
for (side = [-1, 1]) mirror([0, side > 0 ? 0 : 1, 0]) hip_pod_solid();
for (sx = [-1, 1], sy = [-1, 1]) translate([sx * (body_length / 2 - corner_in), sy * (body_width / 2 - corner_in), 0]) cylinder(h = split_z, d = 9);
for (sx = [-1, 1], sy = [-1, 1]) translate([pi_x + sx * 29, sy * 11.5, 0]) cylinder(h = wall + 5, d = 5.5);
for (sx = [-1, 1]) translate([drv_x + sx * 20, 0, 0]) cylinder(h = wall + 5, d = 5.5);
for (sy = [-1, 1]) translate([bat_x, sy * 30, 0]) battery_rib();
for (side = [-1, 1]) mirror([0, side > 0 ? 0 : 1, 0]) hip_collars();
}
translate([0, 0, wall]) linear_extrude(split_z) main_2d(-wall);
for (side = [-1, 1]) mirror([0, side > 0 ? 0 : 1, 0]) hip_pod_cut();
for (sx = [-1, 1], sy = [-1, 1]) translate([sx * (body_length / 2 - corner_in), sy * (body_width / 2 - corner_in), split_z - 8]) cylinder(h = 9, d = insert_d);
for (sx = [-1, 1], sy = [-1, 1]) translate([pi_x + sx * 29, sy * 11.5, wall]) cylinder(h = 6, d = m2_hole);
for (sx = [-1, 1]) translate([drv_x + sx * 20, 0, wall]) cylinder(h = 6, d = m2_hole);
for (side = [-1, 1], i = [0 : 3])
translate([body_length / 2 - 16 - i * 9, side * body_width / 2, split_z / 2 + 8]) rotate([0, 20, 0]) cube([3, wall * 3, 16], center = true);
translate([-body_length / 2, 0, split_z - 12]) cube([wall * 3, 14, 9], center = true);
}
}
// ---------- body lid ----------
ang = atan(6 / lid_h);
module front_cut(w, h, d) {
translate([body_length / 2 - 3, 0, lid_h * 0.5]) rotate([0, -ang, 0]) cube([d * 2, w, h], center = true);
}
module body_lid() {
difference() {
union() {
hull() {
linear_extrude(0.01) body_2d();
translate([0, 0, lid_h - 0.01]) linear_extrude(0.01) body_2d(-6);
}
translate([0, 0, -4]) linear_extrude(4.01) main_2d(-wall - 0.3);
for (sx = [-1, 1], sy = [-1, 1]) translate([sx * (body_length / 2 - corner_in), sy * (body_width / 2 - corner_in), -4]) cylinder(h = lid_h + 4, d = 9);
if (sensor == "lidar" || sensor == "both") translate([lidar_x, 0, lid_h - 0.01]) cylinder(h = 3, d = 44);
for (sx = [-1, 1]) translate([sx * 9, 0, wall]) cylinder(h = lid_h - 2 * wall - 4, d = 5);
}
translate([0, 0, -5]) linear_extrude(5.01) main_2d(-2 * wall - 0.3);
hull() {
linear_extrude(0.01) body_2d(-wall);
translate([0, 0, lid_h - wall - 0.01]) linear_extrude(0.01) body_2d(-6 - wall);
}
for (sx = [-1, 1], sy = [-1, 1]) {
translate([sx * (body_length / 2 - corner_in), sy * (body_width / 2 - corner_in), -5]) cylinder(h = lid_h + 10, d = m3_clear);
translate([sx * (body_length / 2 - corner_in), sy * (body_width / 2 - corner_in), lid_h - 3.5]) cylinder(h = 6, d = m3_head);
}
if (sensor == "lidar" || sensor == "both")
translate([lidar_x, 0, lid_h - 10]) {
cylinder(h = 20, d = 12);
for (a = [45 : 90 : 315]) rotate([0, 0, a]) translate([15, 0, 0]) cylinder(h = 20, d = 2.7);
}
front_cut(body_width - 26, 12, 1);
if (sensor == "camera" || sensor == "both") front_cut(26, 10, 6);
for (sx = [-1, 1]) translate([sx * 9, 0, wall]) cylinder(h = 5, d = m2_hole);
}
}
// ---------- hip yoke (right leg frame, origin on the roll axis) ----------
module yoke_arm(x0) {
translate([x0, 0, 0]) rotate([90, 0, 90]) linear_extrude(arm_t) hull() {
circle(r = arm_r);
translate([(bk_y0 + bk_y1) / 2, bk_z1 - 3]) square([bk_y1 - bk_y0 - 6, 4], center = true);
}
}
module hip_yoke() {
difference() {
union() {
translate([bk_x0, bk_y0, bk_z0]) cube([bk_x1 - bk_x0, bk_y1 - bk_y0, bk_z1 - bk_z0]);
yoke_arm(arm_f0);
yoke_arm(arm_r0);
translate([bk_x1 - 0.01, pitch_face_y, pitch_z]) rotate([-90, 0, 0]) difference() {
cylinder(h = col_h, d = col_d);
translate([0, 0, -1]) cylinder(h = col_h + 2, d = horn_boss + 2);
}
}
// pitch servo pocket, open at the top
translate([-(rL - shaft_off) - cl, pitch_face_y - rH - cl, pitch_z - rW / 2 - cl])
cube([rL + 2 * cl, rH + 2 * cl, rW + 2 * cl + 40]);
translate([0, bk_y1 - 1, pitch_z]) rotate([-90, 0, 0]) cylinder(h = col_h + 4, d = horn_boss + 2);
for (hx = [shaft_off - shi, -(rL - shaft_off - shi)], hy = [pitch_face_y - rH + shi, pitch_face_y - shi])
translate([hx, hy, bk_z0 - 1]) cylinder(h = sp + 2, d = m2_hole);
// front arm rides on the pod collar and bolts to the roll horn
translate([arm_f0 - 1, 0, 0]) rotate([0, 90, 0]) cylinder(h = col_h + 1.2, d = col_d + 2 * cl);
translate([arm_f0 + 1.5, 0, 0]) rotate([0, 90, 0]) { horn_holes(10); cylinder(h = 10, d = 4); }
// rear arm rides on the pod stub
translate([arm_r0 - 1, 0, 0]) rotate([0, 90, 0]) cylinder(h = arm_t + 2, d = stub_d + 2 * cl);
}
}
// ---------- leg (pitch axis at origin, plate y in [0, lt], leg down -z) ----------
ax = -leg_length;
module leg_2d() {
union() {
hull() { circle(d = 38); translate([0, -0.42 * leg_length]) circle(d = 19); }
hull() { translate([0, -0.42 * leg_length]) circle(d = 19); translate([0, ax]) circle(d = 34); }
}
}
module slot_2d(z0, z1) { if (z0 - z1 > 24) hull() { translate([0, z0 - 7]) circle(d = 7); translate([0, z1 + 7]) circle(d = 7); } }
module ankle_cradle() {
w = wW + 2 * cl; d = wH + cl; h = wL + 2 * cl;
for (sx = [-1, 1]) translate([sx * (w / 2 + sp / 2) - sp / 2, -d, ax - shaft_off - cl - sp]) cube([sp, d, h + sp]);
translate([-(w / 2 + sp), -d, ax - shaft_off - cl - sp]) cube([w + 2 * sp, d, sp]);
translate([-(w / 2 + sp), -d, ax - shaft_off - cl + h]) cube([w + 2 * sp, d, sp]);
}
module leg() {
difference() {
union() {
rotate([90, 0, 0]) translate([0, 0, -lt]) linear_extrude(lt) difference() {
leg_2d();
slot_2d(-26, -0.42 * leg_length + 11);
slot_2d(-0.42 * leg_length - 11, ax + 26);
}
ankle_cradle();
translate([0, lt - 0.01, ax]) rotate([-90, 0, 0]) difference() {
cylinder(h = col_h, d = col_d);
translate([0, 0, -1]) cylinder(h = col_h + 2, d = horn_boss + 2);
}
}
// pitch end: bore rides on the bucket collar, horn bolts through
translate([0, -1, 0]) rotate([-90, 0, 0]) cylinder(h = col_h + 1.2, d = col_d + 2 * cl);
translate([0, lt / 2, 0]) rotate([-90, 0, 0]) { horn_holes(lt + 2); cylinder(h = lt + 4, d = 4, center = true); }
// ankle: shaft through the plate, cradle screws into the servo sides
translate([0, -1, ax]) rotate([-90, 0, 0]) cylinder(h = lt + col_h + 2, d = 10);
for (hz = [ax - shaft_off + shi, ax + wL - shaft_off - shi], hy = [-shi, -(wH - shi)])
translate([0, hy, hz]) rotate([0, 90, 0]) cylinder(h = wW + 4 * sp, d = m2_hole, center = true);
}
}
// ---------- wheel hub and tyre ----------
rim_d = wheel_diameter - 2 * tire_t;
module wheel_hub() {
web_t = 6;
difference() {
union() {
difference() {
cylinder(h = wheel_width, d = rim_d);
translate([0, 0, -1]) cylinder(h = wheel_width + 2, d = rim_d - 6);
}
cylinder(h = web_t, d = rim_d - 5);
}
for (a = [0 : 72 : 359]) rotate([0, 0, a + 36]) translate([0, 0, -1]) hull() {
translate([0, 22, 0]) cylinder(h = web_t + 2, d = 10);
translate([0, rim_d / 2 - 14, 0]) cylinder(h = web_t + 2, d = 20);
}
translate([0, 0, wheel_width / 2]) rotate_extrude() translate([rim_d / 2, 0]) circle(d = 3);
translate([0, 0, -1]) { cylinder(h = col_h + 1.2, d = col_d + 2 * cl); cylinder(h = web_t + 2, d = 4); }
translate([0, 0, web_t / 2]) horn_holes(web_t + 2);
}
}
module tire() {
color("DimGray") difference() {
rotate_extrude() hull() {
translate([rim_d / 2 + 0.2, 0]) square([0.01, wheel_width]);
translate([wheel_diameter / 2 - 4, 4]) circle(r = 4);
translate([wheel_diameter / 2 - 4, wheel_width - 4]) circle(r = 4);
}
for (i = [0 : tread_n - 1]) rotate([0, 0, i * 360 / tread_n])
translate([wheel_diameter / 2, 0, wheel_width / 2]) rotate([15, 0, 0]) cube([4, 2.2, wheel_width * 2], center = true);
}
color("DimGray") translate([0, 0, wheel_width / 2]) rotate_extrude() translate([rim_d / 2 + 0.2, 0]) circle(d = 2.6);
}
// ---------- assembly ----------
module right_leg_assembly() {
translate([0, roll_y, hip_z]) {
roll_servo();
rotate([leg_roll, 0, 0]) {
color("Silver") hip_yoke();
translate([0, pitch_face_y, pitch_z]) pitch_servo();
translate([0, 0, pitch_z]) rotate([0, -leg_pitch, 0]) translate([0, leg_y_in, 0]) {
color("Silver") leg();
translate([0, 0, ax]) wheel_servo();
translate([0, hub_y - leg_y_in, ax]) rotate([-90, 0, 0]) { color("WhiteSmoke") wheel_hub(); tire(); }
}
}
}
}
module assembly() {
color("WhiteSmoke") body_tray();
color("WhiteSmoke") translate([0, 0, split_z]) body_lid();
color("DimGray") translate([0, 0, split_z]) front_cut(body_width - 28, 11, 0.35);
if (sensor == "lidar" || sensor == "both") color("DimGray") translate([lidar_x, 0, body_height + 3]) cylinder(h = 33, d = 38);
right_leg_assembly();
mirror([0, 1, 0]) right_leg_assembly();
color("Gainsboro") translate([0, 0, ground_z - 3]) cube([500, track_w + 160, 6], center = true);
}
if (part == "assembly") assembly();
else if (part == "body_tray") body_tray();
else if (part == "body_lid") translate([0, 0, lid_h]) mirror([0, 0, 1]) body_lid();
else if (part == "hip_yoke") translate([0, 0, -bk_z0]) hip_yoke();
else if (part == "leg") translate([0, 0, lt]) rotate([-90, 0, 0]) leg();
else if (part == "wheel_hub") wheel_hub();
else if (part == "tire") tire();
Comments
Context, not a score. Comments never move a model up or down the results.No comments yet
Printed it? A note about your material and the clearance you landed on saves the next person a failed print.
