Skip to content

Commit f312b3e

Browse files
committed
Optimize bucket cylinder geometry for 18" stroke
Updated OpenSCAD loader arm and bucket cylinder geometry to support an 18-inch (457mm) hydraulic cylinder stroke. Adjusted crossbeam position to 1050mm to align with physical arm cutouts, recalculated bucket cylinder mount Z-offset to -40mm, and improved diagnostic echo statements for stroke verification. Added detailed design notes in conversation_log.md.
1 parent 59b1b1f commit f312b3e

File tree

3 files changed

+97
-22
lines changed

3 files changed

+97
-22
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# AI Conversation Log
2+
3+
## Session: January 2, 2026 - Hydraulic Cylinder Optimization & Visual Fixes
4+
5+
### Objectives
6+
1. Fix visual misalignment of bucket hydraulic cylinders in OpenSCAD.
7+
2. Calculate and optimize cylinder stroke lengths.
8+
3. Update geometry for an 18-inch stroke cylinder.
9+
4. Align the crossbeam position with the physical arm cutouts.
10+
11+
### Actions Taken
12+
13+
#### 1. Visual Alignment Fix
14+
* **Issue:** Cylinders appeared "rotated up" and disconnected from the bucket.
15+
* **Cause:** The cylinder calculation assumed a straight arm geometry (`ARM_LENGTH`), ignoring the L-shape drop of the V2 loader arm.
16+
* **Fix:** Updated `bucket_cyl_length` function and `bucket_cylinders` module in `lifetrac_v25.scad` to use `ARM_TIP_X` and `ARM_TIP_Z` (actual tip coordinates) instead of the scalar `ARM_LENGTH`.
17+
18+
#### 2. 16" Stroke Calculation
19+
* **Analysis:** Calculated current geometry stroke.
20+
* **Result:** Confirmed that `CROSS_BEAM_1_POS = 800` and `BUCKET_CYL_MOUNT_Z_OFFSET = -112` provided a near-perfect match for a standard 16" (406mm) stroke cylinder.
21+
22+
#### 3. Upgrade to 18" Stroke
23+
* **Request:** User requested to size up to an 18" (457mm) stroke cylinder.
24+
* **Optimization:** Ran iterative calculations to find new mounting points.
25+
* **Initial Result:** `CROSS_BEAM_1_POS = 760` and `BUCKET_CYL_MOUNT_Z_OFFSET = -80` yielded ~457mm stroke.
26+
* **Updates:** Modified `lifetrac_v25_params.scad` and added detailed echo statements to `lifetrac_v25.scad` to print stroke diagnostics to the console.
27+
28+
#### 4. Crossbeam & Cutout Alignment
29+
* **Issue:** The calculated crossbeam position (760mm) did not align with the physical cutouts and angle irons on the arm plates.
30+
* **Correction:** User requested to keep the crossbeam in the cutout.
31+
* **Adjustment:**
32+
* Reverted changes in `loader_arm_v2.scad` to restore the angle irons/cutout to their original relative position (approx. 1050mm from pivot).
33+
* Updated `CROSS_BEAM_1_POS` to **1050** in `lifetrac_v25_params.scad` to match the physical arm geometry.
34+
* Recalculated cylinder mount offset for this new position.
35+
* Updated `BUCKET_CYL_MOUNT_Z_OFFSET` to **-40** to achieve the required 18" stroke from the 1050mm mounting point.
36+
37+
### Final Configuration
38+
* **Cylinder Stroke:** 18 inches (457mm)
39+
* **Crossbeam Position:** 1050mm (Aligned with arm cutouts)
40+
* **Bucket Mount Z-Offset:** -40mm
41+
* **Status:** Visuals aligned, geometry optimized, and physical constraints satisfied.

LifeTrac-v25/mechanical_design/openscad/lifetrac_v25.scad

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ ARM_LIFT_ANGLE = -ARM_GROUND_ANGLE + ARM_V2_OFFSET_ANGLE + (animation_phase * (6
168168

169169
// Cross beam positions along arm length (from pivot)
170170
// First cross beam positioned for bucket cylinder attachment
171-
CROSS_BEAM_1_POS = ARM_LENGTH * 0.65; // Aligned with bucket cylinder arm mount position
171+
// CROSS_BEAM_1_POS = ARM_LENGTH * 0.65; // Aligned with bucket cylinder arm mount position
172172
CROSS_BEAM_2_POS = ARM_LENGTH - 200; // Second cross beam near bucket
173173

174174
// Cross beam size (for cutout calculations)
@@ -370,20 +370,21 @@ BUCKET_MAX_TILT = 90; // Fully curled (bucket bottom facing up
370370
function bucket_cyl_length(arm_angle, bucket_tilt) =
371371
let(
372372
// Cross beam attachment point (in arm local coords, then rotated)
373-
arm_local_y = BUCKET_CYL_ARM_POS,
374-
arm_local_z = CROSS_BEAM_SIZE/2 + 30, // Above cross beam (matches bracket height)
373+
arm_local_y = CROSS_BEAM_1_POS,
374+
arm_local_z = CROSS_BEAM_MOUNT_Z_OFFSET,
375375
arm_y = arm_local_y * cos(arm_angle) - arm_local_z * sin(arm_angle),
376376
arm_z = arm_local_y * sin(arm_angle) + arm_local_z * cos(arm_angle),
377377

378378
// Bucket attachment (in bucket local, tilt about arm tip, then arm rotation)
379-
bucket_local_y = BUCKET_CYL_BUCKET_Y,
380-
bucket_local_z = BUCKET_CYL_BUCKET_Z,
379+
// Must match the translation in bucket_attachment: translate([0, 100, BUCKET_HEIGHT - 100])
380+
bucket_local_y = BUCKET_CYL_MOUNT_Y_OFFSET + 100,
381+
bucket_local_z = BUCKET_CYL_MOUNT_Z_OFFSET + (BUCKET_HEIGHT - 100),
381382
// Tilt about bucket pivot (at arm tip)
382383
bucket_tilted_y = bucket_local_y * cos(bucket_tilt) - bucket_local_z * sin(bucket_tilt),
383384
bucket_tilted_z = bucket_local_y * sin(bucket_tilt) + bucket_local_z * cos(bucket_tilt),
384385
// Add arm length to get position relative to arm pivot
385-
bucket_arm_y = ARM_LENGTH + bucket_tilted_y,
386-
bucket_arm_z = bucket_tilted_z,
386+
bucket_arm_y = ARM_TIP_X + bucket_tilted_y,
387+
bucket_arm_z = ARM_TIP_Z + bucket_tilted_z,
387388
// Rotate by arm angle
388389
bucket_y = bucket_arm_y * cos(arm_angle) - bucket_arm_z * sin(arm_angle),
389390
bucket_z = bucket_arm_y * sin(arm_angle) + bucket_arm_z * cos(arm_angle),
@@ -403,6 +404,30 @@ BUCKET_CYL_LEN_4 = bucket_cyl_length(ARM_MAX_ANGLE, BUCKET_MAX_TILT);
403404
BUCKET_CYL_LEN_5 = bucket_cyl_length(0, BUCKET_MIN_TILT); // Arm horizontal
404405
BUCKET_CYL_LEN_6 = bucket_cyl_length(0, BUCKET_MAX_TILT);
405406

407+
// Design Check: Specific Operational Points
408+
// 1. Retracted: Arm at Ground (MIN), Bucket at +10 deg absolute
409+
// Bucket Tilt = Abs - Arm = 10 - ARM_MIN_ANGLE
410+
DESIGN_TILT_RETRACTED = 10 - ARM_MIN_ANGLE;
411+
DESIGN_LEN_RETRACTED = bucket_cyl_length(ARM_MIN_ANGLE, DESIGN_TILT_RETRACTED);
412+
413+
// 2. Extended: Arm at Full Height (MAX), Bucket at -20 deg absolute
414+
// Bucket Tilt = Abs - Arm = -20 - ARM_MAX_ANGLE
415+
DESIGN_TILT_EXTENDED = -20 - ARM_MAX_ANGLE;
416+
DESIGN_LEN_EXTENDED = bucket_cyl_length(ARM_MAX_ANGLE, DESIGN_TILT_EXTENDED);
417+
418+
DESIGN_STROKE = DESIGN_LEN_EXTENDED - DESIGN_LEN_RETRACTED;
419+
420+
echo("=== HYDRAULIC CYLINDER DESIGN CHECK ===");
421+
echo("ARM_MIN_ANGLE =", ARM_MIN_ANGLE);
422+
echo("ARM_MAX_ANGLE =", ARM_MAX_ANGLE);
423+
echo("DESIGN_TILT_RETRACTED (Rel) =", DESIGN_TILT_RETRACTED);
424+
echo("DESIGN_TILT_EXTENDED (Rel) =", DESIGN_TILT_EXTENDED);
425+
echo("DESIGN_LEN_RETRACTED =", DESIGN_LEN_RETRACTED);
426+
echo("DESIGN_LEN_EXTENDED =", DESIGN_LEN_EXTENDED);
427+
echo("DESIGN_STROKE REQUIRED =", DESIGN_STROKE);
428+
echo("TARGET STROKE = 457mm (18 inch)");
429+
echo("DIFF =", DESIGN_STROKE - 457);
430+
406431
BUCKET_CYL_LEN_MIN = min(BUCKET_CYL_LEN_1, BUCKET_CYL_LEN_2, BUCKET_CYL_LEN_3,
407432
BUCKET_CYL_LEN_4, BUCKET_CYL_LEN_5, BUCKET_CYL_LEN_6);
408433
BUCKET_CYL_LEN_MAX = max(BUCKET_CYL_LEN_1, BUCKET_CYL_LEN_2, BUCKET_CYL_LEN_3,
@@ -413,6 +438,12 @@ BUCKET_CYL_REQUIRED_STROKE = BUCKET_CYL_LEN_MAX - BUCKET_CYL_LEN_MIN;
413438
BUCKET_CYL_STROKE_WITH_MARGIN = ceil(BUCKET_CYL_REQUIRED_STROKE * CYLINDER_STROKE_MARGIN);
414439
BUCKET_CYL_CLOSED_LENGTH = ceil(BUCKET_CYL_LEN_MIN * CYLINDER_CLOSED_MARGIN);
415440

441+
echo("=== BUCKET CYLINDER FULL RANGE ===");
442+
echo("MIN LENGTH =", BUCKET_CYL_LEN_MIN);
443+
echo("MAX LENGTH =", BUCKET_CYL_LEN_MAX);
444+
echo("REQUIRED STROKE (Full Range) =", BUCKET_CYL_REQUIRED_STROKE);
445+
echo("STROKE WITH MARGIN =", BUCKET_CYL_STROKE_WITH_MARGIN);
446+
416447
// Select standard stroke
417448
BUCKET_CYLINDER_STROKE_CALC =
418449
BUCKET_CYL_STROKE_WITH_MARGIN <= 150 ? 150 :
@@ -2088,7 +2119,7 @@ module loader_arms() {
20882119
// The arms are at +/- ARM_SPACING/2
20892120
// The cross beam spans between them
20902121

2091-
translate([0, ARM_MAIN_LEN - 50, 0]) {
2122+
translate([0, CROSS_BEAM_1_POS, 0]) {
20922123
rotate([0, 90, 0])
20932124
cube([50.8, 152.4, ARM_SPACING], center=true); // 2x6 tube
20942125

@@ -2165,7 +2196,7 @@ module bobcat_quick_attach_plate() {
21652196
for (side = [-1, 1]) {
21662197
x = side * BUCKET_CYL_X_SPACING; // Match arm-side cylinder X offset
21672198
y = BUCKET_CYL_MOUNT_Y_OFFSET; // Flush with back of plate (Y=0)
2168-
z = -60; // Height on plate
2199+
z = BUCKET_CYL_MOUNT_Z_OFFSET; // Height on plate
21692200
translate([x, y, z])
21702201
rotate([90, 0, 0])
21712202
u_channel_lug_with_pin(TUBE_3X3_1_4, 80, BOLT_DIA_3_4 + 2);
@@ -2305,11 +2336,11 @@ module bucket_cylinders() {
23052336
if (show_hydraulics) {
23062337
// Cylinder base on cross beam (arm local coordinates, at cross beam position)
23072338
// Now uses BUCKET_CYL_X_SPACING for proper clearance from side walls
2308-
cross_beam_z = CROSS_BEAM_SIZE/2 + 30; // Top of cross beam plus bracket
2309-
arm_attach_local = [0, BUCKET_CYL_ARM_POS, cross_beam_z];
2339+
arm_attach_local = [0, CROSS_BEAM_1_POS, CROSS_BEAM_MOUNT_Z_OFFSET];
23102340

23112341
// Cylinder rod end on bucket (bucket local coordinates, before tilt)
2312-
bucket_attach_local = [0, BUCKET_CYL_BUCKET_Y, BUCKET_CYL_BUCKET_Z];
2342+
// Must match the translation in bucket_attachment: translate([0, 100, BUCKET_HEIGHT - 100])
2343+
bucket_attach_local = [0, BUCKET_CYL_MOUNT_Y_OFFSET + 100, BUCKET_CYL_MOUNT_Z_OFFSET + (BUCKET_HEIGHT - 100)];
23132344

23142345
// Calculate actual extension based on current arm angle and bucket tilt
23152346
current_bucket_cyl_length = bucket_cyl_length(ARM_LIFT_ANGLE, BUCKET_TILT_ANGLE);
@@ -2340,8 +2371,8 @@ module bucket_cylinders() {
23402371

23412372
// Position relative to arm tip
23422373
bucket_at_arm_tip = [bucket_tilted[0],
2343-
ARM_LENGTH + bucket_tilted[1],
2344-
bucket_tilted[2]];
2374+
ARM_TIP_X + bucket_tilted[1],
2375+
ARM_TIP_Z + bucket_tilted[2]];
23452376

23462377
// Rotate by arm angle
23472378
bucket_rotated = rot_x(bucket_at_arm_tip, ARM_LIFT_ANGLE);

LifeTrac-v25/mechanical_design/openscad/lifetrac_v25_params.scad

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ ARM_V2_OFFSET_ANGLE = ARM_MIN_ANGLE_COMPUTED + ARM_GROUND_ANGLE; // Difference f
140140
ARM_MIN_ANGLE = ARM_MIN_ANGLE_COMPUTED; // Lowest position (at ground)
141141
ARM_MAX_ANGLE = 60 + ARM_V2_OFFSET_ANGLE; // Maximum raised position
142142

143-
// Cross beam configuration
144-
CROSS_BEAM_SIZE = TUBE_2X2_1_4[0]; // 2"x2" tube size
145-
CROSS_BEAM_CLEARANCE = 15; // Extra clearance around cross beam in cutout
146-
CROSS_BEAM_1_POS = ARM_LENGTH * 0.65; // First cross beam position
147-
CROSS_BEAM_2_POS = ARM_LENGTH * 0.95; // Second cross beam position (near bucket)
143+
// Cross beam configuration (Moved to below)
144+
// CROSS_BEAM_SIZE = TUBE_2X2_1_4[0]; // 2"x2" tube size
145+
// CROSS_BEAM_CLEARANCE = 15; // Extra clearance around cross beam in cutout
146+
// CROSS_BEAM_1_POS = ARM_LENGTH * 0.65; // First cross beam position
147+
// CROSS_BEAM_2_POS = ARM_LENGTH * 0.95; // Second cross beam position (near bucket)
148148

149149
// Pivot position in panel coordinates (for arc slot calculations)
150150
PIVOT_PANEL_X = ARM_PIVOT_Y; // Pivot X in panel coords
@@ -185,14 +185,17 @@ LIFT_CYL_BASE_Y = max(50, min(WHEEL_BASE/2, _calc_base_y));
185185
// Bucket Cylinder Mount Parameters
186186
BUCKET_CYL_MOUNT_SIZE = TUBE_3X3_1_4[0]; // 3" (76.2mm)
187187
BUCKET_CYL_MOUNT_Y_OFFSET = -BUCKET_CYL_MOUNT_SIZE/2; // Flush with back of bucket plate
188+
BUCKET_CYL_MOUNT_Z_OFFSET = -40; // Calculated for 18" stroke cylinder
188189

189190
// Cross Beam Cylinder Mount Parameters
190191
CROSS_BEAM_HEIGHT = TUBE_2X6_1_4[0]; // 2" (50.8mm)
191192
CROSS_BEAM_MOUNT_Z_OFFSET = -(CROSS_BEAM_HEIGHT/2 + BUCKET_CYL_MOUNT_SIZE/2); // Bottom of cross beam
192193

193-
// =============================================================================
194-
// ENGINE CONFIGURATION
195-
// =============================================================================
194+
// Cross beam configuration
195+
CROSS_BEAM_SIZE = TUBE_2X2_1_4[0]; // 2"x2" tube size
196+
CROSS_BEAM_CLEARANCE = 15; // Extra clearance around cross beam in cutout
197+
CROSS_BEAM_1_POS = 1050; // Optimized for 18" cylinder stroke
198+
CROSS_BEAM_2_POS = ARM_LENGTH * 0.95; // Second cross beam position (near bucket)
196199

197200
ENGINE_HP = 25; // Desired horsepower (e.g., 25HP V-Twin)
198201
// Estimate engine weight (kg) based on HP (approximate for small engines)

0 commit comments

Comments
 (0)