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 hip pods, a wrap-around hip yoke per leg, tapered leg plates with an integral ankle block, 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 74 · mass_g 1200 · leg_pitch 0 · leg_roll 0 · sensor lidar.
Wheeled bipedal balancer
mick/wheeled-biped-balancer@0.7.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 hip pods, a wrap-around hip yoke per leg, tapered leg plates with an integral ankle block, 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_cap, hip_yoke, leg, ankle_cap, 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
Every servo pocket has one open face and a printed cap that closes it, so there is always an obvious way in. The hip pod opens toward the inside of the chassis: the servo goes in from the battery bay before the lid is fitted, and hip_cap plugs the mouth and is held by the servo's own four M2 side screws, clamping the case against the outboard wall. The yoke bucket opens upward: the pitch servo drops in and four M2 go up through the bucket floor. The ankle block is bored right through: the wheel servo goes in from the inboard side, four M2 pass through the block's side walls, and ankle_cap covers the opening with two more.
The horn is drawn in the assembly, which is what the earlier versions were missing. Each servo is shown with its shaft and the horn disc standing 5 mm proud of the case face, and every driven part mates on that face. That is why the shafts looked like they stopped short of their holes: the gap was the horn, which simply was not there.
The ankle block is an extrusion of the leg's own ankle profile rather than a set of walls stuck onto it, so it is flush with the silhouette by construction and the wall thickness around the servo falls out of ankle_d.
The hip pod shell is a rounded box built at pocket size plus one wall thickness, blended back into the tray side, so the wall around the servo is even the whole way round instead of thick in the middle and thin at the corners.
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. The range is symmetric at plus and minus 45 degrees, and the real inward limit is the two wheels meeting at the centreline, which the console reports.
Print orientation, no supports: tray upright, lid upside down, caps flat, 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.
Measure before printing structural parts: servo case dimensions and shaft offset, mounting-hole positions, the horn bolt circle, and how far the horn stands off the case face. 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.7.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_cap, hip_yoke, leg, ankle_cap, wheel_hub, tire | ||
| hip_actuator | "STS3250" | STS3215, STS3250 | ||
| wheel_actuator | "STS3215" | STS3215, STS3250 | ||
| leg_length | 140 | 90 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 | 74 | 66 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.7.0 is MIT
Source
main.scad is the entrypointmain.scad
// Wheeled bipedal balancer, printable parts.
// Per leg: roll servo in a hip pod that opens into the chassis and is closed
// by hip_cap; hip yoke on its horn with a second arm on a stub behind the pod;
// pitch servo dropped into the yoke bucket from above; leg plate on that horn;
// wheel servo into the ankle block from inboard, closed by ankle_cap; hub on
// the wheel horn; TPU tyre clicked onto the hub.
/* [Part] */
// What to render: the assembly, or one printable part in print orientation.
part = "assembly"; // [assembly, body_tray, body_lid, hip_cap, hip_yoke, leg, ankle_cap, 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; // [90: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 = 74; // [66: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 = 52;
hip_z = 12; // roll axis above the tray floor -- kept low on purpose
cl = 0.3;
sp = 2.5; // pocket wall thickness
cap_t = 4; // servo cap plate 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_d = 21; // horn disc diameter -- measure
horn_thick = 5; // case face to horn mating face -- measure
horn_clear = 24; // clearance hole the horn turns in
shaft_off = 10; // shaft centre from the near end of the case -- check
shi = 6; // mounting holes inset from case ends and faces -- measure
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. Origin on the roll axis, shaft +x.
// Roll servo flipped so the case stands ABOVE the axis: x [-rH,0], z [-so, rL-so].
pkt_x0 = -rH - cl; pkt_x1 = cl;
pkt_z0 = -shaft_off - cl; pkt_z1 = rL - shaft_off + cl;
roll_y = body_width / 2 + 4 + rW / 2;
pod_y1 = rW / 2 + cl + sp;
cap_y = -rW / 2 - cl; // inboard face of the cap pocket, hip frame
arm_r = 15;
arm_f0 = horn_thick; arm_f1 = arm_f0 + arm_t;
arm_r1 = pkt_x0 - sp - cl; arm_r0 = arm_r1 - arm_t;
// ---- yoke bucket below the pod. Pitch servo shaft +y, length fore-aft.
pitch_face_y = 14;
pitch_z = pkt_z0 - sp - rW / 2 - cl - 1;
bk_x0 = arm_r0; 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 = pitch_face_y + horn_thick; // leg mates on the pitch horn face
ankle_d = wW + 2 * cl + 11;
ank_d = wH + cl; // ankle block depth, inboard of the plate
wheel_yl = leg_y_in + lt + 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;
function wy_at(a) = roll_y + wheel_yl * cos(a) - (pitch_z - leg_length) * sin(a);
in_ok = [for (a = [0 : -1 : -45]) if (wy_at(a) > wheel_width / 2 + 2) a];
roll_in = len(in_ok) > 0 ? in_ok[len(in_ok) - 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;
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; 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("ankle wall around the servo: ", round((ankle_d - wW - 2*cl)/2*10)/10, " mm each side"));
echo(str("bed check 180 mm: body ", body_length, ", wheel ", wheel_diameter, ", leg ", leg_print, leg_print > 180 ? " -- lay the leg diagonally" : ""));
echo("assembly: roll servo in from the battery bay + hip_cap; pitch servo down into the bucket; wheel servo in from inboard + ankle_cap");
echo("fasteners: 4x M3 insert + 4x M3x10 for the lid; servo M2 screws elsewhere; 2x M2 per ankle_cap; tyre snaps on");
// ---------- primitives ----------
module main_2d(o = 0) {
offset(r = corner_r + o) square([body_length - 2 * corner_r, body_width - 2 * corner_r], center = true);
}
// Servo with shaft +z and the horn disc standing horn_thick proud of the face.
module servo(sz) {
color("Goldenrod") translate([-shaft_off, -sz[1] / 2, -sz[2]]) cube([sz[0], sz[1], sz[2]]);
color("Goldenrod") cylinder(h = horn_thick - 3, d = 6);
color("Silver") translate([0, 0, horn_thick - 3]) cylinder(h = 3, d = horn_d);
}
module horn_pattern(h) {
cylinder(h = h, d = 4.5, center = true);
for (a = [0 : 90 : 270]) rotate([0, 0, a]) translate([horn_circle / 2, 0, 0]) cylinder(h = h, d = horn_hole, center = true);
}
module slab(l, h, r) { hull() for (sx = [-1, 1], sz = [-1, 1]) translate([sx * (l / 2 - r), 0, sz * (h / 2 - r)]) sphere(r = r); }
module roll_servo() { rotate([0, 90, 0]) rotate([0, 0, 180]) servo(hip_size); }
module pitch_servo() { rotate([-90, 0, 0]) rotate([0, 0, 180]) servo(hip_size); }
module wheel_servo() { rotate([-90, 0, 0]) rotate([0, 0, -90]) servo(whl_size); }
// Roll servo side-face screw pattern, in the hip frame, axis along y.
module roll_screws(y0, h) {
for (hz = [shaft_off - shi, -(rL - shaft_off - shi)], hx = [-shi, -(rH - shi)])
translate([hx, y0, hz]) rotate([-90, 0, 0]) cylinder(h = h, d = m2_hole);
}
// ---------- hip cap ----------
module hip_cap() {
difference() {
translate([pkt_x0, cap_y - cap_t, pkt_z0]) cube([rH + 2 * cl, cap_t, rL + 2 * cl]);
roll_screws(cap_y - cap_t - 1, cap_t + 2);
}
}
// ---------- 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() {
cx = (pkt_x0 + pkt_x1) / 2; cz = hip_z + (pkt_z0 + pkt_z1) / 2;
PL = rH + 2 * cl + 2 * sp; PH = rL + 2 * cl + 2 * sp;
hull() {
translate([cx, roll_y + pod_y1 - 5, cz]) for (sx = [-1, 1], sz = [-1, 1])
translate([sx * (PL / 2 - 5), 0, sz * (PH / 2 - 5)]) sphere(r = 5);
translate([cx, body_width / 2 - 7, cz]) slab(PL, PH, 3);
}
translate([pkt_x0 - sp, roll_y, hip_z]) rotate([0, -90, 0]) cylinder(h = 5, d = stub_d);
}
module hip_pod_cut() {
y0 = body_width / 2 - wall - 4;
translate([pkt_x0, y0, hip_z + pkt_z0]) cube([rH + 2 * cl, roll_y + rW / 2 + cl - y0, rL + 2 * cl]);
translate([-1, roll_y, hip_z]) rotate([0, 90, 0]) cylinder(h = pkt_x1 + sp + 2, d = horn_clear);
translate([0, roll_y, hip_z]) roll_screws(rW / 2, sp + cl + 3);
}
module body_tray() {
difference() {
union() {
linear_extrude(split_z) main_2d();
for (s = [0, 1]) mirror([0, s, 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();
}
translate([0, 0, wall]) linear_extrude(split_z) main_2d(-wall);
for (s = [0, 1]) mirror([0, s, 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 + 10]) rotate([0, 20, 0]) cube([3, wall * 3, 15], 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) main_2d();
translate([0, 0, lid_h - 0.01]) linear_extrude(0.01) main_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) main_2d(-wall);
translate([0, 0, lid_h - wall - 0.01]) linear_extrude(0.01) main_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 (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 - 8, 5], 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([-(rL - shaft_off) - cl, pitch_face_y - rH - cl, pitch_z - rW / 2 - cl])
cube([rL + 2 * cl, rH + 2 * cl, rW + 2 * cl + 0.1]);
translate([0, bk_y1 - sp - 1, pitch_z]) rotate([-90, 0, 0]) cylinder(h = sp + 3, d = horn_clear);
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);
translate([arm_f0 + arm_t / 2, 0, 0]) rotate([0, 90, 0]) horn_pattern(arm_t + 2);
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;
akz = ax + wL - shaft_off + 5;
module ankle_2d() { hull() { translate([0, akz]) circle(d = ankle_d); translate([0, ax]) circle(d = ankle_d); } }
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, akz]) circle(d = ankle_d); }
ankle_2d();
}
}
// Two screws through the ankle side walls, and through ankle_cap.
module ankle_screws() {
for (sx = [-1, 1], z = [ax - 4, ax + 28])
translate([sx * (wW / 2 + cl + (ankle_d / 2 - wW / 2 - cl) / 2), 1, z]) rotate([90, 0, 0]) cylinder(h = ank_d + 8, d = m2_hole);
}
module ankle_cap() {
difference() {
rotate([90, 0, 0]) translate([0, 0, ank_d]) linear_extrude(sp) offset(r = -0.4) ankle_2d();
ankle_screws();
}
}
module leg() {
difference() {
union() {
rotate([90, 0, 0]) translate([0, 0, -lt]) linear_extrude(lt) difference() {
leg_2d();
hull() { translate([0, -30]) circle(d = 7); translate([0, akz + 14]) circle(d = 7); }
}
rotate([90, 0, 0]) linear_extrude(ank_d) ankle_2d();
}
// ankle bored right through, so the servo goes in from inboard
translate([-(wW / 2 + cl), -ank_d - 1, ax - shaft_off - cl])
cube([wW + 2 * cl, ank_d + 1, wL + 2 * cl]);
translate([0, -1, ax]) rotate([-90, 0, 0]) cylinder(h = lt + 2, d = horn_clear);
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 = ankle_d + 4, d = m2_hole, center = true);
ankle_screws();
translate([0, lt / 2, 0]) rotate([-90, 0, 0]) horn_pattern(lt + 2);
}
}
// ---------- 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, web_t / 2]) horn_pattern(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() {
translate([0, roll_y, hip_z]) {
roll_servo();
color("Silver") hip_cap();
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();
color("Silver") ankle_cap();
translate([0, 0, ax]) wheel_servo();
translate([0, lt, 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();
mirror([0, 1, 0]) right_leg();
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_cap") translate([0, 0, cap_t]) rotate([-90, 0, 0]) hip_cap();
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 == "ankle_cap") translate([0, 0, ank_d + sp]) rotate([-90, 0, 0]) ankle_cap();
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.
