Exemple #1
0
static void handle_motors(unsigned long long current_time) { // {{{
	// Check for move.
	if (!computing_move) {
		movedebug("handle motors not moving");
		return;
	}
	movedebug("handling %d %d", computing_move, cbs_after_current_move);
	double factor = 1;
	double t = (current_time - settings.start_time) / 1e6;
	if (t >= settings.t0 + settings.tp) {	// Finish this move and prepare next. {{{
		movedebug("finishing %f %f %f %ld %ld", t, settings.t0, settings.tp, long(current_time), long(settings.start_time));
		//debug("finish steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			bool new_move = false;
			if (!isnan(sp.settings.dist[0])) {
				for (int a = 0; a < sp.num_axes; ++a) {
					if (!isnan(sp.axis[a]->settings.dist[0])) {
						sp.axis[a]->settings.source += sp.axis[a]->settings.dist[0];
						sp.axis[a]->settings.dist[0] = NAN;
						//debug("new source %d %f", a, sp.axis[a]->settings.source);
					}
				}
				sp.settings.dist[0] = NAN;
			}
			for (int a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			move_axes(&sp, current_time, factor);
			//debug("f %f", factor);
		}
		//debug("f2 %f %ld %ld", factor, settings.last_time, current_time);
		bool did_steps = do_steps(factor, current_time);
		//debug("f3 %f", factor);
		// Start time may have changed; recalculate t.
		t = (current_time - settings.start_time) / 1e6;
		if (t / (settings.t0 + settings.tp) >= done_factor) {
			int had_cbs = cbs_after_current_move;
			//debug("clearing %d cbs after current move for later inserting into history", cbs_after_current_move);
			cbs_after_current_move = 0;
			run_file_fill_queue();
			if (settings.queue_start != settings.queue_end || settings.queue_full) {
				had_cbs += next_move();
				if (!aborting && had_cbs > 0) {
					int fragment;
					if (num_active_motors == 0)
						fragment = (current_fragment + FRAGMENTS_PER_BUFFER - 1) % FRAGMENTS_PER_BUFFER;
					else
						fragment = current_fragment;
					//debug("adding %d cbs to fragment %d", had_cbs, fragment);
					history[fragment].cbs += had_cbs;
				}
				return;
			}
			cbs_after_current_move += had_cbs;
			//debug("adding %d to cbs after current move making it %d", had_cbs, cbs_after_current_move);
			if (factor == 1) {
				//debug("queue done");
				if (!did_steps) {
					//debug("done move");
					computing_move = false;
					// Cut off final sample, which was no steps anyway.
					current_fragment_pos -= 1;
				}
				for (int s = 0; s < NUM_SPACES; ++s) {
					Space &sp = spaces[s];
					for (int m = 0; m < sp.num_motors; ++m)
						sp.motor[m]->settings.last_v = 0;
				}
				if (cbs_after_current_move > 0) {
					if (!aborting) {
						int fragment;
						if (num_active_motors == 0)
							if (running_fragment == current_fragment) {
								//debug("sending movecbs immediately");
								send_host(CMD_MOVECB, cbs_after_current_move);
								cbs_after_current_move = 0;
								return;
							}
							else
								fragment = (current_fragment + FRAGMENTS_PER_BUFFER - 1) % FRAGMENTS_PER_BUFFER;
						else
							fragment = current_fragment;
						//debug("adding %d cbs to final fragment %d", cbs_after_current_move, fragment);
						history[fragment].cbs += cbs_after_current_move;
					}
					//debug("clearing %d cbs after current move in final", cbs_after_current_move);
					cbs_after_current_move = 0;
				}
			}
		}
		return;
	} // }}}
	if (t < settings.t0) {	// Main part. {{{
		double t_fraction = t / settings.t0;
		double current_f = (settings.f1 * (2 - t_fraction) + settings.f2 * t_fraction) * t_fraction;
		movedebug("main t %f t0 %f tp %f tfrac %f f1 %f f2 %f cf %f", t, settings.t0, settings.tp, t_fraction, settings.f1, settings.f2, current_f);
		//debug("main steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, current_f, false);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	else {	// Connector part. {{{
		movedebug("connector %f %f %f", t, settings.t0, settings.tp);
		double tc = t - settings.t0;
		double t_fraction = tc / settings.tp;
		double current_f2 = settings.fp * (2 - t_fraction) * t_fraction;
		double current_f3 = settings.fq * t_fraction * t_fraction;
		//debug("connect steps");
		for (int s = 0; s < NUM_SPACES; ++s) {
			if (!settings.single && s == 2)
				continue;
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0]) && isnan(sp.axis[a]->settings.dist[1])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, (1 - settings.fp) + current_f2, false);
			make_target(sp, current_f3, true);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	do_steps(factor, current_time);
} // }}}
Exemple #2
0
static void handle_motors(unsigned long long current_time) { // {{{
	// Check for move.
	if (!computing_move) {
		movedebug("handle motors not moving");
		return;
	}
	movedebug("handling %d", computing_move);
	double factor = 1;
	double t = (current_time - settings.start_time) / 1e6;
	if (t >= settings.t0 + settings.tp) {	// Finish this move and prepare next. {{{
		movedebug("finishing %f %f %f %ld %ld", t, settings.t0, settings.tp, long(current_time), long(settings.start_time));
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			bool new_move = false;
			if (!isnan(sp.settings.dist[0])) {
				for (uint8_t a = 0; a < sp.num_axes; ++a) {
					if (!isnan(sp.axis[a]->settings.dist[0])) {
						sp.axis[a]->settings.source += sp.axis[a]->settings.dist[0];
						sp.axis[a]->settings.dist[0] = NAN;
						//debug("new source %d %f", a, sp.axis[a]->settings.source);
					}
				}
				sp.settings.dist[0] = NAN;
			}
			for (uint8_t a = 0; a < sp.num_axes; ++a)
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			move_axes(&sp, current_time, factor);
			//debug("f %f", factor);
		}
		//debug("f2 %f %ld %ld", factor, settings.last_time, current_time);
		bool did_steps = do_steps(factor, current_time);
		//debug("f3 %f", factor);
		// Start time may have changed; recalculate t.
		t = (current_time - settings.start_time) / 1e6;
		if (t / (settings.t0 + settings.tp) >= done_factor) {
			uint8_t had_cbs = cbs_after_current_move;
			cbs_after_current_move = 0;
			run_file_fill_queue();
			if (settings.queue_start != settings.queue_end || settings.queue_full) {
				had_cbs += next_move();
				if (!aborting && had_cbs > 0) {
					//debug("adding %d cbs to fragment %d", had_cbs, current_fragment);
					history[current_fragment].cbs += had_cbs;
				}
				return;
			}
			cbs_after_current_move += had_cbs;
			if (factor == 1) {
				//debug("queue done");
				if (!did_steps) {
					//debug("done move");
					computing_move = false;
				}
				for (uint8_t s = 0; s < 2; ++s) {
					Space &sp = spaces[s];
					for (uint8_t m = 0; m < sp.num_motors; ++m)
						sp.motor[m]->settings.last_v = 0;
				}
				if (cbs_after_current_move > 0) {
					if (!aborting) {
						//debug("adding %d cbs to final fragment %d", cbs_after_current_move, current_fragment);
						history[current_fragment].cbs += cbs_after_current_move;
					}
					cbs_after_current_move = 0;
				}
			}
		}
		return;
	} // }}}
	if (t < settings.t0) {	// Main part. {{{
		double t_fraction = t / settings.t0;
		double current_f = (settings.f1 * (2 - t_fraction) + settings.f2 * t_fraction) * t_fraction;
		movedebug("main t %f t0 %f tp %f tfrac %f f1 %f f2 %f cf %f", t, settings.t0, settings.tp, t_fraction, settings.f1, settings.f2, current_f);
		for (int s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, current_f, false);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	else {	// Connector part. {{{
		movedebug("connector %f %f %f", t, settings.t0, settings.tp);
		double tc = t - settings.t0;
		double t_fraction = tc / settings.tp;
		double current_f2 = settings.fp * (2 - t_fraction) * t_fraction;
		double current_f3 = settings.fq * t_fraction * t_fraction;
		for (uint8_t s = 0; s < 2; ++s) {
			Space &sp = spaces[s];
			for (uint8_t a = 0; a < sp.num_axes; ++a) {
				if (isnan(sp.axis[a]->settings.dist[0]) && isnan(sp.axis[a]->settings.dist[1])) {
					sp.axis[a]->settings.target = NAN;
					continue;
				}
				sp.axis[a]->settings.target = sp.axis[a]->settings.source;
			}
			make_target(sp, (1 - settings.fp) + current_f2, false);
			make_target(sp, current_f3, true);
			move_axes(&sp, current_time, factor);
		}
	} // }}}
	do_steps(factor, current_time);
} // }}}
Exemple #3
0
static void apply_tick() { // {{{
	// Move motors to position for next time tick.
	// If it exceeds limits, adjust hwtime so that it's acceptable.
	//debug("tick");
	if (current_fragment_pos >= SAMPLES_PER_FRAGMENT) {
		// Fragment is already full. This shouldn't normally happen.
		debug("aborting apply_tick, because fragment is already full.");
		return;
	}
	// Check for move.
	if (!computing_move) {
		mdebug("apply tick called, but not moving");
		return;
	}
	mdebug("handling %d %d", computing_move, cbs_after_current_move);
	// This loop is normally only run once, but when a move is complete it is rerun for the next move.
	while ((running_fragment - 1 - current_fragment + FRAGMENTS_PER_BUFFER) % FRAGMENTS_PER_BUFFER > (FRAGMENTS_PER_BUFFER > 4 ? 4 : FRAGMENTS_PER_BUFFER - 2)) {
		settings.hwtime += settings.hwtime_step;
		//debug("tick time %d step %d frag %d pos %d", settings.hwtime, settings.hwtime_step, current_fragment, current_fragment_pos);
		double t = settings.hwtime / 1e6;
		double target_factor;	// Factor of current move that should be completed at this time.
		if (settings.hwtime >= settings.end_time)
			target_factor = 1;
		else if (settings.hwtime <= 0)
			target_factor = 0;
		else {
			target_factor = ((settings.v1 - settings.v0) / (settings.end_time / 1e6) * t * t / 2 + settings.v0 * t) / settings.dist;
			if (target_factor > 1)
				target_factor = 1;
			if (target_factor < 0)
				target_factor = 0;
		}
		//debug("target factor: %f (t=%f end=%f)", target_factor, t, settings.end_time / 1e6);
		// Go straight to the next move if the distance was 0 (so target_factor is NaN).
		if (!std::isnan(target_factor)) {
			double f = set_targets(target_factor);
			if (f < 1) {
				//double old = target_factor;
				if (settings.factor > 0 || settings.hwtime <= 0)
					target_factor = settings.factor + f * (target_factor - settings.factor);
				else {
					// settings.factor == 0, so we're at the start of a move.
					// settings.hwtime > 0, so this must be a continuation.
					// Only the new part can be limited, so to limit the same distance, it needs to be a larger fraction.
					// Example:
					// hwtime_step = 10
					// hwtime = 6
					// -> newpart = 0.6
					// f = 0.9
					// target move = 100
					// so (1-0.9)*100=10 of target move must be removed
					// that is (1-0.9)/0.6 of new part.
					double newpart = settings.hwtime * 1. / settings.hwtime_step;
					f = 1 - (1 - f) / newpart;
					target_factor = f * target_factor;
				}
				if (target_factor < 0)
					target_factor = 0;
				else if (target_factor > 1)
					target_factor = 1;
				//debug("adjust factor (%f) from %f to %f because f=%f", settings.factor, old, target_factor, f);
				set_targets(target_factor);
				// Adjust time.
				settings.hwtime -= settings.hwtime_step * ((1 - f) * .99);
			}
			//debug("target factor %f time 0 -> %d -> %d v %f -> %f", target_factor, settings.hwtime, settings.end_time, settings.v0, settings.v1);
			settings.factor = target_factor;
			if (settings.factor < 1) {
				do_steps();
				return;
			}
		}
		//debug("next segment");
		// Set new sources for all axes.
		for (int s = 0; s < NUM_SPACES; ++s) {
			Space &sp = spaces[s];
			for (int a = 0; a < sp.num_axes; ++a) {
				auto ax = sp.axis[a];
				ax->settings.source = ax->settings.target;
			}
		}
		// start new move; adjust time.
		history[current_fragment].cbs += cbs_after_current_move;
		//debug("adding %d cbs because move is completed", cbs_after_current_move);
		cbs_after_current_move = next_move(settings.end_time);
		//debug("new pending cbs: %d", cbs_after_current_move);
		mdebug("next move prepared");
		if (!computing_move) {
			// There is no next move.
			continue_event = true;
			do_steps();
			return;
		}
		mdebug("try again");
		// Next loop the time is incremented again, but in this case that shouldn't happen, so compensate.
		settings.hwtime -= settings.hwtime_step;
	}
	//if (spaces[0].num_axes >= 2)
		//debug("move z %d %d %f %f %f", current_fragment, current_fragment_pos, spaces[0].axis[2]->settings.current, spaces[0].motor[0]->settings.current_pos, spaces[0].motor[0]->settings.current_pos + avr_pos_offset[0]);
} // }}}