Module for generating Abaqus .inp files for AMSIM.
def generate_abaqus_event_series(
simulation: gi.simulation,
filepath: str = "pyGcodeDecode_abaqus_events.inp",
tolerance: float = 1e-12,
output_unit_system: str = None) -> tuple
Generate abaqus event series.
Arguments:
simulation
gi.simulation - simulation instancefilepath
string, default = "pyGcodeDecode_abaqus_events.inp" - output file pathtolerance
float, default = 1e-12 - tolerance to determine whether extrusion is happeningoutput_unit_system
str, optional - Unit system for the output. The one from the simulation is used, in None is specified.
Returns:
tuple
- the event series as a tuple for use in ABAQUS-Python
The CLI for the pyGCodeDecode package.
Simulating the G-code of a 3DBenchy from PrusaSlicer on a Prusa MINI.
def benchy_example()
Extensive example for the usage of pyGCodeDecode simulating G-code for the famous 3DBenchy.
Minimal example simulating the G-code of a brace from Aura-slicer on an Anisoprint Composer A4.
def brace_example()
Minimal example for the usage of pyGCodeDecode simulating the G-code of a brace.
GCode Interpreter Module.
def update_progress(progress: float, name: str = "Percent") -> None
Display or update a console progress bar.
Arguments:
progress
- float between 0 and 1 for percentage, < 0 represents a 'halt', > 1 represents 100%name
- (string, default = "Percent") customizable name for progress bar
def generate_planner_blocks(states: List[state], firmware=None)
Convert list of states to trajectory repr. by planner blocks.
Arguments:
states
- (list[state]) list of statesfirmware
- (string, default = None) select firmware by name
Returns:
block_list (list[planner_block]) list of all planner blocks to complete travel between all states
def find_current_segment(path: List[segment],
t: float,
last_index: int = None,
keep_position: bool = False)
Find the current segment.
Arguments:
path
- (list[segment]) all segments to be searchedt
- (float) time of searchlast_index
- (int) last found index for optimizing searchkeep_position
- (bool) keeps position of last segment, use this when working with gaps of no movement between segments
Returns:
segment
- (segment) the segment which defines movement at that point in timelast_index
- (int) last index where something was found, search speed optimization possible
def unpack_blocklist(blocklist: List[planner_block]) -> List[segment]
Return list of segments by unpacking list of planner blocks.
Arguments:
blocklist
- (list[planner_block]) list of planner blocks
Returns:
path
- (list[segment]) list of all segments
class simulation()
Simulation of .gcode with given machine parameters.
def __init__(gcode_path: pathlib.Path,
machine_name: str = None,
initial_machine_setup: "setup" = None,
output_unit_system: str = "SImm")
Initialize the Simulation of a given G-code with initial machine setup or default machine.
- Generate all states from GCode.
- Connect states with planner blocks, consisting of segments
- Self correct inconsistencies.
Arguments:
gcode_path
- (Path) path to GCode machine name: (string, default = None) name of the default machine to useinitial_machine_setup
- (setup, default = None) setup instanceoutput_unit_system
- (string, default = "SImm") available unit systems: SI, SImm & inch
Example:
gcode_interpreter.simulation(gcode_path=r"path/to/part.gcode", initial_machine_setup=printer_setup)
def plot_2d_position(
filepath: pathlib.Path = pathlib.Path("trajectory_2D.png"),
colvar="Velocity",
show_points=False,
colvar_spatial_resolution=1,
dpi=400,
scaled=True,
show=False)
Plot 2D position (XY plane) with matplotlib (unmaintained).
def plot_3d(extrusion_only: bool = True,
screenshot_path: pathlib.Path = None,
vtk_path: pathlib.Path = None,
mesh: pv.MultiBlock = None) -> pv.MultiBlock
3D Plot with PyVista.
Arguments:
extrusion_only
bool, optional - Plot only parts where material is extruded. Defaults to True.screenshot_path
pathlib.Path, optional - Path to screenshot to be saved. Prevents interactive plot. Defaults to None.vtk_path
pathlib.Path, optional - Path to vtk to be saved. Prevents interactive plot. Defaults to None.mesh
pv.MultiBlock, optional - A pyvista mesh from a previous run to avoid running the mesh generation again. Defaults to None.
Returns:
pv.MultiBlock
- The mesh used in the plot so it can be used (e.g. in subsequent plots).
def plot_vel(axis: Tuple[str] = ("x", "y", "z", "e"),
show: bool = True,
show_planner_blocks: bool = True,
show_segments: bool = False,
show_jv: bool = False,
time_steps: Union[int, str] = "constrained",
filepath: pathlib.Path = None,
dpi: int = 400) -> Figure
Plot axis velocity with matplotlib.
Arguments:
axis
- (tuple(string), default = ("x", "y", "z", "e")) select plot axisshow
- (bool, default = True) show plot and return plot figureshow_planner_blocks
- (bool, default = True) show planner_blocks as vertical linesshow_segments
- (bool, default = False) show segments as vertical linesshow_jv
- (bool, default = False) show junction velocity as xtime_steps
- (int or string, default = "constrained") number of time steps or constrain plot vertices to segment verticesfilepath
- (Path, default = None) save fig as image if filepath is provideddpi
- (int, default = 400) select dpi
Returns:
(optionally)
fig
- (figure)
def trajectory_self_correct()
Self correct all blocks in the blocklist with self_correction() method.
def get_values(t: float, output_unit_system: str = None) -> Tuple[List[float]]
Return unit system scaled values for vel and pos.
Arguments:
t
- (float) timeoutput_unit_system
str, optional - Unit system for the output. The one from the simulation is used, in None is specified.
Returns:
list
- [vel_x, vel_y, vel_z, vel_e] velocitylist
- [pos_x, pos_y, pos_z, pos_e] position
def check_initial_setup(initial_machine_setup)
Check the printer Dict for typos or missing parameters and raise errors if invalid.
Arguments:
initial_machine_setup
- (dict) initial machine setup dictionary
def print_summary(start_time: float)
Print simulation summary to console.
Arguments:
start_time
float - time when the simulation run was started
def refresh(new_state_list: List[state] = None)
Refresh simulation. Either through new state list or by rerunning the self.states as input.
Arguments:
new_state_list
- (list[state], default = None) new list of states, if None is provided, existing states get resimulated
def extrusion_extent(output_unit_system: str = None) -> np.ndarray
Return scaled xyz min & max while extruding.
Arguments:
output_unit_system
str, optional - Unit system for the output. The one from the simulation is used, in None is specified.
Raises:
ValueError
- if nothing is extruded
Returns:
np.ndarray
- extent of extruding positions
def extrusion_max_vel(output_unit_system: str = None) -> np.float64
Return scaled maximum velocity while extruding.
Arguments:
output_unit_system
str, optional - Unit system for the output. The one from the simulation is used, in None is specified.
Returns:
max_vel
- (np.float64) maximum travel velocity while extruding
def save_summary(filepath: Union[pathlib.Path, str])
Save summary to .yaml file.
Arguments:
-
filepath
pathlib.Path | str - path to summary fileSaved data keys:
- filename (string, filename)
- t_end (float, end time)
- x/y/z _min/_max (float, extent where positive extrusion)
- max_extrusion_travel_velocity (float, maximum travel velocity where positive extrusion)
def get_scaling_factor(output_unit_system: str = None) -> float
Get a scaling factor to convert lengths from mm to another supported unit system.
Arguments:
output_unit_system
str, optional - Wanted output unit system. Uses the one specified for the simulation on None is specified.
Returns:
float
- scaling factor
class setup()
Setup for printing simulation.
def __init__(presets_file: str,
printer: str = None,
layer_cue: str = None) -> None
Create simulation setup.
Arguments:
presets_file
- (string) choose setup yaml file with printer presetsprinter
- (string) select printer from preset filelayer_cue
- (string) set slicer specific layer change cue from comment
def load_setup(filepath)
Load setup from file.
Arguments:
filepath
- (string) specify path to setup file
def select_printer(printer_name)
Select printer by name.
Arguments:
printer_name
- (string) select printer by name
def set_initial_position(initial_position: Union[tuple, dict],
input_unit_system: str = None)
Set initial Position.
Arguments:
initial_position
- (tuple or dict) set initial position as tuple of len(4) or dictionary with keys: {X, Y, Z, E}.input_unit_system
str, optional - Wanted input unit system. Uses the one specified for the setup if None is specified.
Example:
setup.set_initial_position((1, 2, 3, 4))
setup.set_initial_position({"X": 1, "Y": 2, "Z": 3, "E": 4})
def set_property(property_dict: dict)
Overwrite or add a property to the printer dictionary. Printer has to be selected through select_printer() beforehand.
Arguments:
property_dict
- (dict) set or add property to the setup
Example:
setup.set_property({"layer_cue": "LAYER_CHANGE"})
def get_dict() -> dict
Return the setup for the selected printer.
Returns:
return_dict
- (dict) setup dictionary
def get_scaling_factor(input_unit_system: str = None) -> float
Get a scaling factor to convert lengths from mm to another supported unit system.
Arguments:
input_unit_system
str, optional - Wanted input unit system. Uses the one specified for the setup if None is specified.
Returns:
float
- scaling factor
Junction handling module.
class junction_handling()
Junction handling super class.
def connect_state(state_A: state, state_B: state)
Connect two states and generates the velocity for the move from state_A to state_B.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
Returns:
velocity
- (float) the target velocity for that travel move
def calc_vel_next()
Return the target velocity for the following move.
def get_target_vel()
Return target velocity.
def __init__(state_A: state, state_B: state)
Initialize the junction handling.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
def get_junction_vel()
Return default junction velocity of zero.
Returns:
0
- zero for default full stop junction handling
class junction_handling_marlin_jd(junction_handling)
Marlin specific junction handling with Junction Deviation.
def calc_JD(vel_0: velocity, vel_1: velocity, p_settings: state.p_settings)
Calculate junction deviation velocity from 2 velocitys.
Reference:
https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/ http://blog.kyneticcnc.com/2018/10/computing-junction-deviation-for-marlin.html
Arguments:
vel_0
- (velocity) entryvel_1
- (velocity) exitp_settings
- (state.p_settings) print settings
Returns:
velocity
- (float) velocity abs value
def __init__(state_A: state, state_B: state)
Marlin specific junction velocity calculation with Junction Deviation.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
def get_junction_vel()
Return junction velocity.
Returns:
junction_vel
- (float) junction velocity
class junction_handling_marlin_jerk(junction_handling)
Marlin classic jerk specific junction handling.
Reference MarlinFirmware/Marlin#8887 MarlinFirmware/Marlin#8888 MarlinFirmware/Marlin#367 (comment)
def __init__(state_A: state, state_B: state)
Marlin classic jerk specific junction velocity calculation.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
def calc_j_vel()
Calculate the junction velocity.
def get_junction_vel()
Return the calculated junction velocity.
Returns:
junction_vel
- (float) junction velocity
class junction_handling_klipper(junction_handling)
Klipper specific junction handling.
- similar junction deviation calc
- corner vel set by: square_corner_velocity end_velocity^2 = start_velocity^2 + 2accelmove_distance for 90deg turn
- todo: smoothed look ahead
Reference: https://www.klipper3d.org/Kinematics.html https://github.com/Klipper3d/klipper/blob/ea2f6bc0f544132738c7f052ffcc586fa884a19a/klippy/toolhead.py
def __init__(state_A: state, state_B: state)
Klipper specific junction velocity calculation.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
def calc_j_delta()
Calculate the junction deviation with klipper specific values.
The jerk value represents the square_corner_velocity!
def calc_j_vel()
Calculate the junction velocity.
def get_junction_vel()
Return the calculated junction velocity.
Returns:
junction_vel
- (float) junction velocity
class junction_handling_MKA(junction_handling)
Anisoprint A4 like junction handling.
def __init__(state_A: state, state_B: state)
Marlin classic jerk specific junction velocity calculation.
Arguments:
state_A
- (state) start statestate_B
- (state) end state
def calc_j_vel()
Calculate the junction velocity.
def get_junction_vel()
Return the calculated junction velocity.
Returns:
junction_vel
- (float) junction velocity
Planner block Module.
class planner_block()
Planner Block Class.
def move_maker2(v_end)
Calculate the correct move type (trapezoidal,triangular or singular) and generate the corresponding segments.
Arguments:
vel_end
- (velocity) target velocity for end of move
def self_correction(tolerance=float("1e-12"))
Check for interfacing vel and self correct.
def timeshift(delta_t: float)
Shift planner block in time.
Arguments:
delta_t
- (float) time to be shifted
def extrusion_block_max_vel() -> Union[np.ndarray, None]
Return max vel from planner block while extruding.
Returns:
block_max_vel
- (np.ndarray 1x4) maximum axis velocity while extruding in block or None if no extrusion is happening
def __init__(state: state, prev_block: "planner_block", firmware=None)
Calculate and store planner block consisting of one or multiple segments.
Arguments:
state
- (state) the current stateprev_block
- (planner_block) previous planner blockfirmware
- (string, default = None) firmware selection for junction
@property
def prev_block()
Define prev_block as property.
@property
def next_block()
Define next_block as property.
def __str__() -> str
Create string from planner block.
def __repr__() -> str
Represent planner block.
def get_segments()
Return segments, contained by the planner block.
def get_block_travel()
Return the travel length of the planner block.
State module with state.
class state()
State contains a Position and Printing Settings (p_settings) to apply for the corresponding move to this State.
class p_settings()
Store Printing Settings.
def __init__(p_acc, jerk, vX, vY, vZ, vE, speed, units="SImm")
Initialize printing settings.
Arguments:
p_acc
- (float) printing accelerationjerk
- (float) jerk or similarvX
- (float) max x velocityvY
- (float) max y velocityvZ
- (float) max z velocityvE
- (float) max e velocityspeed
- (float) default target velocityunits
- (string, default = "SImm") unit settings
def __str__() -> str
Create summary string for p_settings.
def __repr__() -> str
Define representation.
def __init__(state_position: position = None,
state_p_settings: p_settings = None)
Initialize a state.
Arguments:
state_position
- (position) state positionstate_p_settings
- (p_settings) state printing settings
@property
def state_position()
Define property state_position.
@property
def state_p_settings()
Define property state_p_settings.
@property
def line_number()
Define property line_nmbr.
@line_number.setter
def line_number(nmbr)
Set line number.
Arguments:
nmbr
- (int) line number
@property
def next_state()
Define property next_state.
@next_state.setter
def next_state(state: "state")
Set next state.
Arguments:
state
- (state) next state
@property
def prev_state()
Define property prev_state.
@prev_state.setter
def prev_state(state: "state")
Set previous state.
Arguments:
state
- (state) previous state
def __str__() -> str
Generate string for representation.
def __repr__() -> str
Call str() for representation.
State generator module.
def arg_extract(string: str, key_dict: dict) -> dict
Extract arguments from known command dictionaries.
Arguments:
string
- (str) string of Commandskey_dict
- (dict) dictionary with known commands and subcommands
Returns:
dict
- (dict) dictionary with all found keys and their arguments
def read_gcode_to_dict_list(filepath: pathlib.Path) -> List[dict]
Read gcode from .gcode file.
Arguments:
filename
- (Path) filepath of the .gcode file
Returns:
dict_list
- (list[dict]) list with every line as dict
def dict_list_traveler(line_dict_list: List[dict],
initial_machine_setup: dict) -> List[state]
Convert the line dictionary to a state.
Arguments:
line_dict_list
- (dict) dict list with commandsinitial_machine_setup
- (dict) dict with initial machine setup [absolute_position, absolute_extrusion, units, initial_position...]
Returns:
state_list
- (list[state]) all states in a list
def check_for_unsupported_commands(line_dict_list: dict) -> dict
Search for unsupported commands used in the G-code, warn the user and return the occurrences.
Arguments:
line_dict_list
dict - list of dicts containing all commands appearing
Returns:
dict
- a dict containing the appearing unsupported commands and how often they appear.
def generate_states(filepath: pathlib.Path,
initial_machine_setup: dict) -> List[state]
Generate state list from GCode file.
Arguments:
filepath
- (Path) filepath to GCodeinitial_machine_setup
- (dict) dictionary with machine setup
Returns:
states
- (list[states]) all states in a list
Tools for pyGCD.
def save_layer_metrics(simulation: simulation,
filepath: Union[pathlib.Path,
str] = "./layer_metrics.csv",
locale: str = None,
delimiter: str = ";")
Print out print times, distance traveled and the average travel speed to a csv-file.
Arguments:
-
simulation
- (simulation) simulation instance -
filepath
- (Path | string, default = "./layer_metrics.csv") file name -
locale
- (string, default = None) select locale settings, e.g. "en_US.utf8" "de_DE.utf8", None = use system locale -
delimiter
- (string, default = ";") select delimiterLayers are detected using the given layer cue.
def write_submodel_times(simulation: simulation,
sub_orig: list,
sub_side_x_len: float,
sub_side_y_len: float,
sub_side_z_len: float,
filename="submodel_times.yaml",
**kwargs)
Write the submodel entry and exit times to a yaml file.
Arguments:
simulation
- (simulation) the simulation instance to analyzesub_orig
- (list with [xcoord, ycoord, zcoord]) the origin of the submodel control volumesub_side_len
- (float) the side length of the submodel control volumefilename
- (string) yaml filename**kwargs
- (any) provide additional info to write into the yaml file
Utilitys.
Utils for the GCode Reader contains:
- vector 4D
- velocity
- position
class vector_4D()
The vector_4D class stores 4D vector in x,y,z,e.
Supports:
- str
- add
- sub
- mul (scalar)
- truediv (scalar)
- eq
def __init__(*args)
Store 3D position + extrusion axis.
Arguments:
args
- coordinates as arguments x,y,z,e or (tuple or list) [x,y,z,e]
def __str__() -> str
Return string representation.
def __add__(other)
Add functionality for 4D vectors.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray')
Returns:
add
- (self) component wise addition
def __sub__(other)
Sub functionality for 4D vectors.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray')
Returns:
sub
- (self) component wise subtraction
def __mul__(other)
Scalar multiplication functionality for 4D vectors.
Arguments:
other
- (float or int)
Returns:
mul
- (self) scalar multiplication, scaling
def __truediv__(other)
Scalar division functionality for 4D Vectors.
Arguments:
other
- (float or int)
Returns:
div
- (self) scalar division, scaling
def __eq__(other)
Check for equality and return True if equal.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray')
Returns:
eq
- (bool) true if equal (with tolerance)
def get_vec(withExtrusion=False) -> List[float]
Return the 4D vector, optionally with extrusion.
Arguments:
withExtrusion
- (bool, default = False) choose if vec repr contains extrusion
Returns:
vec
- (list[3 or 4]) with (x,y,z,(optionally e))
def get_norm(withExtrusion=False) -> float
Return the 4D vector norm. Optional with extrusion.
Arguments:
withExtrusion
- (bool, default = False) choose if norm contains extrusion
Returns:
norm
- (float) length/norm of 3D or 4D vector
class velocity(vector_4D)
4D - Velocity object for (Cartesian) 3D printer.
def __str__() -> str
Print out velocity.
def get_norm_dir(withExtrusion=False)
Get normalized vector (regarding travel distance), if only extrusion occurs, normalize to extrusion length.
Arguments:
withExtrusion
- (bool, default = False) choose if norm dir contains extrusion
Returns:
dir
- (list[3 or 4]) normalized direction vector as list
def avoid_overspeed(p_settings)
Return velocity without any axis overspeed.
Arguments:
p_settings
- (p_settings) printing settings
Returns:
vel
- (velocity) constrained by max velocity
def not_zero()
Return True if velocity is not zero.
Returns:
not_zero
- (bool) true if velocity is not zero
def is_extruding()
Return True if extrusion velocity is not zero.
Returns:
is_extruding
- (bool) true if positive extrusion velocity
class position(vector_4D)
4D - Position object for (Cartesian) 3D printer.
def __str__() -> str
Print out position.
def is_travel(other) -> bool
Return True if there is travel between self and other position.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray')
Returns:
is_travel
- (bool) true if between self and other is distance
def is_extruding(other: "position", ignore_retract: bool = True) -> bool
Return True if there is extrusion between self and other position.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray')ignore_retract
- (bool, default = True) if true ignore retract movements else retract is also extrusion
Returns:
is_extruding
- (bool) true if between self and other is extrusion
def get_t_distance(other=None, withExtrusion=False) -> float
Calculate the travel distance between self and other position. If none is provided, zero will be used.
Arguments:
other
- (4D vector, 1x4 'list', 1x4 'tuple' or 1x4 'numpy.ndarray', default = None)withExtrusion
- (bool, default = False) use or ignore extrusion
Returns:
travel
- (float) travel or extrusion and travel distance
class segment()
Store Segment data for linear 4D Velocity function segment.
contains: time, position, velocity Supports
- str
Additional methods
- move_segment_time: moves Segment in time by a specified interval
- get_velocity: returns the calculated Velocity for all axis at a given point in time
- get_position: returns the calculated Position for all axis at a given point in time
Class method
- create_initial: returns the artificial initial segment where everything is at standstill, intervall length = 0
- self_check: returns True if all self checks have been successfull
def __init__(t_begin: float,
t_end: float,
pos_begin: position,
vel_begin: velocity,
pos_end: position = None,
vel_end: velocity = None)
Initialize a segment.
Arguments:
t_begin
- (float) begin of segmentt_end
- (float) end of segmentpos_begin
- (position) beginning position of segmentvel_begin
- (velocity) beginning velocity of segmentpos_end
- (position, default = None) ending position of segmentvel_end
- (velocity, default = None) ending velocity of segment
def __str__() -> str
Create string from segment.
def __repr__()
Segment representation.
def move_segment_time(delta_t: float)
Move segment in time.
Arguments:
delta_t
- (float) time to be shifted
def get_velocity(t: float) -> velocity
Get current velocity of segment at a certain time.
Arguments:
t
- (float) time
Returns:
current_vel
- (velocity) velocity at time t
def get_position(t: float) -> position
Get current position of segment at a certain time.
Arguments:
t
- (float) time
Returns:
pos
- (position) position at time t
def self_check(p_settings=None)
Check the segment for self consistency.
todo:
- max acceleration
Arguments:
p_settings
- (p_setting, default = None) printing settings to verify
def is_extruding() -> bool
Return true if the segment is pos. extruding.
Returns:
is_extruding
- (bool) true if positive extrusion
@classmethod
def create_initial(cls, initial_position: position = None)
Create initial static segment with (optionally) initial position else start from Zero.
Arguments:
initial_position
- (postion, default = None) position to begin segment series
Returns:
segment
- (segment) initial beginning segment