Rendering these values. This takes a few seconds.
Download STL
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, tapered 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 74 · mass_g 1200 · leg_pitch 0 · leg_roll 0 · sensor lidar.

MIT

Wheeled bipedal balancer

mick/wheeled-biped-balancer@0.6.0

Remix this
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.

Sign in to report

0reused0 remixes · 0 imports0downloads0.7.0latest

Parameters

from source
90260, steps of 1
60240, steps of 5
1460, steps of 1
130200, steps of 1
70140, steps of 1

Showing the render for these values.

Description

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, tapered 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

Every joint is a flat horn joint, the way a printed servo bracket normally works: the servo sits in a closed pocket with 0.3 mm clearance held by its own M2 screws, the horn stands proud of the servo face, and the driven part bolts flat onto it with four M2 and a clearance hole at the centre. No seating recesses and no journal rings. The one exception is the roll joint, which carries the most bending: its yoke has a second arm behind the pod running on a printed stub, so the horn is not the only support.

Each servo loads through one opening facing away from the outside of the robot. The hip pods take their servo from inside the chassis before the lid goes on and present a smooth closed bulge that blends into the tray wall. The ankle servo drops into a walled cradle on the inboard face of the leg, and its horn comes through a clearance hole in the leg so the hub can sit flat against the outboard face.

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, 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 and thicken again at the ankle.

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 servo 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.6.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
Parameters of Wheeled bipedal balancer, with the ranges the source declares
NameDefaultRangeUnitDescription
part"assembly"assembly, body_tray, body_lid, hip_yoke, leg, wheel_hub, tire
hip_actuator"STS3250"STS3215, STS3250
wheel_actuator"STS3215"STS3215, STS3250
leg_length14090 to 260 step 1
wheel_diameter14060 to 240 step 5
wheel_width2614 to 60 step 1
body_length150130 to 200 step 1
body_width8070 to 140 step 1
body_height7466 to 120 step 1
mass_g1200400 to 3000 step 50
leg_pitch0-60 to 60 step 1
leg_roll0-45 to 45 step 1
sensor"lidar"none, lidar, camera, both

Lineage

0 models depend on this one

Only what this model came from and what came from it.

Remix, the code changed Import, used unchanged and pinned The version you are on Withdrawn, still recorded

License

Whoever downloads this takes these obligations along
  • mick/wheeled-biped-balancer@0.6.0 is MIT

Source

main.scad is the entrypoint
main.scad
// Wheeled bipedal balancer, printable parts.
// Per leg: roll servo in a closed hip pod low in the chassis, hip yoke on its
// horn with a second arm on a stub behind the pod, pitch servo in the yoke
// bucket, leg plate on that horn, wheel servo in a walled ankle cradle with
// its horn through the leg, hub bolted flat to it, 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; // [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
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_thick = 6;         // servo face to horn mating face -- measure
horn_clear = 24;        // clearance hole the horn passes through
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].
pod_x0 = -rH - cl - sp;         pod_x1 = cl + sp;
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  = 15;
arm_f0 = horn_thick;      arm_f1 = arm_f0 + arm_t;
arm_r1 = pod_x0 - 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      = pod_z0 - rW / 2 - cl - sp - 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 bolts flat onto the pitch horn
hub_y    = leg_y_in + lt;               // hub sits flat on the leg, horn through it
wheel_yl = hub_y + wheel_width / 2;
ankle_d  = max(36, wW + 2 * cl + 2 * sp + 6);

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("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");

// ---------- primitives ----------
module main_2d(o = 0) {
  offset(r = corner_r + o) square([body_length - 2 * corner_r, body_width - 2 * corner_r], center = true);
}
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_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); }

// ---------- 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 = (pod_x0 + pod_x1) / 2;  cz = hip_z + (pod_z0 + pod_z1) / 2;
  L = pod_x1 - pod_x0;  H = pod_z1 - pod_z0;
  hull() {
    translate([cx, body_width / 2 - 10, cz]) slab(L, H, 4);
    translate([cx, roll_y + pod_y1 - 6, cz]) slab(L - 11, H - 11, 6);
  }
  translate([pod_x0, roll_y, hip_z]) rotate([0, -90, 0]) cylinder(h = 5, d = stub_d);
}
module hip_pod_cut() {
  y0 = body_width / 2 - wall - 3;
  translate([-rH - cl, y0, hip_z - shaft_off - cl]) 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 = pod_x1 + 2, d = horn_clear);
  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 + 3, d = m2_hole);
}
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 + 60]);
    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 + 4;
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); }
    hull() { translate([0, akz]) circle(d = ankle_d); translate([0, ax]) circle(d = ankle_d); }
  }
}
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 + 2 * sp]);
  for (z = [ax - shaft_off - cl - sp, ax - shaft_off - cl + h])
    translate([-(w / 2 + sp), -d, z]) cube([w + 2 * sp, d, sp]);
  translate([-(w / 2 + sp), -d - sp, ax - shaft_off - cl - sp]) cube([w + 2 * sp, sp, h + 2 * sp]);
}
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); }
      }
      ankle_cradle();
    }
    translate([0, lt / 2, 0]) rotate([-90, 0, 0]) horn_pattern(lt + 2);
    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 = 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, 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();
    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, 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_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.

Sign in to comment