示例#1
0
Status Stroke::traverse(Ticks tCurrent, QuadStepper &stepper) {
    Quad<StepCoord> dGoal = goalPos(tCurrent);
    if (tStart <= 0) {
        return STATUS_STROKE_START;
    }
#ifdef TEST
    Ticks endTicks = tCurrent - (tStart + dtTotal);
    if (endTicks > -5) {
        TESTCOUT2("traverse(", endTicks, ") ", dGoal.toString());
    }
#endif

    Status status = STATUS_BUSY_MOVING;
    Quad<StepDV> pulse;
#define PULSE_BLOCK 32 /* pulses emitted without limit checks */
    Quad<StepCoord> dPosSeg = dGoal - dPos;
    for (bool done = true; ; done = true) {
        for (QuadIndex i = 0; i < QUAD_ELEMENTS; i++) {
            StepCoord dp = dPosSeg.value[i];
            if (dp < -PULSE_BLOCK) {
                pulse.value[i] = -PULSE_BLOCK;
                done = false;
            } else if (dp > PULSE_BLOCK) {
                pulse.value[i] = PULSE_BLOCK;
                done = false;
            } else if (dp) {
                pulse.value[i] = dp;
                done = false;
            } else {
                pulse.value[i] = 0;
            }
            dPosSeg.value[i] -= (StepCoord) pulse.value[i];
            dPos.value[i] += (StepCoord) pulse.value[i];
        }
        if (done) {
            break;
        }
        if (0 > (status = stepper.stepDirection(pulse))) {
            return status;
        }
        if (0 > (status = stepper.stepFast(pulse))) {
            return status;
        }
    }
    if (tCurrent >= tStart + dtTotal) {
        TESTCOUT3("Stroke::traverse() tCurrent:", tCurrent, " tStart:", tStart, " dtTotal:", dtTotal);
        return STATUS_OK;
    }
    return STATUS_BUSY_MOVING;
}
示例#2
0
/**
 * Create a line by scaling a known PH5Curve to match the requested linear
 * offset.
 */
Status StrokeBuilder::buildLine(Stroke & stroke, Quad<StepCoord> relPos) {
    PH5TYPE K[QUAD_ELEMENTS];
    PH5TYPE Ksqrt[QUAD_ELEMENTS];
    StepCoord pulses = 0;
    QuadIndex iMax = 0;

    // Determine scale K for each Quad dimension
    for (QuadIndex i = 0; i < QUAD_ELEMENTS; i++) {
        K[i] = relPos.value[i] / 6400.0;
        TESTCOUT2("K[", i, "]:", K[i]);
        Ksqrt[i] = sqrt(abs(K[i]));
        if (pulses < abs(relPos.value[i])) {
            pulses = abs(relPos.value[i]);
            iMax = i;
        }
    }

    // Generate scaled PH5Curve coefficients
    TESTCOUT1("buildLine:", relPos.toString());
#define Z6400 56.568542495
    PHVECTOR<Complex<PH5TYPE> > z[QUAD_ELEMENTS];
    PHVECTOR<Complex<PH5TYPE> > q[QUAD_ELEMENTS];
    for (QuadIndex i = 0; i < QUAD_ELEMENTS; i++) {
        z[i].push_back(Complex<PH5TYPE>());
        if (K[i] < 0) {
            z[i].push_back(Complex<PH5TYPE>(0, Z6400 * Ksqrt[i]));
            z[i].push_back(Complex<PH5TYPE>(0, Z6400 * Ksqrt[i]));
        } else {
            z[i].push_back(Complex<PH5TYPE>(Z6400 * Ksqrt[i]));
            z[i].push_back(Complex<PH5TYPE>(Z6400 * Ksqrt[i]));
        }
        q[i].push_back(Complex<PH5TYPE>());
        q[i].push_back(Complex<PH5TYPE>(3200 * K[i]));
        q[i].push_back(Complex<PH5TYPE>(6400 * K[i]));
    }

    // Use the longest PH5Curve to determine the parametric value for all
    PH5Curve<PH5TYPE> phMax(z[iMax], q[iMax]);
    PHFeed<PH5TYPE> phfMax(phMax, vMax, vMaxSeconds);
    PH5TYPE tS = phfMax.get_tS();

    // Calculate the optimal number of segments using weird heuristics
#define MS_PER_SEGMENT 30
    int16_t N = 1000 * tS / MS_PER_SEGMENT;
    int16_t minSegs = minSegments;
    if (minSegs == 0) {
        minSegs = 5; // minimum number of acceleration segments
        minSegs = (float)minSegs * (float)abs(pulses) / (vMax * vMaxSeconds);
        TESTCOUT4("pulses:", pulses, " minSegs:", minSegs, " vMax:", vMax, " vMaxSeconds:", vMaxSeconds);
        int16_t minSegsK = abs(pulses) / 200.0;
        if (minSegs < minSegsK) {
            TESTCOUT1("minSegsK:", minSegsK);
            minSegs = minSegsK;
        }
        minSegs = max((int16_t)16, min((int16_t)(STROKE_SEGMENTS - 1), minSegs));
    }
    N = max(minSegs, min(maxSegments, (int16_t)N));
    if (N >= STROKE_SEGMENTS) {
        return STATUS_STROKE_MAXLEN;
    }

    // Build the stroke dimension by dimension
    stroke.clear();
    stroke.setTimePlanned(tS);
    stroke.length = N;
#define SCALE 2
    stroke.scale = SCALE;
    PH5TYPE E[STROKE_SEGMENTS + 1];
    E[0] = phfMax.Ekt(0, 0);
    for (int16_t iSeg = 1; iSeg <= N; iSeg++) {
        PH5TYPE fSeg = iSeg / (PH5TYPE)N;
        E[iSeg] = phfMax.Ekt(E[iSeg - 1], fSeg);
    }
    for (QuadIndex i = 0; i < QUAD_ELEMENTS; i++) {
        PH5Curve<PH5TYPE> ph(z[i], q[i]);
        StepCoord s = 0;
        StepCoord v = 0;
        for (int16_t iSeg = 1; iSeg <= N; iSeg++) {
            PH5TYPE pos = ph.r(E[iSeg]).Re();
            if (iSeg == N) {
                stroke.dEndPos.value[i] = pos < 0 ? pos - 0.5 : pos + 0.5;
                TESTCOUT2("dEndPos.value[", (int) i, "] ", stroke.dEndPos.value[i]);
            }
            pos /= SCALE;
            StepCoord sNew = pos < 0 ? pos - 0.5 : pos + 0.5;
            StepCoord vNew = sNew - s;
            stroke.vPeak = max(stroke.vPeak, (int32_t)abs(vNew*SCALE));
            StepCoord dv = vNew - v;
            //TESTCOUT4("iSeg:", iSeg, " sNew:", sNew, " vNew:", vNew, " dv:", dv);
            if (dv < (StepCoord) - 127 || (StepCoord) 127 < dv) {
                TESTCOUT3(" STATUS_STROKE_SEGPULSES pulses:", dv, " i:", (int)i, " N:", (int)N);
                return STATUS_STROKE_SEGPULSES;
            }
            stroke.seg[iSeg - 1].value[i] = dv;
            v = vNew;
            s = sNew;
        }
    }

    leastFreeRam = min(leastFreeRam, freeRam());

    TESTCOUT3(" N:", N, " tS:", tS, " dEndPos:", stroke.dEndPos.toString());

    return STATUS_OK;
}
示例#3
0
void f(Quad& q) {
	cout << q.toString() << endl
		<< q.area() << endl
		<< q.perimeter() << endl;
}