예제 #1
0
파일: arc.c 프로젝트: aldenhart/TinyG
uint8_t _compute_center_arc()
{
	// calculate the theta (angle) of the current point (see header notes)
	double theta_start = _get_theta(-gm.arc_offset[gm.plane_axis_0], -gm.arc_offset[gm.plane_axis_1]);
	if(isnan(theta_start) == true) { return(TG_ARC_SPECIFICATION_ERROR);}

	// calculate the theta (angle) of the target point
	double theta_end = _get_theta(
		gm.target[gm.plane_axis_0] - gm.arc_offset[gm.plane_axis_0] - gm.position[gm.plane_axis_0], 
 		gm.target[gm.plane_axis_1] - gm.arc_offset[gm.plane_axis_1] - gm.position[gm.plane_axis_1]);
	if(isnan(theta_end) == true) { return (TG_ARC_SPECIFICATION_ERROR); }

	// ensure that the difference is positive so we have clockwise travel
	if (theta_end < theta_start) { theta_end += 2*M_PI; }

	// compute angular travel and invert if gcode wants a counterclockwise arc
	// if angular travel is zero interpret it as a full circle
	double angular_travel = theta_end - theta_start;
	if (angular_travel == 0) {
		if (gm.motion_mode == MOTION_MODE_CCW_ARC) { 
			angular_travel -= 2*M_PI;
		} else {
			angular_travel = 2*M_PI;
		}
	} else {
		if (gm.motion_mode == MOTION_MODE_CCW_ARC) { 
			angular_travel -= 2*M_PI;
		}
	}

	// Find the radius, calculate travel in the depth axis of the helix,
	// and compute the time it should take to perform the move
	double radius_tmp = hypot(gm.arc_offset[gm.plane_axis_0], gm.arc_offset[gm.plane_axis_1]);
	double linear_travel = gm.target[gm.plane_axis_2] - gm.position[gm.plane_axis_2];
	double move_time = _get_arc_time(linear_travel, angular_travel, radius_tmp);

	// Trace the arc
	set_vector(gm.target[gm.plane_axis_0], gm.target[gm.plane_axis_1], gm.target[gm.plane_axis_2],
			   gm.target[A], gm.target[B], gm.target[C]);

	return(ar_arc(vector,
				  gm.arc_offset[gm.plane_axis_0],
				  gm.arc_offset[gm.plane_axis_1],
				  gm.arc_offset[gm.plane_axis_2],
				  theta_start, radius_tmp, angular_travel, linear_travel, 
				  gm.plane_axis_0, gm.plane_axis_1, gm.plane_axis_2, move_time));
}
예제 #2
0
파일: plan_arc.cpp 프로젝트: kitling/g2
/*
 * _compute_arc() - compute arc from I and J (arc center point)
 *
 *	The theta calculation sets up an clockwise or counterclockwise arc from the current
 *	position to the target position around the center designated by the offset vector.
 *	All theta-values measured in radians of deviance from the positive y-axis.
 *
 *                      | <- theta == 0
 *                    * * *
 *                  *       *
 *                *           *
 *                *     O ----T   <- theta_end (e.g. 90 degrees: theta_end == PI/2)
 *                *   /
 *                  C   <- theta_start (e.g. -145 degrees: theta_start == -PI*(3/4))
 *
 *  Parts of this routine were originally sourced from the grbl project.
 */
static stat_t _compute_arc()
{
	// A non-zero radius value indicates a radius arc
	// Compute IJK offset coordinates. These override any current IJK offsets
	if (fp_NOT_ZERO(arc.radius)) ritorno(_compute_arc_offsets_from_radius()); // returns if error

	// Calculate the theta (angle) of the current point (see header notes)
	// Arc.theta is starting point for theta (theta_start)
	arc.theta = _get_theta(-arc.offset[arc.plane_axis_0], -arc.offset[arc.plane_axis_1]);
	if(isnan(arc.theta) == true) return(STAT_ARC_SPECIFICATION_ERROR);

	// calculate the theta (angle) of the target point
	float theta_end = _get_theta(
		arc.gm.target[arc.plane_axis_0] - arc.offset[arc.plane_axis_0] - arc.position[arc.plane_axis_0],
 		arc.gm.target[arc.plane_axis_1] - arc.offset[arc.plane_axis_1] - arc.position[arc.plane_axis_1]);
	if(isnan(theta_end) == true) return (STAT_ARC_SPECIFICATION_ERROR);

	// ensure that the difference is positive so we have clockwise travel
	if (theta_end < arc.theta) { theta_end += 2*M_PI; }

	// compute angular travel and invert if gcode wants a counterclockwise arc
	// if angular travel is zero interpret it as a full circle
	arc.angular_travel = theta_end - arc.theta;
	if (fp_ZERO(arc.angular_travel)) {
		if (cm.gm.motion_mode == MOTION_MODE_CCW_ARC) {
			arc.angular_travel -= 2*M_PI;
		} else {
			arc.angular_travel = 2*M_PI;
		}
	} else {
		if (cm.gm.motion_mode == MOTION_MODE_CCW_ARC) {
			arc.angular_travel -= 2*M_PI;
		}
	}

	// Find the radius, calculate travel in the depth axis of the helix,
	// and compute the time it should take to perform the move
	arc.radius = hypot(arc.offset[arc.plane_axis_0], arc.offset[arc.plane_axis_1]);
	arc.linear_travel = arc.gm.target[arc.linear_axis] - arc.position[arc.linear_axis];

	// length is the total mm of travel of the helix (or just a planar arc)
	arc.length = hypot(arc.angular_travel * arc.radius, fabs(arc.linear_travel));
	if (arc.length < cm.arc_segment_len) return (STAT_MINIMUM_LENGTH_MOVE); // arc is too short to draw

	arc.time = _get_arc_time(arc.linear_travel, arc.angular_travel, arc.radius);

	// Find the minimum number of segments that meets these constraints...
	float segments_required_for_chordal_accuracy = arc.length / sqrt(4*cm.chordal_tolerance * (2 * arc.radius - cm.chordal_tolerance));
	float segments_required_for_minimum_distance = arc.length / cm.arc_segment_len;
	float segments_required_for_minimum_time = arc.time * MICROSECONDS_PER_MINUTE / MIN_ARC_SEGMENT_USEC;
	arc.segments = floor(min3(segments_required_for_chordal_accuracy,
							   segments_required_for_minimum_distance,
							   segments_required_for_minimum_time));

	arc.segments = max(arc.segments, 1);		//...but is at least 1 segment
	arc.gm.move_time = arc.time / arc.segments;	// gcode state struct gets segment_time, not arc time
	arc.segment_count = (int32_t)arc.segments;
	arc.segment_theta = arc.angular_travel / arc.segments;
	arc.segment_linear_travel = arc.linear_travel / arc.segments;
	arc.center_0 = arc.position[arc.plane_axis_0] - sin(arc.theta) * arc.radius;
	arc.center_1 = arc.position[arc.plane_axis_1] - cos(arc.theta) * arc.radius;
	arc.gm.target[arc.linear_axis] = arc.position[arc.linear_axis];	// initialize the linear target
	return (STAT_OK);
}