Fix (UI): Corrected console outputs for UBOM.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
env_scad/
|
||||||
|
env_scad/*
|
||||||
32
config.py
Normal file
32
config.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
from models.dimensions_3d import Dimensions_3D
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
class Config(BaseModel):
|
||||||
|
D_AXLE_FRONT: ClassVar[float] = 42
|
||||||
|
D_AXLE_REAR: ClassVar[float] = 27
|
||||||
|
D_WASHER_AXLE_REAR_WHEEL_POSITIONING: ClassVar[float] = 50
|
||||||
|
D_WASHER_BOLT_REAR_WHEEL_POSITIONING: ClassVar[float] = 30
|
||||||
|
D_WHEEL: ClassVar[float] = 400
|
||||||
|
D_WHEEL_BONE: ClassVar[float] = 25
|
||||||
|
L_BOLT_EXTENSION: ClassVar[float] = 10
|
||||||
|
# M_TOTAL: ClassVar[float] = 160
|
||||||
|
R_BED: ClassVar[Dimensions_3D] = Dimensions_3D(x=400, y=1200, z=18)
|
||||||
|
SIZE_BOLT: ClassVar[float] = 25
|
||||||
|
SIZE_BOLT_REAR_WHEEL_POSITIONING: ClassVar[float] = 10
|
||||||
|
SPACING_WASHER_AXLE_REAR_WHEEL_POSITIONING: ClassVar[float] = 1
|
||||||
|
SPACING_XY_BED_BORDER: ClassVar[float] = 10
|
||||||
|
T_CLAMP: ClassVar[float] = 20
|
||||||
|
T_PLATE: ClassVar[float] = 8
|
||||||
|
T_WASHER_AXLE_REAR_WHEEL_POSITIONING: ClassVar[float] = 4
|
||||||
|
T_WASHER_BOLT_REAR_WHEEL_POSITIONING: ClassVar[float] = 1.5
|
||||||
|
T_WHEEL: ClassVar[float] = 100
|
||||||
|
Z_OVERLAP_TEE_CLAMP_ROUND: ClassVar[float] = 80
|
||||||
|
Z_OFFSET_WHEEL_TO_BED_BASE: ClassVar[float] = 5
|
||||||
|
|
||||||
|
X_POSITION_WHEEL_CENTRE: float
|
||||||
|
Y_POSITION_AXLE_FRONT: float
|
||||||
|
Y_POSITION_AXLE_REAR: float
|
||||||
|
Z_OFFSET_BED_TO_AXLE: float
|
||||||
@@ -45,7 +45,7 @@ X_POS_AXLE_LEG_REAR = min(X_POS_WHEEL_CENTRE - T_WHEEL / 2 - SPACING_WASHER_AXLE
|
|||||||
// THICKNESS_SHELL_BRAKE_BEAM = 5;
|
// THICKNESS_SHELL_BRAKE_BEAM = 5;
|
||||||
// L_BEAM_BRAKE_BELT_TENSION_FIXING = 150;
|
// L_BEAM_BRAKE_BELT_TENSION_FIXING = 150;
|
||||||
D_BEAM_BRAKE = 40;
|
D_BEAM_BRAKE = 40;
|
||||||
T_BEAM_BRAKE = 5;
|
T_BEAM_BRAKE = 3;
|
||||||
D_BRAKE_BALLSCREW_AXLE = 16; // M16 pitch 1.5
|
D_BRAKE_BALLSCREW_AXLE = 16; // M16 pitch 1.5
|
||||||
L_BRAKE_BALLSCREW_AXLE = 450;
|
L_BRAKE_BALLSCREW_AXLE = 450;
|
||||||
D_BRAKE_BALLSCREW_POWER_WHEEL = 120;
|
D_BRAKE_BALLSCREW_POWER_WHEEL = 120;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
,teddy,lord-T-1024,20.02.2025 13:01,file:///home/teddy/.config/libreoffice/4;
|
|
||||||
BIN
docs/UBOM.ods
BIN
docs/UBOM.ods
Binary file not shown.
0
models/__init__.py
Normal file
0
models/__init__.py
Normal file
69
models/base_3d_object.py
Normal file
69
models/base_3d_object.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
from coordinates_3d import Coordinates_3D
|
||||||
|
from dimensions_3d import Dimensions_3D
|
||||||
|
from material import Material
|
||||||
|
|
||||||
|
from abc import ABC
|
||||||
|
from pydantic import BaseModel
|
||||||
|
import openpyscad as ops
|
||||||
|
# from solid import OpenSCADObject
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class Base_3D_Object(BaseModel, ABC):
|
||||||
|
colour: str = ''
|
||||||
|
dimensions_enclosing_cube: Dimensions_3D
|
||||||
|
__mass: float
|
||||||
|
material: Material
|
||||||
|
object: ops.base.BaseObject
|
||||||
|
parent: 'Base_3D_Object' = None
|
||||||
|
position_centre_local_assembly: Coordinates_3D = Coordinates_3D(x = 0, y = 0, z = 0)
|
||||||
|
rotation: Coordinates_3D = Coordinates_3D(x = 0, y = 0, z = 0)
|
||||||
|
__volume_solid: float
|
||||||
|
|
||||||
|
"""
|
||||||
|
@classmethod
|
||||||
|
def make_local_object(cls, colour: str, dimensions_enclosing_cube: Dimensions_3D, material: Material, position_centre_local_assembly: Coordinates_3D, rotation: Coordinates_3D) -> 'Base_3D_Object':
|
||||||
|
return cls(
|
||||||
|
colour=colour,
|
||||||
|
dimensions_enclosing_cube=dimensions_enclosing_cube,
|
||||||
|
mass=material.density * dimensions_enclosing_cube.x * dimensions_enclosing_cube.y * dimensions_enclosing_cube.z,
|
||||||
|
material=material,
|
||||||
|
position_centre_local_assembly=position_centre_local_assembly,
|
||||||
|
position_centre_major_assembly=position_centre_local_assembly,
|
||||||
|
rotation=rotation,
|
||||||
|
volume_solid=dimensions_enclosing_cube.x * dimensions_enclosing_cube.y * dimensions_enclosing_cube.z
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dimensions_and_material_and_parent(cls, dimensions_enclosing_cube: Dimensions_3D, material: Material, parent: Optional['Base_3D_Object']) -> 'Base_3D_Object':
|
||||||
|
return cls(
|
||||||
|
dimensions_enclosing_cube = dimensions_enclosing_cube,
|
||||||
|
material = material,
|
||||||
|
colour = material.colour,
|
||||||
|
parent = parent,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_position_centre_major_assembly(self) -> Coordinates_3D:
|
||||||
|
if self.parent is None:
|
||||||
|
return self.position_centre_local_assembly
|
||||||
|
else:
|
||||||
|
position_centre_parent_major_assembly = self.parent.get_position_centre_major_assembly()
|
||||||
|
return Coordinates_3D(
|
||||||
|
x=self.position_centre_local_assembly.x + position_centre_parent_major_assembly.x,
|
||||||
|
y=self.position_centre_local_assembly.y + position_centre_parent_major_assembly.y,
|
||||||
|
z=self.position_centre_local_assembly.z + position_centre_parent_major_assembly.z
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_mass(self) -> float:
|
||||||
|
if self.__mass is None:
|
||||||
|
self.__mass = self.material.density * self.volume_solid
|
||||||
|
return self.__mass
|
||||||
|
|
||||||
|
def get_volume_solid(self) -> float:
|
||||||
|
if self.__volume_solid is None:
|
||||||
|
self.__volume_solid = self.dimensions_enclosing_cube.x * self.dimensions_enclosing_cube.y * self.dimensions_enclosing_cube.z
|
||||||
|
return self.__volume_solid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
0
models/bed/__init__.py
Normal file
0
models/bed/__init__.py
Normal file
10
models/bed/bed_assembly.py
Normal file
10
models/bed/bed_assembly.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
from models.base_3d_object import Base_3D_Object
|
||||||
|
import models.fixings.tube_clamp_round_base_plate_132
|
||||||
|
|
||||||
|
"""
|
||||||
|
import solid
|
||||||
|
import solid.utils
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Bed_Assembly(Base_3D_Object):
|
||||||
43
models/common/metric_bolt.py
Normal file
43
models/common/metric_bolt.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
from models.base_3d_object import Base_3D_Object
|
||||||
|
from models.dimensions_3d import Dimensions_3D
|
||||||
|
from models.material import Material
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
|
||||||
|
|
||||||
|
class Metric_Bolt(Base_3D_Object):
|
||||||
|
head_diameter: float = Field(gt = 0)
|
||||||
|
head_length: float = Field(gt = 0)
|
||||||
|
length: float = Field(gt = 0)
|
||||||
|
shaft_length: float = Field(gt = 0)
|
||||||
|
size: float = Field(gt = 0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_size_and_length_and_material(cls, size: float, length: float, material: Material) -> 'Metric_Bolt':
|
||||||
|
head_diameter = cls.get_head_diameter(size = size)
|
||||||
|
bolt = Metric_Bolt.from_dimensions_and_material(
|
||||||
|
dimensions_enclosing_cube = Dimensions_3D(
|
||||||
|
x = head_diameter,
|
||||||
|
y = head_diameter,
|
||||||
|
z = length
|
||||||
|
),
|
||||||
|
material = material
|
||||||
|
)
|
||||||
|
bolt.size = size
|
||||||
|
bolt.length = length
|
||||||
|
bolt.head_diameter = head_diameter
|
||||||
|
bolt.head_length = cls.get_head_length(size = size)
|
||||||
|
bolt.shaft_length = bolt.length - bolt.head_length
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_head_diameter(cls, size: float) -> float:
|
||||||
|
return size * 2
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_head_length(cls, size: float) -> float:
|
||||||
|
return size
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_washer_diameter_safe_working_clearance(cls, size: float) -> float:
|
||||||
|
return size * 4 if size < 20 else size * 3
|
||||||
7
models/coordinates_3d.py
Normal file
7
models/coordinates_3d.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
class Coordinates_3D(BaseModel):
|
||||||
|
x: float
|
||||||
|
y: float
|
||||||
|
z: float
|
||||||
7
models/dimensions_3d.py
Normal file
7
models/dimensions_3d.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
class Dimensions_3D(BaseModel):
|
||||||
|
x: float = Field(ge = 0)
|
||||||
|
y: float = Field(ge = 0)
|
||||||
|
z: float = Field(ge = 0)
|
||||||
17
models/fixings/base_tube_clamp.py
Normal file
17
models/fixings/base_tube_clamp.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
from models.base_3d_object import Base_3D_Object
|
||||||
|
from models.material import Material
|
||||||
|
|
||||||
|
from abc import abstractmethod
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
class Base_Tube_Clamp(Base_3D_Object):
|
||||||
|
MATERIAL_DEFAULT: ClassVar[Material] = Material(
|
||||||
|
name = 'Steel',
|
||||||
|
density = 7.85,
|
||||||
|
colour = 'LightGrey'
|
||||||
|
)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def from_tube_diameter(cls, tube_diameter: float) -> 'Base_Tube_Clamp':
|
||||||
|
pass
|
||||||
@@ -31,7 +31,7 @@ module tube_clamp_round_3_way_outlet_tee_176(tube_diameter) {
|
|||||||
rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true);
|
rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true);
|
||||||
}
|
}
|
||||||
// Shopping
|
// Shopping
|
||||||
echo("Round 3-way outlet tee 176: Tube clamp - x1");
|
echo(str("Round 3-way outlet tee 176: Tube clamp Φ", tube_diameter, "mm - x1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test output
|
// test output
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ module tube_clamp_round_3_way_through_116(tube_diameter) {
|
|||||||
translate([0, L_shaft_long / 2, 0]) rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true);
|
translate([0, L_shaft_long / 2, 0]) rotate([90, 0, 0]) cylinder(L_shaft_long, tube_diameter / 2, tube_diameter / 2, center = true);
|
||||||
}
|
}
|
||||||
// Shopping
|
// Shopping
|
||||||
echo("Round 3-way through 116: Tube clamp - x1");
|
echo(str("Round 3-way through 116: Tube clamp Φ", tube_diameter, "mm - x1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test output
|
// test output
|
||||||
|
|||||||
150
models/fixings/tube_clamp_round_base_plate_132.py
Normal file
150
models/fixings/tube_clamp_round_base_plate_132.py
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
|
||||||
|
from models.base_3d_object import Base_3D_Object
|
||||||
|
from models.fixings.base_tube_clamp import Base_Tube_Clamp
|
||||||
|
from models.dimensions_3d import Dimensions_3D
|
||||||
|
from models.material import Material
|
||||||
|
|
||||||
|
from pydantic import Field
|
||||||
|
# import solid
|
||||||
|
import openpyscad as ops
|
||||||
|
|
||||||
|
class Tube_Clamp_Round_Base_Plate_132(Base_Tube_Clamp):
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_tube_diameter_and_parent(cls, tube_diameter: float, parent: Base_3D_Object) -> 'Tube_Clamp_Round_Base_Plate_132':
|
||||||
|
L_shaft_with_base_plate = cls.get_L_shaft_with_base_plate(tube_diameter = tube_diameter)
|
||||||
|
R_plate = cls.get_R_plate(tube_diameter = tube_diameter)
|
||||||
|
y_offset_hole = cls.get_offset_hole_y(tube_diameter = tube_diameter)
|
||||||
|
diameter_hole_bolt = cls.get_diameter_hole(tube_diameter = tube_diameter)
|
||||||
|
|
||||||
|
tube_clamp = cls.from_dimensions_and_material_and_parent(
|
||||||
|
dimensions_enclosing_cube = Dimensions_3D(
|
||||||
|
x = R_plate.x,
|
||||||
|
y = R_plate.y,
|
||||||
|
z = L_shaft_with_base_plate
|
||||||
|
),
|
||||||
|
material = cls.MATERIAL_DEFAULT,
|
||||||
|
parent = parent,
|
||||||
|
)
|
||||||
|
|
||||||
|
clamp_shaft = cls.__make_shaft_object(
|
||||||
|
tube_diameter = tube_diameter,
|
||||||
|
L_shaft_with_base_plate = L_shaft_with_base_plate,
|
||||||
|
R_plate = R_plate,
|
||||||
|
)
|
||||||
|
clamp_shaft.translate([0, 0, L_shaft_with_base_plate / 2])
|
||||||
|
|
||||||
|
base_plate = cls.__make_base_plate_object(
|
||||||
|
R_plate = R_plate,
|
||||||
|
y_offset_hole = y_offset_hole,
|
||||||
|
diameter_hole_bolt = diameter_hole_bolt,
|
||||||
|
)
|
||||||
|
base_plate.translate([0, 0, R_plate.z / 2])
|
||||||
|
|
||||||
|
tube_clamp.object = ops.Union()
|
||||||
|
tube_clamp.object.append(base_plate)
|
||||||
|
tube_clamp.object.append(clamp_shaft)
|
||||||
|
|
||||||
|
tube_clamp.object.color(cls.MATERIAL_DEFAULT.colour)
|
||||||
|
return tube_clamp
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __make_shaft_object(cls, tube_diameter: float, L_shaft_with_base_plate: float, R_plate: tuple[float, float, float]) -> ops.base.BaseObject:
|
||||||
|
clamp_shaft = ops.Difference()
|
||||||
|
clamp_shaft.append(
|
||||||
|
ops.Cylinder(
|
||||||
|
h = L_shaft_with_base_plate,
|
||||||
|
r = tube_diameter / 2 + R_plate.z,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
clamp_shaft.append(
|
||||||
|
ops.Cylinder(
|
||||||
|
h = L_shaft_with_base_plate,
|
||||||
|
r = tube_diameter / 2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return clamp_shaft
|
||||||
|
@classmethod
|
||||||
|
def __make_base_plate_object(cls, R_plate: Dimensions_3D, y_offset_hole: float, diameter_hole_bolt: float) -> ops.base.BaseObject:
|
||||||
|
base_plate = ops.Difference()
|
||||||
|
base_plate.append(
|
||||||
|
ops.Cube(
|
||||||
|
v = [R_plate.x, R_plate.y, R_plate.z],
|
||||||
|
center = True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
base_plate.append(
|
||||||
|
ops.Cylinder(
|
||||||
|
h = R_plate.z,
|
||||||
|
r = diameter_hole_bolt / 2,
|
||||||
|
center = True,
|
||||||
|
).translate([0, y_offset_hole, 0])
|
||||||
|
)
|
||||||
|
base_plate.append(
|
||||||
|
ops.Cylinder(
|
||||||
|
h = R_plate.z,
|
||||||
|
r = diameter_hole_bolt / 2,
|
||||||
|
center = True,
|
||||||
|
).translate([0, -y_offset_hole, 0])
|
||||||
|
)
|
||||||
|
return base_plate
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_L_shaft_with_base_plate(cls, tube_diameter: float) -> float:
|
||||||
|
L_shaft = 25
|
||||||
|
if tube_diameter == 27:
|
||||||
|
L_shaft = 85
|
||||||
|
elif tube_diameter == 42:
|
||||||
|
L_shaft = 122
|
||||||
|
return L_shaft
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_R_plate(cls, tube_diameter: float) -> Dimensions_3D:
|
||||||
|
R_plate = Dimensions_3D(
|
||||||
|
x = 10,
|
||||||
|
y = 20,
|
||||||
|
z = 1
|
||||||
|
)
|
||||||
|
if tube_diameter == 27:
|
||||||
|
R_plate = Dimensions_3D(
|
||||||
|
x = 64,
|
||||||
|
y = 114,
|
||||||
|
z = 7
|
||||||
|
)
|
||||||
|
elif tube_diameter == 42:
|
||||||
|
R_plate = Dimensions_3D(
|
||||||
|
x = 80,
|
||||||
|
y = 140,
|
||||||
|
z = 10
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported tube diameter: {tube_diameter}")
|
||||||
|
return R_plate
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_offset_hole_y(cls, tube_diameter: float) -> float:
|
||||||
|
y_offset = 10
|
||||||
|
if tube_diameter == 27:
|
||||||
|
y_offset = 38
|
||||||
|
elif tube_diameter == 42:
|
||||||
|
y_offset = 50
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported tube diameter: {tube_diameter}")
|
||||||
|
return y_offset
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_diameter_hole(cls, tube_diameter: float) -> float:
|
||||||
|
return 10
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_mass(cls, tube_diameter: float) -> float:
|
||||||
|
mass = 0
|
||||||
|
if tube_diameter == 27:
|
||||||
|
mass = 0.5
|
||||||
|
elif tube_diameter == 42:
|
||||||
|
mass = 1.06
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported tube diameter: {tube_diameter}")
|
||||||
|
return mass
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ module tube_clamp_round_base_plate_132(tube_diameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Shopping
|
// Shopping
|
||||||
echo("Round base plate 132: Tube clamp - x1");
|
echo(str("Round base plate 132: Tube clamp Φ", tube_diameter, "mm - x1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test output
|
// test output
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module tube_clamp_round_tee_long_104(tube_diameter) {
|
|||||||
translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2, tube_diameter / 2, center = true);
|
translate([L_shaft_short / 2, 0, 0]) rotate([0, 90, 0]) cylinder(L_shaft_short, tube_diameter / 2, tube_diameter / 2, center = true);
|
||||||
}
|
}
|
||||||
// Shopping
|
// Shopping
|
||||||
echo("Round tee long 104: Tube clamp - x1");
|
echo(str("Round tee long 104: Tube clamp Φ", tube_diameter, "mm - x1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test output
|
// test output
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ module tube_clamp_square_base_plate_132(beam_width) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Shopping
|
// Shopping
|
||||||
echo("Square base plate 132: Tube clamp - x1");
|
echo(str("Square base plate 132: Tube clamp Φ", beam_width, "mm - x1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// test output
|
// test output
|
||||||
|
|||||||
7
models/material.py
Normal file
7
models/material.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
class Material(BaseModel):
|
||||||
|
colour: str
|
||||||
|
density: float = Field(gt = 0)
|
||||||
|
name: str
|
||||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
openpyscad
|
||||||
|
pydantic
|
||||||
|
# solid
|
||||||
Reference in New Issue
Block a user