FbicsTaskCc
From Opencam
/*Date: Thu, 31 Jul 2003 10:12:25 -0400 (EDT) From: "Tom Kramer" <kramerAT---.nist.---> Subject: Re: VWS-OLPS-FBCS/g-code generation software - source??? To: m pictorATy--oo.---
Hello Mark -
> What platform was that written for?
It was written for a Sun computer.
> How is this licensed? Public Domain?
It is public domain.
> Do you consider it stable, or a development version?
It is pretty stable. I never make changes without testing. I would not expect to have trouble making it compile on other platforms -- if I had the proprietary software it uses (see below).
> Do I understand correctly that VWS was both a design > environment and a CAM processing program? Does FBICS > include this as well?
VWS included design, process planning, and code generation. FBICS does not include design but has process planning and code generation. The main focus of FBICS was automated hierarchical process planning. The code generation in VWS is more extensive, but where FBICS generates, it does it better than VWS. I put minimal effort into the code generation part of FBICS since commercial systems are available that do better.
> Do I understand correctly that FBICS contains the > features of (or similar to) EMC?
FBICS contains the RS274 interpreter used in EMC. FBICS uses the NML messaging system developed by EMC. Other than that, FBICS and EMC have no common software.
FBICS is big. It consists of seven independent processes communicating using NML communications and STEP Part 21 files.
While FBICS itself is public domain, it uses three proprietary software systems that NIST cannot redistribute. These are: Parasolid for solid modeling, HOOPS for graphics, and STEPTools for data handling. All of these are available for several platforms including PCs, but you have to get your own copy. The use of HOOPS is isolated in the fbics_draw process, and the use of Parasolid is isolated in the fbics_model process, but STEPTools is used in several processes. FBICS includes around 100,000 lines of source code generated automatically by STEPTools and requires the STEPTools library.
The NC code generator is in the fbics_task process, I have attached the source code of fbics_task for your use. There is also a DMIS code generator in the source code. Functions that deal with NC code have "nc" in their names.
I hope this is helpful.
Tom K.
- /
//The following code was originally in a file named taskpl.cc //approximately 9782 lines (below this)
- include "taskpl.hh" /* includes needed stuff */
- include "fte_code.h"
/* declaration of other functions */
static how change_cutter_units(integral_cutting_edge_tool * a_cutter,
double factor, length_unit_type new_units);
static how change_part_units(RoseDesign * design,
List (Numeric_parameter) * parameter_list, double factor);
static how change_probe_units(
probe_tool * a_probe, double factor, length_unit_type new_units);
static how check_counterbore(Machining_feature * volume); static how check_hole(Machining_feature * volume); static how check_one_feature(Machining_feature * volume); static how check_other_feature(Machining_feature * volume); static how check_pocket(Machining_feature * volume); static how check_pocket_general(General_pocket * pocket); static how check_pocket_rectangular(Rectangular_closed_pocket * pocket); static how clean_taskpl(); static how dmis_feed( double feed, FILE * dmis_out); static how fab_bore(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_center_drill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_chamfer(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_counterbore(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_countersink(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_dmis_corner(
double center_x, double center_y, double center_z, double radius, double depth, double start, double angle, int how_many, double points[][3], double clear, double hitol, double lotol, char * text, FILE * dmis_out);
static how fab_dmis_hole(inspection_level_type level,
Round_hole * the_hole, probe_tool * probe, FILE * dmis_out);
static how fab_dmis_locate(
locate_part_block_block_ex * op, inspection_level_type level, probe_tool * probe, double feed, FILE * dmis_out);
static how fab_dmis_needs_tool(
inspection_level_type level, Machining_feature * volume, probe_tool * probe, double feed, FILE * dmis_out);
static how fab_dmis_no_tool(
inspect_no_tool * op, node * step, FILE * dmis_out);
static how fab_dmis_pocket_cylinders(
ListOfDouble * coords, double depth, double length, double width, Numeric_parameter * rad, double angle, double tip_radius, double tool_length, inspection_level_type level, FILE * dmis_out);
static how fab_dmis_pocket_planes(ListOfDouble * coords, double depth,
double length, double width, double radius, double angle, double tip_radius, double tool_length, inspection_level_type level, FILE * dmis_out);
static how fab_dmis_print_cylinder( double point_x, double point_y,
double point_z, double axis_x, double axis_y, double axis_z, double diameter, double length, int how_many, double (* points)[3], double retract, double uptol, double lotol, FILE * dmis_out);
static how fab_dmis_print_plane(
int pull_out, double point_x, double point_y, double point_z, double normal_x, double normal_y, double normal_z, int how_many, double (* points)[3], double retract, char * plane_name, FILE * dmis_out);
static how fab_dmis_rectangular_pocket(inspection_level_type level,
Rectangular_closed_pocket * a_pocket, probe_tool * probe, FILE * dmis_out);
static how fab_dmis_side_plane(
double height, double length, double min_length, double center_x, double center_y, double center_z, double offset, double angle, double clear, char * side_name, double points[][3], int how_many, FILE * dmis_out);
static how fab_face_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_finish_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_fly_cut(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_nc_needs_tool(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double stepover, double pass_depth, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_nc_no_tool(nc_no_tool * op, node * step); static how fab_peripheral_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_ream(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_rough_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_round(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_slot(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_tap(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how fab_twist_drill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double pass_depth, double stepover, double speed, double general_feed, ON_OFF flood, FEAT_MACH_STRATEGY machining_method);
static how find_horizontal_plane_points( double length, double width,
double radius, double center_x, double center_y, double center_z, double angle, int how_many, double (* points)[3], int * found);
static int find_if_close(double first, double second, double tolerance); static how find_inspection_point(double center_x, double center_y,
double x_size, double y_size, int nth, double * answer);
static how find_pocket_depth(Pocket_bottom_condition * bottom, double * depth); static double find_pocket_left_x(
double wy, double low_y, double left_x, double up_y, double radius);
static double find_pocket_right_x(
double wy, double low_y, double right_x, double up_y, double radius);
static double find_pocket_rotation(
double length, double width, ListOfDouble * coords);
static how find_probe_length(probe_tool * probe, double * length); static how find_tool_instance(List (tool_instance) * tools,
char * tool_instance_id, tool_instance ** the_tool);
static how find_vertical_cylinder_points(double center_x, double center_y,
double center_z, double radius, double depth, double start_angle, double end_angle, int how_many, double (* points)[3], int * found);
static how find_vertical_plane_points(
double length, double width, double offset, double center_x, double center_y, double center_z, double angle, int how_many, double (* points)[3], double size1, double size2, int * found);
static how generate_dmis(char * op_file_name, char * dmis_file_name); static how generate_dmis_change_tool(
tool_instance * the_tool, probe_tool * the_probe, FILE * dmis_out);
static how generate_end_dmis(FILE * dmis_out); static how generate_end_nc(); static how generate_initialize_dmis(FILE * dmis_out); static how generate_initialize_nc(); static how generate_nc(char * op_file_name, char * nc_file_name); static how length_units_same(List (Numeric_parameter) * parameter_list); static how nc_change_tool(tool_instance * tool); static how nc_feed(double feed); static how nc_finish_mill_pocket_bottom(
double stepover, double speed, double general_feed, double plunge_feed, double left_x, double right_x, double up_y, double low_y, double wy, double last_y, double radius, double depth, double top_z);
static how nc_finish_mill_pocket_rectangular(
Rectangular_closed_pocket * pocket, tool_instance * tool, double stepover, double speed, double general_feed, ON_OFF flood, double plunge_feed);
static how nc_finish_mill_pocket_regular(
Rectangular_closed_pocket * pocket, double tool_diameter, double stepover, double speed, double general_feed, double plunge_feed, ON_OFF flood);
static how nc_finish_mill_pocket_sides(
double radius, double right_x, double up_y, double left_x, double low_y, double top, double above, double depth);
static how nc_finish_mill_pocket_straight(
Rectangular_closed_pocket * pocket, double tool_diameter, double speed, double general_feed, double plunge_feed, ON_OFF flood, int pocket_type);
static how nc_flood(ON_OFF flood); static how nc_spindle_speed(double speed); static how nc_spindle_turning(CANON_DIRECTION direction); static how nc_retract(); static how pm_bottom_on_part(double length, double width, double center_x,
double center_y, double center_z, double angle, int * answer);
static how pm_circle_on_part(double x, double y, double z, double normal_x,
double normal_y, double normal_z, double radius, int * answer);
static how pm_copy_entity(int tag1, int * tag2, int set_part_flag); static how pm_corner_on_part(double radius, double height, double angle,
double base_x, double base_y, double base_z, double x_axis_x, double x_axis_y, double x_axis_z, int * answer);
static how pm_detach(); static how pm_model_part_in(
char * part_in_file_name, axis2_placement_setup * location);
static how pm_model_part_now(
char * part_in_file_name, axis2_placement_setup * location);
static how pm_model_part_out(
char * part_out_file_name, axis2_placement_setup * location);
static how pm_point_on_part(double x, double y, double z, int * answer); static how pm_rectangle_on_part(
double x, double y, double z, double normal_x, double normal_y, double normal_z, double length, double width, int * answer);
static how pm_show_volume(char * file_name, int volume_type); static how pm_side_on_part(
double length, double height, double offset, double center_x, double center_y, double center_z, double angle, int * answer);
static int point_in_pocket(double * point, double center_x, double center_y,
double length, double width, double radius);
static how print_nc_hexapod(FILE * nc_file, double code_list[][10], int stop); static how print_nc_ngc(FILE * nc_file, double code_list[][10], int stop); static how read_a_part(char * file_name, Part ** the_part); static how read_operation(
char * op_file_name, RoseDesign ** design, work_executable ** op);
static how read_shop_options(char * file_name); static how read_task_options(char * file_name); static how read_tool_catalog(char * file_name); static how read_tool_check_slots(List (tool_instance) * tools); static how read_tool_inventory(char * file_name); static how read_tool_link(
List (tool_instance) * inventory, RoseDesign * catalog);
static how rotate_pseudocode(double code_list[][10], int stop,
double angle, double center_x, double center_y);
static how rotate_xy_location(
double angle, double * ex, double * wy, double center_x, double center_y);
static how read_tool_inventory(char * file_name); static how set_adjustment(); static how set_parameter_limits(
Numeric_parameter * par, double * hitol, double * lotol);
static how verify_bore(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_center_drill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_chamfer(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_counterbore(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_countersink(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_dmis_op_locate_part(
inspection_level_type level, probe_tool * probe, double feed_rate);
static how verify_dmis_op_needs_tool(inspection_level_type level,
Machining_feature * volume, probe_tool * probe, double feed_rate);
static how verify_face_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_finish_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double general_feed, double stepover, FEAT_MACH_STRATEGY machining_method);
static how verify_finish_mill_rectangular_pocket(
Rectangular_closed_pocket * pocket, tool_instance * tool, double stepover, double speed, double general_feed, double plunge_feed);
static how verify_fly_cut(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
how verify_nc_op_needs_tool(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, ON_OFF flood, double pass_depth, double stepover, FEAT_MACH_STRATEGY machining_method);
static how verify_nc_op_no_tool(nc_no_tool * op, node * step); static how verify_peripheral_mill(nc_needs_tool * op,
Machining_feature * volume, tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_ream(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_rough_mill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_round(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_slot(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_tap(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how verify_twist_drill(nc_needs_tool * op, Machining_feature * volume,
tool_instance * tool, double speed, double feed_rate, FEAT_MACH_STRATEGY machining_method);
static how write_line1(int canon_name); static how write_line2(int canon_name, double argument1); static how write_line3(int canon_name, double argument1, double argument2); static how write_line4(
int canon_name, double argument1, double argument2, double argument3);
static how write_line5(int canon_name,
double argument1, double argument2, double argument3, double argument4);
static how write_line6(int canon_name, double argument1,
double argument2, double argument3, double argument4, double argument5);
static int zout(double numb, int precision);
extern char * nmlFile;
/* initialization of the _taskpl model */ task_planner _taskpl;
/*
The _nml_kludger initializes before anything else, so rcs_version_printed is set to 1, turning off version messages before initialization of any NML objects. Without this, NML initializations in other files that get linked may cause the message to be printed before main starts executing so that setting rcs_version_printed to 1 in main is too late.
- /
class nml_kludger{public: nml_kludger(){rcs_version_printed = 1;}}; nml_kludger _nml_kludger;
NML _pipe_task_to_model(fbics_format, "task_to_model", "fbics_task", nmlFile); NML _pipe_model_to_task(fbics_format, "model_to_task", "fbics_task", nmlFile);
/***********************************************************************/
/* change_cutter_units
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. A drill is not a twist_drill: FTE_DRILL_NOT_A_TWIST_DRILL. 2. A unknown tool type is used: FTE_UNKNOWN_CUTTER_TYPE 3. A tool type not yet handled is used: FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET.
Side Effects: See below
Called By: read_tool_catalog
- /
static how change_cutter_units( /* ARGUMENTS */
integral_cutting_edge_tool * a_cutter, /* the cutter having units changed */ double factor, /* factor for multiplying lengths */ length_unit_type new_units) /* new length unit */
{
const char name[] SET_TO "change_cutter_units"; tool_body * the_body; drill * a_drill; twist_drill * a_twist_drill; milling_cutter * a_mill; facemill * a_facemill; endmill * an_endmill;
a_cutter->length_units(new_units); the_body SET_TO a_cutter->body_information();
if (the_body->isa("drill"))
{
a_drill SET_TO ROSE_CAST(drill, the_body);
a_drill->cutting_diameter(factor * a_drill->cutting_diameter());
a_drill->overall_length(factor * a_drill->overall_length());
CHK((NOT(a_drill->isa("twist_drill"))), FTE_DRILL_NOT_A_TWIST_DRILL);
a_twist_drill SET_TO ROSE_CAST(twist_drill, a_drill);
a_twist_drill->depth_capacity(factor * a_twist_drill->depth_capacity());
a_twist_drill->web_thickness(factor * a_twist_drill->web_thickness());
a_twist_drill->margin_width(factor * a_twist_drill->margin_width());
a_twist_drill->flute_length(factor * a_twist_drill->flute_length());
}
else if (the_body->isa("countersink"))
{
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else if (the_body->isa("counterbore"))
{
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else if (the_body->isa("tap"))
{
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else if (the_body->isa("milling_cutter"))
{
a_mill SET_TO ROSE_CAST(milling_cutter, the_body);
a_mill->nose_radius(factor * a_mill->nose_radius());
a_mill->depth_capacity(factor * a_mill->depth_capacity());
a_mill->maximum_cutter_diameter(factor *
a_mill->maximum_cutter_diameter());
a_mill->overall_length(factor * a_mill->overall_length());
if (a_mill->isa("endmill"))
{ an_endmill SET_TO ROSE_CAST(endmill,a_mill); an_endmill->cutting_diameter(factor * an_endmill->cutting_diameter()); an_endmill->flute_length(factor * an_endmill->flute_length()); if (an_endmill->corner_radius() ISNT ROSE_NULL_REAL) an_endmill->corner_radius(factor * an_endmill->corner_radius()); if (an_endmill->nose_chamfer_length() ISNT ROSE_NULL_REAL) an_endmill->nose_chamfer_length(factor * an_endmill->nose_chamfer_length()); }
else if (a_mill->isa("facemill"))
{ a_facemill SET_TO ROSE_CAST(facemill, a_mill); a_facemill->cutting_diameter(factor * a_facemill->cutting_diameter()); }
else
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else if (the_body->isa("reamer"))
{
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else if (the_body->isa("boring_tool"))
{
ERM(FTE_NOT_HANDLING_THIS_TOOL_TYPE_YET);
}
else
ERM(FTE_UNKNOWN_CUTTER_TYPE);
return RET_OK;
}
/***********************************************************************/
/* change_part_units
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. The factor is neither 25.4 nor 1/25.4: FTE_BAD_FACTOR
Side Effects: See below
Called By: read_a_part
This changes the length units of a part from inches to millimeters or vice versa. If the change is from inches to millimeters: 1. "in" is changed to "mm" as the unit in all Numeric_parameters on the
parameter_list (which has already been made to include only Numeric_parameters representing length whose units are "in").
2. Values of all Numeric_parameters are multiplied by 25.4. 3. Upper and lower limits of plus_minus values are multiplied by 25.4. 4. All coordinates of location are multiplied by 25.4.
Analogous changes are made if the change is from "mm" to "in", but the multiplication factor is (1.0 / 25.4).
- /
static how change_part_units( /* ARGUMENTS */
RoseDesign * design, /* AP224 data design */ List (Numeric_parameter) * parameter_list, /* has "degrees" removed */ double factor) /* length conversion factor */
{
const char name[] SET_TO "change_part_units";
Numeric_parameter * a_parameter;
List (Plus_minus_value) plus_minus_list;
Plus_minus_value * a_plus;
List (Location_element) location_list;
ListOfDouble * coords;
int size;
int n;
size SET_TO parameter_list->size();
if (factor IS 25.4)
{
for (n SET_TO 0; n < size; n++)
{ (*parameter_list)[n]->parameter_units("mm"); }
}
else if (factor IS (1.0 / 25.4))
{
for (n SET_TO 0; n < size; n++)
{ (*parameter_list)[n]->parameter_units("in"); }
}
else
ERM(FTE_BAD_FACTOR);
for (n SET_TO 0; n < size; n++)
{
a_parameter SET_TO (*parameter_list)[n];
a_parameter->parameter_value(factor * a_parameter->parameter_value());
}
ROSE.findObjects(&plus_minus_list, design);
size SET_TO plus_minus_list.size();
for (n SET_TO 0; n < size; n++)
{
a_plus SET_TO plus_minus_list[n];
a_plus->upper_limit(factor * a_plus->upper_limit());
a_plus->lower_limit(factor * a_plus->lower_limit());
}
ROSE.findObjects(&location_list, design);
size SET_TO location_list.size();
for (n SET_TO 0; n < size; n++)
{
coords SET_TO location_list[n]->coordinates();
coords->put((factor * (*coords)[0]), 0);
coords->put((factor * (*coords)[1]), 1);
coords->put((factor * (*coords)[2]), 2);
}
return RET_OK;
}
/***********************************************************************/
/* change_probe_units
Returned Value: how (RET_OK)
Side Effects: See below
Called By: read_tool_catalog
- /
static how change_probe_units(
probe_tool * a_probe, double factor, length_unit_type new_units)
{
const char name[] SET_TO "change_probe_units"; ListOfDouble * liz;
a_probe->length_units(new_units); liz SET_TO a_probe->probe_length(); liz->put((factor * (*liz)[0]), 0); liz->put((factor * (*liz)[1]), 1); liz->put((factor * (*liz)[2]), 2); a_probe->diameter(factor * a_probe->diameter()); if (a_probe->tip_length() ISNT ROSE_NULL_REAL) a_probe->tip_length(factor * a_probe->tip_length()); return RET_OK;
}
/***********************************************************************/
/* check_counterbore
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
check_one_feature
THIS IS A STUB for checking a counterbore feature.
Add checks: 1. hole taper list is empty 2. the two holes comprising the counterbore make a reasonable counterbore
A. The two axes are nearly the same.
B. A line between the points of the locations of the holes is nearly
parallel (or anti-parallel) to the axes.
C. The larger hole does not extend beyond the smaller hole in the
axial direction.
Since the counterbore being worked on here is a relocated copy of the original counterbore, some of the above will not be easy to do. When the smaller hole is made, it is made from a different copy of the smaller hole.
- /
static how check_counterbore( /* ARGUMENTS */
Machining_feature * volume) /* pointer to a Machining_feature */
{
const char name[] SET_TO "check_counterbore"; return RET_OK;
}
/****************************************************************************/
/* check_hole
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
check_one_feature
THIS IS A STUB.
- /
static how check_hole( /* ARGUMENTS */
Machining_feature * volume) /* pointer to a Machining_feature */
{
const char name[] SET_TO "check_hole"; return RET_OK;
}
/****************************************************************************/
/* check_one_feature
Returned Value: how
If any function called returns an error code, this returns that code. Otherwise, it returns RET_OK.
Side effects:
One Machining_feature is checked
Called by:
generate_nc_needs_tool
The feature checkers check that a feature is a realizable and reasonable feature. They do not check that the feature is machinable by some operation. The operation verifiers make these checks for specific operations.
This is currently only making real checks on three feature types. Other types should be added, and the "else" should report an error.
If the rest of the system is working, the volume should not be NULL, so this is not checking that. Probably get a segmentation fault here if a NULL slips through.
- /
static how check_one_feature( /* ARGUMENTS */
Machining_feature * volume) /* pointer to a removal volume */
{
const char name[] SET_TO "check_one_feature"; checker_pointer function;
if (volume->isa("Hole"))
function SET_TO check_hole;
else if (volume->isa("Pocket"))
function SET_TO check_pocket;
else if (volume->isa("Counterbore"))
function SET_TO check_counterbore;
else
function SET_TO check_other_feature;
IFF (function(volume));
return RET_OK;
}
/****************************************************************************/
/* check_other_feature
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
check_one_feature
THIS IS A STUB.
- /
static how check_other_feature( /* ARGUMENTS */
Machining_feature * volume) /* pointer to a Machining_feature */
{
const char name[] SET_TO "check_other_feature"; return RET_OK;
}
/****************************************************************************/
/* check_pocket
Returned Value: how
If any of the following errors occur, this returns the error code shown.
Otherwise, it returns RET_OK.
1. check_pocket_rectangular is called and does not return RET_OK.
2. check_pocket_general is called and does not return RET_OK.
3. The pocket is not a Rectangular_pocket or a General_pocket:
FTE_POCKET_IS_NOT_RECTANGULAR_OR_GENERAL
Side effects: None
Called by:
check_one_feature
- /
static how check_pocket( /* ARGUMENTS */
Machining_feature * volume) /* pointer to a Machining_feature */
{
const char name[] SET_TO "check_pocket";
if (volume->isa("Rectangular_closed_pocket"))
{
IFF (check_pocket_rectangular(ROSE_CAST(Rectangular_closed_pocket,
volume)));
}
else if (volume->isa("General_pocket"))
{
IFF (check_pocket_general(ROSE_CAST(General_pocket, volume)));
}
else
ERM(FTE_POCKET_IS_NOT_RECTANGULAR_OR_GENERAL);
return RET_OK;
}
/****************************************************************************/
/* check_pocket_general
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
check_pocket
THIS IS A STUB for checking a General_pocket.
- /
static how check_pocket_general( /* ARGUMENTS */
General_pocket * pocket) /* pointer to a General_pocket */
{
const char name[] SET_TO "check_pocket_general"; return RET_OK;
}
/****************************************************************************/
/* check_pocket_rectangular
Returned Value: how
If any of the following errors occur, this returns the error code shown.
Otherwise, it returns RET_OK.
1. The length of the pocket is not positive:
FTE_RECTANGULAR_POCKET_LENGTH_IS_NOT_POSITIVE
2. The width of the pocket is not positive:
FTE_RECTANGULAR_POCKET_WIDTH_IS_NOT_POSITIVE
3. The corner radius of the pocket is negative (zero is OK):
FTE_RECTANGULAR_POCKET_CORNER_RADIUS_IS_NEGATIVE
4. The corner radius of the pocket is too big to fit into the pocket:
FTE_RECTANGULAR_POCKET_CORNER_RADIUS_IS_TOO_BIG_TO_FIT
Side effects:
None.
Called by:
check_pocket
We are assuming here that the placement of the Rectangular_closed_profile which is the boundary of the pocket is irrelevant, since it is not used. We are assuming that the center of the Rectangular_closed_profile is at the location point of the placement of the pocket itself and that the length and width directions of the profile are parallel to the X and Y axis directions of the placement of the pocket.
add: 1. check that bottom of the pocket is below the top (as given by the
placement of the pocket).
2. check that the depth of the pocket is as may be calculated by knowing
the top and bottom planes and the profile.
- /
static how check_pocket_rectangular( /* ARGUMENTS */
Rectangular_closed_pocket * pocket) /* pointer to a Rectangular_pocket */
{
const char name[] SET_TO "check_pocket_rectangular"; double length; /* side of rectangle parallel to X-axis (before rounding) */ double width; /* side of rectangle parallel to Y-axis (before rounding) */ double radius; /* radius of corner rounding in all four corners */ double depth; /* depth of the pocket */
length SET_TO pocket->closed_boundary()->profile_length()->parameter_value(); width SET_TO pocket->closed_boundary()->profile_width()->parameter_value(); radius SET_TO pocket->closed_boundary()->corner_radius()->parameter_value();
CHK((length <= 0.0), FTE_RECTANGULAR_POCKET_LENGTH_IS_NOT_POSITIVE);
CHK((width <= 0.0), FTE_RECTANGULAR_POCKET_WIDTH_IS_NOT_POSITIVE);
CHK((radius < 0.0), FTE_RECTANGULAR_POCKET_CORNER_RADIUS_IS_NEGATIVE);
CHK(((MIN(length, width) + FEAT_TINY) < (2 * radius)),
FTE_RECTANGULAR_POCKET_CORNER_RADIUS_IS_TOO_BIG_TO_FIT);
return RET_OK;
}
/****************************************************************************/
/* clean_taskpl
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. pm_detach returns an error code.
Side Effects:
This cleans the _taskpl model as described below.
Called By:
init_taskpl exit_taskpl
The flags for plan, nc, and dmis being in progress are turned off. All pointers are set to NULL. All persistent STEPTools objects are cleaned out. Default values are reset.
- /
static how clean_taskpl() /* NO ARGUMENTS */ {
const char name[] SET_TO "clean_taskpl"; int n;
if (_taskpl.attached IS 1)
{
IFF (pm_detach()); /* sets _taskpl.attached 0 */
}
_taskpl.current_tool SET_TO NULL;
/* _taskpl.current_x SET_TO UNKNOWN_LOCATION; */
/* _taskpl.current_y SET_TO UNKNOWN_LOCATION; */
/* _taskpl.current_z SET_TO UNKNOWN_LOCATION; */
_taskpl.dmis_feat SET_TO 0;
_taskpl.dmis_started SET_TO OFF;
for (n SET_TO 0; n < MACH_TOOL_MAX; n++)
{
_taskpl.dmis_tools[n][0] SET_TO 0;
}
_taskpl.feed_rate_dmis SET_TO 0;
_taskpl.feed_rate_nc SET_TO 0;
_taskpl.flood SET_TO OFF;
_taskpl.length_units_factor SET_TO -1.0; /* -1.0 means unset */
_taskpl.nc_line SET_TO 0;
_taskpl.nc_started SET_TO OFF;
_taskpl.sequence_number SET_TO 0;
_taskpl.setup_pointer SET_TO NULL;
_taskpl.setup_speci SET_TO NULL;
_taskpl.tool_catalog SET_TO NULL;
_taskpl.tool_catalog_file_name[0] SET_TO 0;
_taskpl.tool_inventory_pointer SET_TO NULL;
_taskpl.tool_inventory_file_name[0] SET_TO 0;
_taskpl.tools SET_TO NULL;
ROSE.clearWorkspace();
return RET_OK;
}
/***********************************************************************/
/* dmis_feed
Returned Value: how (RET_OK)
Side effects: See below.
Called by:
fab_dmis_needs_tool
If the desired feed is not the feed_rate_dmis stored in the _taskpl model, pseudocode is generated for changing the feed rate and the feed_rate_dmis setting in the _taskpl model is reset.
Length units are set to MM at the beginning of the DMIS program. It is assumed here that the given feed rate is in MM per minute. That unit is not available in DMIS for a feed rate. The closest thing available in DMIS is meters per minute, so this sets the feed rate to feed/1000.
FIX - The above paragraph may not be true. Check it and fix if needed.
- /
static how dmis_feed(/* ARGUMENTS */
double feed, /* feed rate, MM per minute */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "dmis_feed";
if (_taskpl.feed_rate_dmis ISNT feed)
{
fprintf(dmis_out, "FEDRAT/MESVEL, MPM, %.3lf\n", (feed/1000.0));
_taskpl.feed_rate_dmis SET_TO feed; /* in MM per minute */
}
return RET_OK;
}
/***********************************************************************/
/* fab_bore
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_bore( /* ARGUMENTS */
nc_needs_tool * op, /* the bore_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_bore"; return RET_OK;
}
/***********************************************************************/
/* fab_center_drill
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_center_drill( /* ARGUMENTS */
nc_needs_tool * op, /* the center_drill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_center_drill"; return RET_OK;
}
/***********************************************************************/
/* fab_chamfer
Returned Value: how (RET_OK)
Side effects:
None.
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_chamfer( /* ARGUMENTS */
nc_needs_tool * op, /* the machine_chamfer_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_chamfer"; return RET_OK;
}
/***********************************************************************/
/* fab_counterbore
Returned Value: how (RET_OK)
Side effects:
Pseudocode is generated for making a counterbore. The current location is reset.
Called by:
fab_nc_needs_tool
The procedure is:
1. Traverse parallel to the Z-axis to retract_high if not already at
that z-height (normally will be).
2. If necessary, change spindle speed, and/or start spindle clockwise.
3. If necessary, change feed rate to general_feed.
4. Traverse parallel to the XY-plane to the XY location of the hole.
5. Traverse parallel to the Z-axis to one retract_distance_low (a machining option) above the top of the hole.
6. Feed to the bottom of the hole.
When this finishes, the tool tip is at the bottom of the hole which has been counterbored.
The hole that is counterbored is the larger_hole of the counterbore feature (which consists of two holes).
- /
static how fab_counterbore( /* ARGUMENTS */
nc_needs_tool * op, /* the counterboring_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_counterbore"; Round_hole * the_hole; /* the hole to be counterbored */ double ex; /* x coordinate of hole */ double wy; /* y coordinate of hole */ double top_z; /* z coordinate of top of hole */ double depth; /* depth of hole */ ListOfDouble * coords; /* list of coordinates of hole */
the_hole SET_TO ROSE_CAST (Round_hole, volume); depth SET_TO the_hole->hole_depth()->parameter_value(); coords SET_TO the_hole->placement()->location()->coordinates(); ex SET_TO (*coords)[0]; wy SET_TO (*coords)[1]; top_z SET_TO (*coords)[2]; nc_retract(); nc_flood(flood); nc_spindle_speed(speed); nc_spindle_turning(CANON_CLOCKWISE); nc_feed(general_feed); write_line3(CANON_TRAVERSE_XY, ex, wy); write_line2(CANON_TRAVERSE_Z, (top_z + _taskpl.retract_distance_low)); write_line2(CANON_FEED_Z, (top_z - depth)); _taskpl.current_x SET_TO ex; _taskpl.current_y SET_TO wy; _taskpl.current_z SET_TO (top_z - depth); return RET_OK;
}
/***********************************************************************/
/* fab_countersink
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_countersink( /* ARGUMENTS */
nc_needs_tool * op, /* the countersinking_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_countersink"; return RET_OK;
}
/***********************************************************************/
/* fab_dmis_corner
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. find_vertical_cylinder_points returns an error code. 2. fab_dmis_print_cylinder returns an error code. 3. pm_corner_on_part returns an error code.
Side Effects: See below
called by: fab_dmis_pocket_cylinders
This generates DMIS code for a partial cylinder which is a vertical (axis parallel to z-axis) corner of a pocket.
- /
static how fab_dmis_corner( /* ARGUMENTS */
double center_x, /* x value of center of cylinder top */ double center_y, /* y value of center of cylinder top */ double center_z, /* z value of center of cylinder top */ double radius, /* corner radius */ double depth, /* depth of cylinder */ double start, /* angle of rotation of corner start from X-axis */ double angle, /* included angle of corner */ int how_many, /* number of points desired to be found */ double points[][3], /* point array to be filled */ double clear, /* clearance for center of probe tip */ double hitol, /* upper diameter tolerance */ double lotol, /* lower diameter tolerance */ char * text, /* text to add to warning */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_corner"; int found; /* corner on part flag & number points found */
IFF (pm_corner_on_part(radius, depth, angle, center_x, center_y,
(center_z - depth), cos(start), sin(start), 0.0, &found));
if (found ISNT 0)
{
IFF(find_vertical_cylinder_points(center_x, center_y, center_z,
radius, depth, start, (start + angle), how_many, points, &found));
if (found < how_many) /* if not enought points, warn user */
fprintf(stderr, "Warning: cannot inspect pocket %s\n", text);
else
IFF (fab_dmis_print_cylinder(center_x, center_y, (center_z - depth), 0, 0, 1, (2 * radius), depth, how_many, points, clear, hitol, lotol, dmis_out));
} else; /* if corner not on part - do nothing */ return RET_OK;
}
/***********************************************************************/
/* fab_dmis_hole
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. set_parameter_limits returns an error code. 2. find_vertical_cylinder_points returns an error code. 3. fab_dmis_print_cylinder returns an error code.
Side effects: See below
Called by: fab_dmis_needs_tool
This is inspecting the side of an AP224 Round_hole as a DMIS cylinder, if the depth of the hole is at least twice the probe tip diameter and the diameter of the hole is at least twice the probe tip diameter.
This does not inspect the bottom of the hole. It should probably be changed to do so.
If the side of the hole fails the criteria for inspecting, a warning message is printed.
A Round_hole could also be inspected as one to many DMIS circles. It might be good to add a task options regarding how a Round_hole is inspected to allow this alternative.
This checks that all the touch points are actually present on the surface. This check is needed because it is not safe to attempt to probe a point not on the surface of the part. Points inside the part or outside the part will be rejected.
This is not adjusting the depth of the side of the hole in cases where the bottom is not flat. This means that points near the bottom of the hole not on the side might be candidate inspection points, but they will be rejected since they are inside material. A bottom adjustment should probably be added, however, since if a touch point is on the side very near the bottom, the probe tip might hit the bottom while moving horizontally toward the point, giving a bad reading for that point. The size of the adjustment will depend on the bottom type and its parameters.
This function expects that the probe will be above the part when it takes over, as is done by fab_dmis_needs_tool.
fab_dmis_print_cylinder resets the value of the current location at the end of inspecting the hole. The probe is left at the approach point for the last inspection point.
- /
static how fab_dmis_hole( /* ARGUMENTS */
inspection_level_type level, /* inspection level */ Round_hole * the_hole, /* pointer to a hole to inspect */ probe_tool * probe, /* pointer to probe to use */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_hole"; ListOfDouble * coords; /* coordinates of hole top center */ double depth; /* depth of hole */ double radius; /* radius of hole */ double hitol; /* upper diameter tolerance */ double lotol; /* lower diameter tolerance */ double tip_radius; /* radius of probe tip */ double tool_length; /* length of probe to tip center */ int how_many; /* number of points desired */ double clear; /* clearance of center of tool tip */ int found; /* number of points found */ double (* points)[3]; /* array to fill with points */ Numeric_parameter * diameter; /* diameter parameter */ double height; /* height of portion to inspect */
coords SET_TO the_hole->placement()->location()->coordinates();
diameter SET_TO the_hole->diameter()->diameter();
radius SET_TO (diameter->parameter_value())/2;
depth SET_TO the_hole->hole_depth()->parameter_value();
tip_radius SET_TO (probe->diameter() / 2.0);
IFF(find_probe_length(probe, &tool_length));
IFF (set_parameter_limits(diameter, &hitol, &lotol));
clear SET_TO (tip_radius + _taskpl.inspect_clear);
how_many SET_TO
((level IS inspection_level_type_high) ?
_taskpl.inspect_points_cylinder_high:
(level IS inspection_level_type_low) ?
_taskpl.inspect_points_cylinder_low :
_taskpl.inspect_points_cylinder_medium);
if (clear > radius)
fprintf(dmis_out, "$$ hole too narrow to inspect with given clearance\n");
else if ((depth - clear) < tip_radius)
fprintf(dmis_out, "$$ hole too shallow to inspect with given clearance\n");
else
{
points SET_TO new double[how_many][3];
height SET_TO MIN((depth - clear), tool_length);
IFF(find_vertical_cylinder_points
((*coords)[0], (*coords)[1], (*coords)[2], radius, height, 0.0, (2 * M_PI), how_many, points, &found));
if (found < how_many)
fprintf(dmis_out, "$$ hole has too little surface to inspect\n");
else
{ fprintf(dmis_out, "$$ inspecting hole\n"); fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n", ZOUT((*coords)[0]), ZOUT((*coords)[1]), ZOUT(_taskpl.retract_high_dmis)); IFF (fab_dmis_print_cylinder((*coords)[0], (*coords)[1], ((*coords)[2] - depth), 0, 0, 1, (2 * radius), depth, how_many, points, clear, hitol, lotol, dmis_out)); }
delete [] points; /* since made with "new" above */ } return RET_OK;
}
/***********************************************************************/
/* fab_dmis_locate
Returned Value: how
If any of the following errors occur, this records the error shown
and returns the error code. Otherwise, it returns RET_OK.
1. dmis_feed returns an error code.
2. find_probe_length returns an error code.
3. The first given corner is not at the origin:
FTE_FIRST_BLOCK_CORNER_NOT_AT_ORIGIN
4. The z-coordinates of corners 2 and 3 are not the same or
corner2 Y is not zero or corner3 X is not zero:
FTE_BAD_BLOCK_CORNERS
5. The block is too thin or narrow to probe with the given
probe and expected errors: FTE_CANNOT_PROBE_BLOCK_TO_LOCATE_PART
6. find_vertical_plane_points returns an error code.
7. find_vertical_plane_points does not find enough points:
FTE_COULD_NOT_FIND_POINTS_TO_LOCATE_PART
8. fab_dmis_print_plane returns an error code.
Side effects: See below
Called by: generate_dmis_needs_tool
BACKGROUND
This function is used when a part to be inspected has been roughly located on the table of a CMM with the assistance of a vision system. This function provides for locating the part exactly (within the accuracy of the CMM) by probing the sides of the part. The AP224 part model must be built by applying subtractive features to a block shape, and the enough of the exterior of the block must exist on the part so that one face of the block lies on the CMM table and probe points may be found on two of the four faces of the block that are vertical when the part lies on the CMM table.
Read the documentation of the set_locate_attributes function from the workpl.cc file before trying to understand the documentation immediately below.
Several coordinate systems are involved:
1. The machine coordinate system of the CMM (in the view of the DMIS interpreter). 2. The coordinate system of 2D data on the appearance of a part generated from a CAD model of the part and used by the vision system. 3. The setup coordinate system telling where the part is intended to be in relation to the CMM's machine coordinate system. 4. The coordinate system of the block base shape of the part, as located in the part coordinate system. 5. The coordinate system in which CMM control data and probe data are expressed.
The first of these, the machine coordinate system, must be located so its XY plane is coincident with the plane of the CMM table.
The location of the second of these systems with respect to the part is described in the documentation of set_locate_attributes, mentioned above.
The third and fourth coordinate systems must be such that (i) one face of the block base shape is on the CMM table, (ii) one edge of the block is on the +X axis of the machine coordinate system, and (iii) another edge of the block is on the +Y axis (implying, of course, that one corner of the block is at the origin of the machine coordinate system). The actual placement of the block on the CMM table must have the correct face down, but, otherwise, the block may be rotated and translated from its nominal position as given by these two coordinate systems. The nominal placement is important so that the modeler will locate its model where the DMIS generator thinks it is (the place just described) when the generator uses the modeler.
The last of the five coordinate systems listed above is actually four coordinate systems located closer and closer to where it should be as processing proceeds: FINAL, ROT2, TRANS2, and TRANS3. FINAL is the coordinate system found by the vision system and is active when this function begins work. The other three coordinate systems are defined by this function. In this coordinate system, the block is in the position described in the preceding paragraph.
The requirement on the location of the block could be dropped by adding lines to this function to tell the modeler to relocate the block, but that does not seem to be worth the trouble; no generality is lost by requiring the block to be positioned nominally in a specific place.
This method of locating the part focuses on the block base shape for the part, not on the part itself. Thus the second and third coordinate systems may have the part in any position in the machine coordinate system and may have the block in any position in the part coordinate system, but the combination of the two coordinate system placements must put the block in the required position.
WHAT THE FUNCTION DOES
DMIS code to locate the part is generated and printed to a file. The program portion which is generated will include a move for retracting in the z-direction (if not already retracted). This also includes a retract move at the end.
The function receives (from the operation for which this is writing code) the location of three points representing the corners of a block: (1) c1 (c1x, c1y, c1z), a lower corner common to side1 and side2. (2) c2 (c2x, c2y, c2z), the diagonally opposite corner of side1. (3) c3 (c3x, c3y, c3z), the diagonally opposite corner of side2. The values must be such that four faces of the block are vertical and two horizontal.
The corner coordinates are in terms of the machine coordinate system. As described in BACKGROUND above, c1 must be (0, 0, 0), c2y must be 0, c3x must be 0, and c2z must equal c3z. These things are checked by the function (allowing small deviations)
The actual location of the block may differ from the nominal location by a translation (origin error) and a rotation (angle error) of the block. The code written by this function moves the coordinate system so that the block is exactly (within probe measurement error) where it is supposed to be.
The procedure for setting the new DMIS coordinate system is: 1. Define and measure XZ_PLANE1 on side1 of the block. 2. Define a horizontal line on the measured XZ_PLANE1. 3. Rotate the coordinate system in which DMIS works so its X-axis
is parallel to the horizontal line.
4. Define (in the new coordinate system) and measure XZ_PLANE2 on side1
of the block.
5. Translate the coordinate system in which DMIS works parallel to its
Y-axis so its X-axis lies on XZ_PLANE2.
6. Define (in the newer coordinate system) and measure YZ_PLANE on side2
of the block.
7. Translate the coordinate system in which DMIS works parallel to its
X-axis so its Y-axis lies on YZ_PLANE.
In the calls to find_vertical_plane_points, the length of the rectangle is used for the offset to the center of rotation.
The DMIS code written by this function uses the variables: X1, Y1, Z1, X2, Y2, NX, NY. These are DECLared in the code written by generate_initialize_dmis.
The goto point before a probe point is on the normal to the plane at a stand-off distance away from the plane which is equal to maximum error plus the desired clearance plus the tip radius. The maximum error is calculated using the given location error and angle error, and is recalculated after the coordinate system is rotated to cancel the angle error.
The approach distance is half the desired clearance less than the stand-off distance. This is a little arbitrary but workable. The approach distance must not be zero and should be less than the stand-off distance. The given method satisfies those criteria.
- /
static how fab_dmis_locate( /* ARGUMENTS */
locate_part_block_block_ex * op, /* the locate operation */ inspection_level_type level, /* inspection level */ probe_tool * probe, /* pointer to probe to use */ double feed, /* feed rate for operation */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_locate"; double c1x, c1y, c1z; /* lower corner common to both sides */ double c2x, c2y, c2z; /* corner of 1st side diagonally opposite corner1 */ double c3x, c3y, c3z; /* corner of 2nd side diagonally opposite corner1 */ double tip_radius; /* radius of probe tip */ double tool_length; /* length of tool to center of probe tip */ double approach; /* approach and search distance */ double height; /* height of rectangle inspected */ double angle; /* maximum position angle error in radians */ double omax; /* maximum origin location error */ double travel; /* stand-off distance for goto points */ double err_length; /* length of error rectangle */ double (*points)[3]; /* inspection points made here */ int how_many; /* number of points to inspect on a plane */ int found; /* number of points found on plane */
c1x SET_TO (*(op->corner1()))[0]; c1y SET_TO (*(op->corner1()))[1]; c1z SET_TO (*(op->corner1()))[2]; c2x SET_TO (*(op->corner2()))[0]; c2y SET_TO (*(op->corner2()))[1]; c2z SET_TO (*(op->corner2()))[2]; c3x SET_TO (*(op->corner3()))[0]; c3y SET_TO (*(op->corner3()))[1]; c3z SET_TO (*(op->corner3()))[2]; CHK (((c1x < -FEAT_TINY) OR (c1x > FEAT_TINY) OR
(c1y < -FEAT_TINY) OR (c1y > FEAT_TINY) OR (c1z < -FEAT_TINY) OR (c1z > FEAT_TINY)),
FTE_FIRST_BLOCK_CORNER_NOT_AT_ORIGIN);
CHK(((c2z ISNT c3z) OR /* corners 2 & 3 Z differ */
(c2z < FEAT_TINY) OR /* corner2 Z too small */
(c2x < FEAT_TINY) OR /* corner2 X too small */
(c3y < FEAT_TINY) OR /* corner3 Y too small */
(c2y > FEAT_TINY) OR (c2y < -FEAT_TINY) OR /* c2y not zero */
(c3x > FEAT_TINY) OR (c3x < -FEAT_TINY)), /* c3x not zero */
FTE_BAD_BLOCK_CORNERS);
tip_radius SET_TO (probe->diameter() / 2.0);
IFF(find_probe_length(probe, &tool_length));
how_many SET_TO
((level IS inspection_level_type_high) ? _taskpl.inspect_points_plane_high:
(level IS inspection_level_type_low) ? _taskpl.inspect_points_plane_low :
_taskpl.inspect_points_plane_medium);
points SET_TO new double[how_many][3];
IFF (dmis_feed(feed, dmis_out)); if (_taskpl.current_z < _taskpl.retract_high_dmis) fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(_taskpl.current_x), ZOUT(_taskpl.current_y), ZOUT(_taskpl.retract_high_dmis));
fprintf(dmis_out, "$$ Define and measure side of part on XZ plane.\n"); angle SET_TO (op->angle_error_max() * M_PI / 180); omax SET_TO op->origin_error_max(); err_length SET_TO (2 * (((omax + c2x) / cos(angle)) - c2x)); height SET_TO MIN((c2z - tip_radius), (tool_length - op->shape_error_max())); CHK((height < FEAT_TINY), FTE_CANNOT_PROBE_BLOCK_TO_LOCATE_PART); CHK(((c2x - err_length) < FEAT_TINY), FTE_CANNOT_PROBE_BLOCK_TO_LOCATE_PART); IFF(find_vertical_plane_points((c2x - err_length), height, c2x, c2x/2,
-c2x, (c2z - (height / 2)), M_PI_2, how_many, points, err_length, (2 * (op->shape_error_max())), &found));
CHK((found ISNT how_many), FTE_COULD_NOT_FIND_POINTS_TO_LOCATE_PART); travel SET_TO (tip_radius +_taskpl.inspect_clear + (omax * cos(angle)) +
((c2x + (omax * sin(angle))) * tan(angle)));
approach SET_TO (travel - (_taskpl.inspect_clear / 2.0)); fprintf(dmis_out, "SNSET/APPRCH, %.*lf\n", ZOUT(approach)); fprintf(dmis_out, "SNSET/SEARCH, %.*lf\n", ZOUT(approach)); IFF (fab_dmis_print_plane(1, 0, 0, 0, 0, -1, 0, how_many,
points, travel, "XZ_PLANE1", dmis_out));
fprintf(dmis_out, "$$ Construct a horizontal line on the measured XZ\n");
fprintf(dmis_out, "$$ side plane and rotate the coordinate system\n");
fprintf(dmis_out, "$$ about the Z-axis so the X-axis is\n");
fprintf(dmis_out, "$$ parallel to that line.\n");
fprintf(dmis_out, "X1 = OBTAIN/FA(XZ_PLANE1),3\n");
fprintf(dmis_out, "Y1 = OBTAIN/FA(XZ_PLANE1),4\n");
fprintf(dmis_out, "Z1 = OBTAIN/FA(XZ_PLANE1),5\n");
fprintf(dmis_out, "NX = OBTAIN/FA(XZ_PLANE1),6\n");
fprintf(dmis_out, "NY = OBTAIN/FA(XZ_PLANE1),7\n");
fprintf(dmis_out, "X2 = ASSIGN/(X1 - NY)\n");
fprintf(dmis_out, "Y2 = ASSIGN/(Y1 + NX)\n");
fprintf(dmis_out,
"F(XZ_LINE) = FEAT/LINE, BND, CART, X1, Y1, Z1, X2, Y2, Z1, 0, -1, 0\n");
fprintf(dmis_out, "D(ROT2) = ROTATE/ZAXIS, F(XZ_LINE), XDIR\n");
fprintf(dmis_out, "$$ Define and measure side of part on XZ plane again.\n"); travel SET_TO (tip_radius + _taskpl.inspect_clear + omax); approach SET_TO (travel - (_taskpl.inspect_clear / 2.0)); fprintf(dmis_out, "SNSET/APPRCH, %.*lf\n", ZOUT(approach)); fprintf(dmis_out, "SNSET/SEARCH, %.*lf\n", ZOUT(approach)); IFF (fab_dmis_print_plane(1, 0, 0, 0, 0, -1, 0, how_many,
points, travel, "XZ_PLANE2", dmis_out));
fprintf(dmis_out, "$$ Translate the coordinate system by the difference\n"); fprintf(dmis_out, "$$ between the measured Y-coordinate of the point on\n"); fprintf(dmis_out, "$$ the plane and the nominal Y-coordinate. This will\n"); fprintf(dmis_out, "$$ put the orgin on the XZ side of the block while\n"); fprintf(dmis_out, "$$ keepingthe X-axis parallel to that side. This\n"); fprintf(dmis_out, "$$ procedure relies on the measured point on the\n"); fprintf(dmis_out,
"$$ plane being the point closest to the nominal point.\n");
fprintf(dmis_out, "Y1 = OBTAIN/FA(XZ_PLANE2), 4\n"); fprintf(dmis_out, "D(TRANS2) = TRANS/YORIG, Y1\n");
fprintf(dmis_out, "$$ Define and measure side of part on YZ plane\n"); IFF(find_vertical_plane_points(c3y, height, c3y, -c3y, c3y/2,
(c3z - (height / 2)), 0, how_many, points, op->shape_error_max(), 0, &found));
CHK((found ISNT how_many), FTE_COULD_NOT_FIND_POINTS_TO_LOCATE_PART); IFF (fab_dmis_print_plane(1, 0, 0, 0, -1, 0, 0, how_many,
points, travel, "YZ_PLANE", dmis_out));
fprintf(dmis_out, "X1 = OBTAIN/FA(YZ_PLANE),3\n"); fprintf(dmis_out, "D(TRANS3) = TRANS/XORIG, X1\n"); fprintf(dmis_out, "SAVE/D(TRANS3)\n"); approach SET_TO (tip_radius + (_taskpl.inspect_clear / 2.0)); fprintf(dmis_out, "SNSET/APPRCH, %.*lf\n", ZOUT(approach)); fprintf(dmis_out, "SNSET/SEARCH, %.*lf\n", ZOUT(approach)); strcpy(_taskpl.current_system_name, "TRANS3"); delete [] points; /* since made by "new" above */ return RET_OK;
}
/***********************************************************************/
/* fab_dmis_needs_tool
Returned Value: how
If any of the following errors occur, this records the error shown
and returns the error code. Otherwise, it returns RET_OK.
1. dmis_feed returns an error code.
2. fab_dmis_hole returns an error code.
3. fab_dmis_rectangular_pocket returns an error code.
4. The feature is a hole that is not a round hole:
FTE_HOLE_TO_INSPECT_IS_NOT_A_ROUND_HOLE
5. BUG FTE_UNKNOWN_OPERATION__FAB_DMIS_NEEDS_TOOL
Side effects: See below
Called by: generate_dmis_needs_tool
DMIS code to inspect one AP 224 feature is generated and printed to a file. The program portion which is generated will include a move for retracting in the z-direction out of the last feature (if not already retracted) and a move to a point above the current one. The code for retracting is here. The code for moving above the feature is in the functions called. This also includes a retract move at the end, if not already retracted.
An AP224 feature, when machined, creates surfaces on the workpiece. These surfaces almost always are those of DMIS features, so an AP 224 feature may be used to define some number of DMIS features. An AP 224 pocket may need nine DMIS features, for example.
But not all surfaces of an AP 224 feature produce surfaces on the workpiece. The feature surfaces may be entirely outside the part, or they may intersect other features. It is unwise to try to probe non-existent points because either the the attempt will lead to an error condition, or bad data will be obtained.
The subordinate functions of this function deal with this in two ways.
First, each candidate DMIS feature is tested to see if any portion of it is present on the part. If not, no DMIS code is generated for that DMIS feature (without any message to the user). If a portion of the feature is on the part, an attempt is made to find the required number of inspection points on the DMIS feature.
Second, a check is made that each candidate inspection point is actually present on the workpiece surface at the time the DMIS feature is inspected. If a candidate point does not exist, another candidate point that would be on the DMIS feature is generated and tried. Candidate points are sprinkled evenly around the portion of the DMIS feature that would be present if the entire AP224 feature surface were present. If ten times the desired number of points for a DMIS feature have been tried without getting the desired number, no code for the DMIS feature is generated and a warning message is printed. If the points are found, DMIS code is written to define and inspect the DMIS feature.
- /
static how fab_dmis_needs_tool( /* ARGUMENTS */
inspection_level_type level, /* inspection level */ Machining_feature * volume, /* pointer to a removal volume */ probe_tool * probe, /* pointer to probe to use */ double feed, /* feed rate for operation */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_needs_tool";
IFF (dmis_feed(feed, dmis_out)); if (_taskpl.current_z < _taskpl.retract_high_dmis) fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(_taskpl.current_x), ZOUT(_taskpl.current_y), ZOUT(_taskpl.retract_high_dmis));
if (volume->isa("hole"))
{
CHK((NOT (volume->isa("Round_hole"))),
FTE_HOLE_TO_INSPECT_IS_NOT_A_ROUND_HOLE);
IFF(fab_dmis_hole(level, ROSE_CAST(Round_hole, volume),
probe, dmis_out));
}
else if (volume->isa("Rectangular_closed_pocket"))
{
IFF(fab_dmis_rectangular_pocket
(level, ROSE_CAST(Rectangular_closed_pocket, volume), probe, dmis_out));
}
else
ERM(FTE_BUG_UNKNOWN_FEATURE__FAB_DMIS_NEEDS_TOOL);
if (_taskpl.current_z < _taskpl.retract_high_dmis)
{
fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(_taskpl.current_x), ZOUT(_taskpl.current_y), ZOUT(_taskpl.retract_high_dmis));
_taskpl.current_z SET_TO _taskpl.retract_high_dmis; } return RET_OK;
}
/***********************************************************************/
/* fab_dmis_no_tool
Returned Value: how
If any of the following errors occur, this records the error shown and returns the error code. Otherwise, it returns RET_OK. 1. generate_initialize_dmis returns an error code. 2. generate_end_dmis returns an error code. 3. The operation is unknown: FTE_BUG_UNKNOWN_OPERATION__FAB_DMIS_NO_TOOL
Side effects: See below
Called by: generate_dmis_no_tool
DMIS code to start or end a DMIS program is generated and printed to a file.
- /
static how fab_dmis_no_tool( /* ARGUMENTS */
inspect_no_tool * op, /* the operation */ node * step, /* the plan step that is the parent of op */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_no_tool";
if (op->isa("start_inspect_ex"))
{
IFF (generate_initialize_dmis(dmis_out));
_taskpl.dmis_started SET_TO ON;
}
else if (op->isa("end_inspect_ex"))
{
IFF (generate_end_dmis(dmis_out));
_taskpl.dmis_started SET_TO OFF;
}
else
ERM(FTE_BUG_UNKNOWN_OPERATION__FAB_DMIS_NO_TOOL);
return RET_OK;
}
/***********************************************************************/
/* fab_dmis_pocket_cylinders
Returned Value: how
If any of the following functions is called and returns an error code, this returns that error code. Otherwise, it returns RET_OK. 1. fab_dmis_corner does not return RET_OK. 2. set_parameter_limits does not return RET_OK.
Side effects: See below
Called by:
fab_dmis_rectangular_pocket
This writes dmis code for inspecting the cylinders in the four corners of a pocket.
It the pocket is too shallow, or if the pocket is too narrow, this does not try to inspect the cylindrical walls and no message is printed.
There are two degenerate cases: (1) the pocket profile is a circle, in which case there is only one cylinder to inspect, (2) the ends of pocket profile are semi-circles, in which case there are two half-cylinders to inspect. In the general case, there are four quarter-cylinders to inspect. If the radius of the probe is bigger than the radius of the pocket corners, however, no inspection is done.
If any of the cylindrical corners (or ends or the entire pocket wall) should be inspectable, but enough points cannot be found, a warning message is printed. The message identifies which corner (or end or entire pocket wall) it is.
- /
static how fab_dmis_pocket_cylinders( /* ARGUMENTS */
ListOfDouble * coords, /* coordinates of pocket top center */ double depth, /* depth of pocket */ double length, /* length of pocket */ double width, /* width of pocket */ Numeric_parameter * rad, /* parameter for corner radius of pocket */ double angle, /* rotation angle of pocket */ double tip_radius, /* radius of probe tip */ double tool_length, /* length of tool to center of probe tip */ inspection_level_type level, /* inspection level given in step */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_pocket_cylinders"; int how_many; /* number of points desired */ double clear; /* clearance of center of tool tip */ double (* points)[3]; /* array to fill with points */ double arm1; /* dist pocket midpt to corner cntr midpt */ double arm2; /* dist corner cntr midpt to corner cntr */ double radius; /* corner radius of pocket */ double hitol; /* upper tolerance of corner diameter */ double lotol; /* lower tolerance of corner diameter */ double top_x; /* x-coordinate of pocket top center */ double top_y; /* y-coordinate of pocket top center */ double top_z; /* z-coordinate of pocket top center */ double height; /* height of area to inspect */
radius SET_TO rad->parameter_value();
clear SET_TO (tip_radius + _taskpl.inspect_clear);
top_x SET_TO (*coords)[0];
top_y SET_TO (*coords)[1];
top_z SET_TO (*coords)[2];
IFF (set_parameter_limits(rad, &hitol, &lotol));
hitol SET_TO (hitol * 2); /* diameter tolerance is twice radius tolerance */
lotol SET_TO (lotol * 2);
how_many SET_TO
((level IS inspection_level_type_high) ?
_taskpl.inspect_points_cylinder_high:
(level IS inspection_level_type_low) ?
_taskpl.inspect_points_cylinder_low :
_taskpl.inspect_points_cylinder_medium);
points SET_TO new double[how_many][3]; /* might check if null */
height SET_TO MIN((depth - clear), tool_length);
if (clear > radius); /* cylinder(s) too small diameter to inspect */
else if ((depth - clear) < tip_radius) /* cyl(s) too shallow to inspect */
fprintf(stderr, "Warning: pocket too shallow to inspect corners\n");
else if ((fabs(width - (2 * radius)) < 0.000001) AND
(fabs(length - (2 * radius)) < 0.000001)) /* full circle profile */
{
IFF (fab_dmis_corner
(top_x, top_y, top_z, radius, height, angle, (2 * M_PI), how_many, points, clear, hitol, lotol, "wall", dmis_out));
}
else if (fabs(width - (2 * radius)) < 0.000001)
{ /* profile has semicircles at ends */
arm1 SET_TO ((length / 2) - radius);
IFF (fab_dmis_corner
((top_x + (arm1 * cos(angle))), (top_y + (arm1 * sin(angle))), top_z, radius, height, (angle - M_PI_2), M_PI, how_many, points, clear, hitol, lotol, "right end", dmis_out));
IFF (fab_dmis_corner
((top_x - (arm1 * cos(angle))), (top_y - (arm1 * sin(angle))), top_z, radius, height, (angle + M_PI_2), M_PI, how_many, points, clear, hitol, lotol, "left end", dmis_out));
}
else
{
arm1 SET_TO ((length / 2) - radius);
arm2 SET_TO ((width / 2) - radius);
IFF (fab_dmis_corner
((top_x + (arm1 * cos(angle)) + (arm2 * cos(angle - M_PI_2))), (top_y + (arm1 * sin(angle)) + (arm2 * sin(angle - M_PI_2))), top_z, radius, height, (angle - M_PI_2), M_PI_2, how_many, points, clear, hitol, lotol, "lower right corner", dmis_out));
IFF (fab_dmis_corner
((top_x + (arm1 * cos(angle)) + (arm2 * cos(angle + M_PI_2))), (top_y + (arm1 * sin(angle)) + (arm2 * sin(angle + M_PI_2))), top_z, radius, height, angle, M_PI_2, how_many, points, clear, hitol, lotol, "upper right corner",dmis_out));
IFF (fab_dmis_corner
((top_x - (arm1 * cos(angle)) + (arm2 * cos(angle + M_PI_2))), (top_y - (arm1 * sin(angle)) + (arm2 * sin(angle + M_PI_2))), top_z, radius, height, (angle + M_PI_2), M_PI_2, how_many, points, clear, hitol, lotol, "upper left corner", dmis_out));
IFF (fab_dmis_corner
((top_x - (arm1 * cos(angle)) + (arm2 * cos(angle - M_PI_2))), (top_y - (arm1 * sin(angle)) + (arm2 * sin(angle - M_PI_2))), top_z, radius, height, (angle - M_PI), M_PI_2, how_many, points, clear, hitol, lotol, "lower left corner", dmis_out));
} delete [] points; /* since made by "new" above */ return RET_OK;
}
/***********************************************************************/
/* fab_dmis_pocket_planes
Returned Value: how
If any of the following functions is called and returns an error code, this returns that error code. Otherwise, it returns RET_OK. 1. find_horizontal_plane_points does not return RET_OK. 2. fab_dmis_print_plane does not return RET_OK. 3. fab_dmis_side_plane does not return RET_OK. 4. pm_bottom_on_part does not return RET_OK.
Side effects: See below
Called by: fab_dmis_rectangular_pocket
This always inspects the plane at the bottom of the pocket first.
The plane at the +X side of the pocket is inspected next if the inspectable width of the side is at least half a tip radius wide.
The planes at the +Y, -X, and -Y sides of the pocket are inspected similarly to the +X side.
If any of the five planes should be inspectable, but enough points cannot be found, a warning message is printed. The message identifies which plane it is.
The size of the sides to be inspected is checked in fab_dmis_side_plane, so that check is not needed here.
- /
static how fab_dmis_pocket_planes( /* ARGUMENTS */
ListOfDouble * coords, /* center_point of pocket profile at top */ double depth, /* depth of pocket */ double length, /* length of profile */ double width, /* width of profile */ double radius, /* corner radius of profile */ double angle, /* angle of rotation of profile */ double tip_radius, /* radius of probe tip */ double tool_length, /* length of tool to center of probe tip */ inspection_level_type level, /* inspection level given in step */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_pocket_planes"; int how_many; double clear; int found; double (* points)[3]; double center_z; double height; /* height of side rectangles */
clear SET_TO (tip_radius + _taskpl.inspect_clear);
how_many SET_TO
((level IS inspection_level_type_high) ? _taskpl.inspect_points_plane_high:
(level IS inspection_level_type_low) ? _taskpl.inspect_points_plane_low :
_taskpl.inspect_points_plane_medium);
points SET_TO new double[how_many][3]; /* might check if null */
/* Inspect plane at bottom of pocket */
if (((width - (2 * clear)) <= 0) OR ((length - (2 * clear)) <= 0))
found SET_TO 0;
else
{
IFF (pm_bottom_on_part((length - (2 * clear)), (width - (2 * clear)),
(*coords)[0], (*coords)[1], ((*coords)[2] - depth), angle, &found));
}
if ((found ISNT 0) AND ((tool_length + tip_radius) < depth)) /* tool short */
fprintf(stderr, "Warning: tool too short to inspect pocket bottom\n");
else if (found ISNT 0)
{
IFF (find_horizontal_plane_points
((length - (2 * clear)), (width - (2 * clear)), (radius - clear), (*coords)[0], (*coords)[1], ((*coords)[2] - depth), angle, how_many, points, &found));
if (found < how_many)
fprintf(stderr, "Warning: cannot inspect bottom plane of pocket\n");
else
IFF(fab_dmis_print_plane(0, points[0][0], points[0][1], points[0][2], 0, 0, 1, how_many, points, clear, NULL, dmis_out));
}
else; /* plane not on part - do nothing */
if ((depth - clear) < tip_radius)
fprintf(stderr, "Warning: pocket too shallow to inspect sides\n");
else
{
if (radius < tip_radius) /* reset radius if probe does not fit corners */
radius SET_TO tip_radius;
height SET_TO MIN((depth - clear), tool_length);
center_z SET_TO ((*coords)[2] - (height/2));
/* Inspect plane at +X (when unrotated) end of pocket */
IFF (fab_dmis_side_plane(height, (width - (2 * radius)), (tip_radius/2),
(*coords)[0], (*coords)[1], center_z, length/2, angle, clear, "+X", points, how_many,dmis_out));
/* Inspect plane at +Y (when unrotated) end of pocket */
angle SET_TO (angle + M_PI_2);
IFF (fab_dmis_side_plane(height, (length - (2 * radius)), (tip_radius/2),
(*coords)[0], (*coords)[1], center_z, width/2, angle, clear, "+Y", points, how_many,dmis_out));
/* Inspect plane at -X (when unrotated) end of pocket */
angle SET_TO (angle + M_PI_2);
IFF (fab_dmis_side_plane(height, (width - (2 * radius)), (tip_radius/2),
(*coords)[0], (*coords)[1], center_z, length/2, angle, clear, "-X", points, how_many,dmis_out));
/* Inspect plane at -Y (when unrotated) end of pocket */
angle SET_TO (angle + M_PI_2);
IFF (fab_dmis_side_plane(height, (length - (2 * radius)), (tip_radius/2),
(*coords)[0], (*coords)[1], center_z, width/2, angle, clear, "-Y", points, how_many,dmis_out));
} delete [] points; return RET_OK;
}
/***********************************************************************/
/* fab_dmis_print_cylinder
Returned Value: how (RET_OK)
Side effects: See below.
Called by:
fab_dmis_hole fab_dmis_corner
This takes the parameters for a cylinder and a set of points on the cylinder and prints DMIS code to 1. define the cylinder 2. measure the cylinder 3. output the nominal and measured cylinders.
This handles empty cylinders, not solid cylinders. The probe is kept inside the cylinder.
This assumes that the probe can be moved safely from wherever it is before this function starts to a point just off the first point to be measured. This will be the case if the cylinder has its axis parallel to the z_axis, and the probe is anywhere inside the cylinder before this function starts. It will also be the case if the cylinder is in a corner of a pocket and the probe is anywhere inside the pocket.
The value of retract distance should be less than the radius of the cylinder minus the probe tip radius.
This assumes the axis vector is a unit vector.
This is not verifying that the points are on the cylinder, but contains sufficient information to do so.
This resets the value of the current location at the end of inspecting the hole. The probe is left at the approach point for the last inspection point.
If the lower diameter tolerance is less than or equal to the upper diameter tolerance, this writes a tolerance and applies it to the output of the actual feature. Otherwise no tolerance items are generated.
- /
static how fab_dmis_print_cylinder( /* ARGUMENTS */
double point_x, /* x coordinate of bottom center */ double point_y, /* y coordinate of bottom center */ double point_z, /* z coordinate of bottom center */ double axis_x, /* x component of axis */ double axis_y, /* y component of axis */ double axis_z, /* z component of axis */ double diameter, /* diameter of cylinder */ double length, /* length of cylinder */ int how_many, /* number of points on cylinder */ double (* points)[3], /* points on cylinder to measure */ double retract, /* retract distance */ double uptol, /* upper diameter tolerance */ double lotol, /* lower diameter tolerance */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_print_cylinder"; char label[20]; /* name for cylinder DMIS feature */ char label2[20]; /* name for tolerance */ double dot; /* dot product of axis vector and P = |P| * cos(angle) */ double rad_x; /* x comp't of normalized radius vector from pt on side */ double rad_y; /* y comp't of normalized radius vector from pt on side */ double rad_z; /* z comp't of normalized radius vector from pt on side */ double px; /* x component of vector P from bottom to point on side */ double py; /* y component of vector P from bottom to point on side */ double pz; /* z component of vector P from bottom to point on side */ int n;
sprintf(label, "CYLNDR%d", _taskpl.dmis_feat++); fprintf(dmis_out, "F(%s) = FEAT/CYLNDR, INNER, CART, %.*lf, %.*lf, $\n",
label, ZOUT(point_x), ZOUT(point_y));
fprintf(dmis_out, " %.*lf, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf\n",
ZOUT(point_z), ZOUT(axis_x), ZOUT(axis_y), ZOUT(axis_z), ZOUT(diameter), ZOUT(length));
fprintf(dmis_out, "MEAS/CYLNDR, F(%s), %d\n", label, how_many);
for (n SET_TO 0; n < how_many; n++)
{
/* radius from side of cylinder is (dot times axis_vector) minus P */
px SET_TO (points[n][0] - point_x);
py SET_TO (points[n][1] - point_y);
pz SET_TO (points[n][2] - point_z);
dot SET_TO ((px * axis_x) + (py * axis_y) + (pz * axis_z));
rad_x SET_TO ((axis_x * dot) - px);
rad_y SET_TO ((axis_y * dot) - py);
rad_z SET_TO ((axis_z * dot) - pz);
/* normalize radius */
rad_x SET_TO ((rad_x * 2) / diameter);
rad_y SET_TO ((rad_y * 2) / diameter);
rad_z SET_TO ((rad_z * 2) / diameter);
fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[n][0] + (retract * rad_x)), ZOUT(points[n][1] + (retract * rad_y)), ZOUT(points[n][2] + (retract * rad_z)));
fprintf(dmis_out,
"PTMEAS/CART, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf\n", ZOUT(points[n][0]), ZOUT(points[n][1]), ZOUT(points[n][2]), ZOUT(rad_x), ZOUT(rad_y), ZOUT(rad_z));
} n--; fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[n][0] + (retract * rad_x)), ZOUT(points[n][1] + (retract * rad_y)), ZOUT(points[n][2] + (retract * rad_z)));
fprintf(dmis_out, "ENDMES\n");
if (uptol >= lotol)
{
sprintf(label2, "TOL_DIAM%d", _taskpl.dmis_feat++);
fprintf(dmis_out, "T(%s) = TOL/DIAM, %.*lf, %.*lf\n",
label2, ZOUT(lotol), ZOUT(uptol));
} fprintf(dmis_out, "OUTPUT/F(%s)\n", label); fprintf(dmis_out, "OUTPUT/FA(%s)", label); if (uptol >= lotol) fprintf(dmis_out, ", TA(%s)", label2); fprintf(dmis_out, "\n"); _taskpl.current_x SET_TO (points[n][0] + (retract * rad_x)); _taskpl.current_y SET_TO (points[n][1] + (retract * rad_y)); _taskpl.current_z SET_TO (points[n][2] + (retract * rad_z)); return RET_OK;
}
/***********************************************************************/
/* fab_dmis_print_plane
Returned Value: how (RET_OK)
Side effects: See below.
Called by:
fab_dmis_pocket_planes fab_dmis_side_plane
This takes the parameters for a plane and a set of points on the plane and prints DMIS code to: 1. define the plane 2. measure the plane 3. output the nominal and measured planes.
This assumes that the probe can be moved safely from wherever it is before this function starts to a point just off the first point to be measured. This will be the case if the plane is a plane (side or bottom) of a pocket whose axis is parallel to the z_axis, and the probe is anywhere inside the pocket before this function starts.
The value of retract distance should be small enough to keep the probe away from other surfaces. In particular, for the walls of a pocket, retract should not be more than half the pocket width minus the tip radius.
This is not verifying that the points are on the plane, but contains sufficient information to do so.
The normal to the plane is assumed to be a unit vector. The normal must point into free space.
The current position of the probe tip recorded in the _taskpl model is reset by this function.
- /
static how fab_dmis_print_plane( /* ARGUMENTS */
int pull_out, /* non-zero = move above before & pull out after */ double point_x, /* x coordinate of point on plane */ double point_y, /* y coordinate of point on plane */ double point_z, /* z coordinate of point on plane */ double normal_x, /* x component of normal to plane */ double normal_y, /* y component of normal to plane */ double normal_z, /* z component of normal to plane */ int how_many, /* number of points on plane */ double (* points)[3], /* points on plane to measure */ double retract, /* retract distance */ char * plane_name, /* name of plane or NULL */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_print_plane"; char label[11]; double retract_x; double retract_y; double retract_z; int n;
retract_x SET_TO (retract * normal_x);
retract_y SET_TO (retract * normal_y);
retract_z SET_TO (retract * normal_z);
if (plane_name ISNT NULL)
{
strncpy(label, plane_name, 10);
label[10] SET_TO 0;
}
else
sprintf(label, "PLANE%d", _taskpl.dmis_feat++);
fprintf(dmis_out, "F(%s) = FEAT/PLANE, CART, ", label);
fprintf(dmis_out, "%.*lf, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf\n",
ZOUT(point_x), ZOUT(point_y), ZOUT(point_z), ZOUT(normal_x), ZOUT(normal_y), ZOUT(normal_z));
fprintf(dmis_out, "MEAS/PLANE, F(%s), %d\n", label, how_many); if (pull_out) fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[0][0] + retract_x), ZOUT(points[0][1] + retract_y), ZOUT(_taskpl.retract_high_dmis));
for (n SET_TO 0; n < how_many; n++)
{
fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[n][0] + retract_x), ZOUT(points[n][1] + retract_y), ZOUT(points[n][2] + retract_z));
fprintf(dmis_out,
"PTMEAS/CART, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf, %.*lf\n", ZOUT(points[n][0]), ZOUT(points[n][1]), ZOUT(points[n][2]), ZOUT(normal_x), ZOUT(normal_y), ZOUT(normal_z));
} n--; fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[n][0] + retract_x), ZOUT(points[n][1] + retract_y), ZOUT(points[n][2] + retract_z));
fprintf(dmis_out, "ENDMES\n");
fprintf(dmis_out, "OUTPUT/F(%s)\n", label);
fprintf(dmis_out, "OUTPUT/FA(%s)\n", label);
_taskpl.current_x SET_TO (points[n][0] + retract_x);
_taskpl.current_y SET_TO (points[n][1] + retract_y);
_taskpl.current_z SET_TO (points[n][2] + retract_z);
if (pull_out)
{
fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT(points[n][0] + retract_x), ZOUT(points[n][1] + retract_y), ZOUT(_taskpl.retract_high_dmis));
_taskpl.current_z SET_TO (_taskpl.retract_high_dmis); } return RET_OK;
}
/***********************************************************************/
/* fab_dmis_rectangular_pocket
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. find_pocket_depth does not return RET_OK. 2. fab_dmis_pocket_planes does not return RET_OK. 3. fab_dmis_pocket_cylinders does not return RET_OK.
Side effects: See below.
Called by: fab_dmis_needs_tool
This is inspecting an AP224 Rectangular pocket by calling fab_dmis_pocket_planes to inspect the planar walls and bottom of the pocket and calling fab_dmis_pocket_cylinders to inspect the cylindrical walls of the pocket.
We are assuming here that the edges of the bottom are not filleted with the sides. A check of this might be added.
See documentation of fab_dmis_needs tool for more details.
This function expects the tool to be above the part when it takes over, as is done by fab_dmis_needs_tool.
- /
static how fab_dmis_rectangular_pocket( /* ARGUMENTS */
inspection_level_type level, /* inspection level */ Rectangular_closed_pocket * a_pocket, /* pointer to pocket to inspect */ probe_tool * probe, /* pointer to probe to use */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_rectangular_pocket"; ListOfDouble * coords; /* coordinates of pocket top center */ double depth; /* depth of pocket */ double width; /* width of pocket */ double length; /* length of pocket */ Numeric_parameter * radius; /* corner radius of pocket */ double angle; /* rotation angle of pocket */ double tip_radius; /* radius of probe tip */ double tool_length; /* length of probe to tip center */
IFF (find_pocket_depth(a_pocket->bottom_condition(), &depth)); coords SET_TO a_pocket->placement()->location()->coordinates(); length SET_TO a_pocket->closed_boundary()->profile_length()->parameter_value(); width SET_TO a_pocket->closed_boundary()->profile_width()->parameter_value(); radius SET_TO a_pocket->closed_boundary()->corner_radius(); angle SET_TO find_pocket_rotation (length, width, a_pocket->placement()->x_axis()->components()); tip_radius SET_TO (probe->diameter() / 2.0); IFF(find_probe_length(probe, &tool_length)); fprintf(dmis_out, "$$inspecting pocket\n"); fprintf(dmis_out, "GOTO/%.*lf, %.*lf, %.*lf\n",
ZOUT((*coords)[0]), ZOUT((*coords)[1]), ZOUT(_taskpl.retract_high_dmis));
IFF (fab_dmis_pocket_planes(coords, depth, length, width,
radius->parameter_value(), angle, tip_radius, tool_length, level, dmis_out));
IFF (fab_dmis_pocket_cylinders(coords, depth, length, width, radius, angle,
tip_radius, tool_length, level, dmis_out));
return RET_OK;
}
/***********************************************************************/
/* fab_dmis_side_plane
Returned Value: how
If any of the following errors occur, this returns the error code shown. Otherwise, it returns RET_OK. 1. pm_side_on_part returns an error code. 2. find_vertical_plane_points returns an error code. 3. fab_dmis_print_plane returns an error code.
Side Effects: See below
called by: fab_dmis_pocket_planes
This generates DMIS code for a plane which is a vertical (parallel to z-axis) side of a pocket. It checks to be sure at least some of the side is actually present on the part; if not, it does not try to generate code. If at least some of the side is present on the part, it tries to find the required number of points on the side. If the required number is found, it prints DMIS code for inspecting the side using the points. If the required number is not found, it warns the user and prints no code.
- /
static how fab_dmis_side_plane( /* ARGUMENTS */
double height, /* height of rectangle */ double length, /* length of rectangle */ double min_length, /* minimum length for finding points */ double center_x, /* x value of center of rotation of rectangle */ double center_y, /* y value of center of rotation of rectangle */ double center_z, /* z value of center of rotation of rectangle */ double offset, /* distance from center to rectangle */ double angle, /* angle of rotation of rectangle from X-axis */ double clear, /* clearance for center of probe tip */ char * side_name, /* name of side of pocket - +X, -Y, etc */ double points[][3], /* point array to be filled */ int how_many, /* number of points desired to be found */ FILE * dmis_out) /* port to print to */
{
const char name[] SET_TO "fab_dmis_side_plane"; int found; /* plane on part flag & number points found */
if (length >= min_length)
{
IFF (pm_side_on_part(length, height, offset, center_x, center_y,
center_z, angle, &found));
if (found ISNT 0)
{ /* the "0, 0" in this call means use point_on_part */ IFF(find_vertical_plane_points (length, height, offset, center_x, center_y, center_z, angle, how_many, points, 0, 0, &found)); if (found < how_many) /* if not enough points, warn user */ fprintf(stderr, "Warning: cannot inspect plane on %s side of pocket\n", side_name); else IFF (fab_dmis_print_plane (0, points[0][0], points[0][1], points[0][2], -cos(angle), -sin(angle), 0, how_many, points, clear, NULL, dmis_out)); }
else; /* if plane not on part - do nothing */ } else; /* if too small to inspect - do nothing */ return RET_OK;
}
/***********************************************************************/
/* fab_face_mill
Returned Value: how (RET_OK.)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_face_mill( /* ARGUMENTS */
nc_needs_tool * op, /* the face_mill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_face_mill"; return RET_OK;
}
/***********************************************************************/
/* fab_finish_mill
Returned Value: how
If any of the following errors occur, this returns the error code shown.
Otherwise, it returns RET_OK.
1. The volume is not a Rectangular_pocket:
FTE_CANNOT_FINISH_MILL_OTHER_THAN_A_RECTANGULAR_POCKET
2. nc_finish_mill_rectangular_pocket does not return RET_OK.
3. set_adjustment does not return RET_OK.
Side effects:
pseudocode is saved to finish mill a rectangular pocket.
Called by:
fab_nc_needs_tool
This calls various subordinates depending upon the type of removal volume.
- /
static how fab_finish_mill( /* ARGUMENTS */
nc_needs_tool * op, /* the finish_mill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_finish_mill"; Rectangular_closed_pocket * pocket;
if (_taskpl.read_dmis ISNT 0)
{
IFF (set_adjustment());
}
if (volume->isa("Rectangular_closed_pocket"))
{
pocket SET_TO ROSE_CAST(Rectangular_closed_pocket, volume);
IFF (nc_finish_mill_pocket_rectangular(pocket, tool, stepover,
speed, general_feed, flood, (general_feed/2)));
} else /* eventually should be able to finish mill other things */ ERM(FTE_CANNOT_FINISH_MILL_OTHER_THAN_A_RECTANGULAR_POCKET);
_taskpl.pocket_adjustment SET_TO 0.0; return RET_OK;
}
/***********************************************************************/
/* fab_fly_cut
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_fly_cut( /* ARGUMENTS */
nc_needs_tool * op, /* the fly_cut_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_fly_cut"; return RET_OK;
}
/***********************************************************************/
/* fab_nc_needs_tool
Returned Value: how
If any of the following errors occur, this records the error shown and returns the error code. Otherwise, it returns RET_OK. 1. one of the "fab_nc" functions called returns an error code. 2. BUG FTE_UNKNOWN_OPERATION__FAB_NC_NEEDS_TOOL
Side effects:
Pseudocode to perform one machining operation is generated and printed to a file.
Called by: generate_nc_needs_tool
This function retracts the tool.
Setting spindle speed and feed rate are not included here, since not all subordinate functions treat them the same. Speed and feed arguments are passed to all subordinates.
- /
static how fab_nc_needs_tool( /* ARGUMENTS */
nc_needs_tool * op, /* the operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double stepover, /* horizontal stepover */ double pass_depth, /* vertical depth increment bound */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_nc_needs_tool"; fab_pointer function;
if (op->isa("bore_ex"))
function SET_TO fab_bore;
else if (op->isa("center_drill_ex"))
function SET_TO fab_center_drill;
else if (op->isa("counterboring_ex"))
function SET_TO fab_counterbore;
else if (op->isa("countersinking_ex"))
function SET_TO fab_countersink;
else if (op->isa("face_mill_ex"))
function SET_TO fab_face_mill;
else if (op->isa("finish_mill_ex"))
function SET_TO fab_finish_mill;
else if (op->isa("fly_cut_ex"))
function SET_TO fab_fly_cut;
else if (op->isa("machine_chamfer_ex"))
function SET_TO fab_chamfer;
else if (op->isa("machine_round_ex"))
function SET_TO fab_round;
else if (op->isa("peripheral_mill_ex"))
function SET_TO fab_peripheral_mill;
else if (op->isa("ream_ex"))
function SET_TO fab_ream;
else if (op->isa("rough_mill_ex"))
function SET_TO fab_rough_mill;
else if (op->isa("slot_mill_ex"))
function SET_TO fab_slot;
else if (op->isa("tapping_ex"))
function SET_TO fab_tap;
else if (op->isa("twist_drilling_ex"))
function SET_TO fab_twist_drill;
else
ERM(FTE_BUG_UNKNOWN_OPERATION__FAB_NC_NEEDS_TOOL);
IFF (function(op, volume, tool, pass_depth, stepover, speed, general_feed,
flood, machining_method));
nc_retract(); return RET_OK;
}
/***********************************************************************/
/* fab_nc_no_tool
Returned Value: how
If any of the following errors occur, this records the error shown
and returns the error code. Otherwise, it returns RET_OK.
1. one of the following functions is called and returns an error code:
nc_flood, generate_end_nc, find_tool_instance, nc_change_tool,
generate_initialize_nc
2. An unknown operation is used: FTE_BUG_UNKNOWN_OPERATION__FAB_NC_NO_TOOL
Side effects:
Pseudocode to perform one machining operation is generated and printed to a file.
Called by:
generate_nc_no_tool
This generates NC-code for non-cutting operations: starting a program, ending a program, changing a tool, turning coolant on or off.
It would be nice to change the name of this function to fab_nc_no_cut, since the name "no_tool" is misleading (changing tools is one of the things this does), but if the name were changed, the EXPRESS names should be changed to match, which is a big pain.
- /
static how fab_nc_no_tool( /* ARGUMENTS */
nc_no_tool * op, /* the operation */ node * step) /* the plan step that is the parent of op */
{
const char name[] SET_TO "fab_nc_no_tool"; tool_instance * the_tool; ON_OFF flood;
if (op->isa("coolant_ex")) /* this is not dealing with mist coolant */
{
flood SET_TO
((ROSE_CAST(coolant_ex, op))->flood_coolant() IS ROSE_TRUE) ? ON : OFF;
IFF (nc_flood(flood));
}
else if (op->isa("end_nc_ex"))
{
IFF (generate_end_nc());
_taskpl.nc_started SET_TO OFF;
}
else if (op->isa("nc_change_ex"))
{
IFF (find_tool_instance(_taskpl.tools,
(ROSE_CAST(nc_change_ex, op))->inventory_tool(), &the_tool));
IFF (nc_change_tool(the_tool));
}
else if (op->isa("start_nc_ex"))
{
IFF (generate_initialize_nc());
_taskpl.nc_started SET_TO ON;
}
else
ERM(FTE_BUG_UNKNOWN_OPERATION__FAB_NC_NO_TOOL);
return RET_OK;
}
/***********************************************************************/
/* fab_peripheral_mill
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_peripheral_mill( /* ARGUMENTS */
nc_needs_tool * op, /* the peripheral_mill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_peripheral_mill"; return RET_OK;
}
/***********************************************************************/
/* fab_ream
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_ream( /* ARGUMENTS */
nc_needs_tool * op, /* the ream_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_ream"; return RET_OK;
}
/***********************************************************************/
/* fab_rough_mill
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_rough_mill( /* ARGUMENTS */
nc_needs_tool * op, /* the rough_mill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_rough_mill"; return RET_OK;
}
/***********************************************************************/
/* fab_round
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_round( /* ARGUMENTS */
nc_needs_tool * op, /* the machine_round_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_round"; return RET_OK;
}
/***********************************************************************/
/* fab_slot
Returned Value: how (RET_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_slot( /* ARGUMENTS */
nc_needs_tool * op, /* the slot_mill_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_slot"; return RET_OK;
}
/***********************************************************************/
/* fab_tap
Returned Value: how (RE_OK)
Side effects:
None
Called by:
fab_nc_needs_tool
THIS IS A STUB.
- /
static how fab_tap( /* ARGUMENTS */
nc_needs_tool * op, /* the tapping_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_tap"; return RET_OK;
}
/***********************************************************************/
/* fab_twist_drill
Returned Value: how (RET_OK)
Side effects:
Pseudocode is generated for twist drilling a hole. The current location is reset.
Called by:
fab_nc_needs_tool
The procedure is:
1. Traverse parallel to the Z-axis to retract_high.
2. If necessary, change spindle speed, and/or start spindle clockwise.
3. If necessary, change feed rate to general_feed.
4. Either a shallow-hole drill cycle or a deep-hole drill cycle is called, depending on whether the ratio of the depth of the hole to the diameter is less than the deep_hole_factor (a machining option). The actual cycle called for a deep-hole drill cycle is also a machining option; currently the only choices are CANON_DRILL_PECK and CANON_DRILL_PLUNGE. The cycle for a shallow hole is CANON_DRILL_PLUNGE. The motions produced will depend on the NC language into which the pseudocode is printed. For RS274/NGC, print_nc currently uses G83 (G73 would be better but it is not implemented yet) for CANON_DRILL_PECK and G81 for CANON_DRILL_PLUNGE.
When this finishes, the tool tip is at the XY location of the hole, one retract_distance_low (a machining option) above the top of the hole. That is where both G81 and G83 leave it.
- /
static how fab_twist_drill( /* ARGUMENTS */
nc_needs_tool * op, /* the twist_drilling_ex operation */ Machining_feature * volume, /* pointer to a removal volume */ tool_instance * tool, /* pointer to tool to use */ double pass_depth, /* vertical depth increment bound */ double stepover, /* horizontal stepover */ double speed, /* spindle speed */ double general_feed, /* feed rate for basic operation */ ON_OFF flood, /* flood coolant is on or off */ FEAT_MACH_STRATEGY machining_method) /* primary method to use */
{
const char name[] SET_TO "fab_twist_drill";
Round_hole * the_hole;
double ex; /* x coordinate of hole */
double wy; /* y coordinate of hole */
double top_z; /* z coordinate of top of hole */
double depth; /* depth of hole */
double diameter; /* diameter of hole */
ListOfDouble * coords;
the_hole SET_TO ROSE_CAST (Round_hole, volume);
depth SET_TO the_hole->hole_depth()->parameter_value();
coords SET_TO the_hole->placement()->location()->coordinates();
ex SET_TO (*coords)[0];
wy SET_TO (*coords)[1];
top_z SET_TO (*coords)[2];
diameter SET_TO the_hole->diameter()->diameter()->parameter_value();
nc_retract();
nc_flood(flood);
nc_spindle_speed(speed);
nc_spindle_turning(CANON_CLOCKWISE);
nc_feed(general_feed);
if ((depth / diameter) > _taskpl.deep_hole_factor)
{
if (_taskpl.deep_drill_cycle IS
drill_cycle_type_plunge_drilling) write_line5(CANON_DRILL_PLUNGE, ex, wy, (top_z - depth), (top_z + _taskpl.retract_distance_low));
else
write_line6(CANON_DRILL_PECK, ex, wy, (top_z - depth), (top_z + _taskpl.retract_distance_low), pass_depth);
} else write_line5(CANON_DRILL_PLUNGE, ex, wy, (top_z - depth),
(top_z + _taskpl.retract_distance_low));
_taskpl.current_x SET_TO ex; _taskpl.current_y SET_TO wy; _taskpl.current_z SET_TO (top_z + _taskpl.retract_distance_low); return RET_OK;
}
/***********************************************************************/
/* find_horizontal_plane_points
Returned Value: how
If any of the following errors occur, this returns an error code. Otherwise, it returns RET_OK. 1. pm_point_on_part does not return RET_OK.
Side effects: See below.
Called by:
fab_dmis_pocket_planes
This generates points on a horizontal plane. The part of the plane that might exist is contained in the profile which is a rectangle with rounded corners (note that a circle is such a thing) of the given length and width, centered at the point given by center_x, center_y, and center_z, rotated by angle (from the position in which the length is parallel to the x_axis), with the normal to the plane parallel to the Z-axis. Because this is dealing with an AP224 pocket, the length is always greater than or equal to the width
The function calls find_inspection_point to generate an inspection point inside an unrotated rectangle with unrounded corners. Then it calls point_in_pocket to check that the candidate point is still in the unrotated rectangle if the corners are rounded. Then it rotates the point, which will then definitely be in the profile.
The function calls pm_point_on_part to check that each candidate point exists on the part (the part_now, which changes after each machining operation). There is a maximum on the number of candidate points this will try of 10 times the required number of points. If the maximum is reached, this returns RET_OK. The calling function can tell there is a problem by comparing the value of how_many with the value of *found when this returns.
This function assumes it is OK to start with a rapid move to a point with Z retracted directly above the center of the pocket.
- /
static how find_horizontal_plane_points( /* ARGUMENTS */
double length, /* length of profile */ double width, /* width of profile */ double radius, /* corner radius of profile */ double center_x, /* x coordinate of profile center */ double center_y, /* y coordinate of profile center */ double center_z, /* z coordinate of profile center */ double angle, /* angle of rotation of profile */ int how_many, /* number of points to measure */ double (* points)[3], /* point array to be filled */ int * found) /* number of points found here */
{
const char name[] SET_TO "find_horizontal_plane_points"; char label[11]; int n; int answer; double point[2];
*found SET_TO 0;
for (n SET_TO 0; *found < how_many; n++)
{
if (n > (how_many * 10))
break;
find_inspection_point(center_x, center_y, length, width, n, point);
if (NOT (point_in_pocket(point, center_x, center_y,
length, width, radius))) continue;
if (angle ISNT 0.0)
rotate_xy_location(angle, point+0, point+1, center_x, center_y);
IFF (pm_point_on_part (point[0], point[1], center_z, &answer));
if (answer ISNT 1)
continue;
points[*found][0] SET_TO point[0];
points[*found][1] SET_TO point[1];
points[*found][2] SET_TO center_z;
(*found)++;
}
return RET_OK;
}
/***********************