/// <summary> /// Does nothing, as even distances don't require additional patterns. /// </summary> /// <returns> /// The number of new patterns added. /// </returns> /// <param name='forList'> /// THe list to add new patterns to if required. /// </param> /// <param name='totalTicksWaited'> /// The total number of ticks we've waited thus far. /// </param> static void HandleEvenPattern(List <TickProfile> forList, ref int totalTicksWaited) { // Instead of having two additional tick profiles, just make one longer one. TickProfile lastProfile = forList[forList.Count - 1]; totalTicksWaited += lastProfile.tickLength; lastProfile.tickLength *= 2; }
/// <summary> /// Inserts the extra required step for odd distances. /// </summary> /// <returns> /// The number of new patterns added. /// </returns> /// <param name='forList'> /// The list to add new patterns to if required. /// </param> /// <param name='totalTicksWaited'> /// The total number of ticks we've waited thus far. /// </param> static void HandleOddPattern(List <TickProfile> forList, ref int totalTicksWaited) { // Step rate is one more in the future; we also create a gap // for the odd value, below. TickProfile lastProfile = forList[forList.Count - 1]; int additionalTicks = lastProfile.tickLength + lastProfile.stepRate; lastProfile.tickLength += additionalTicks; totalTicksWaited += additionalTicks; }
/// <summary> /// Optionally accelerates the specified arc using the provided platform step rate /// to calculate the initial tick location. Results are added to the provided list. /// If the arc is small, an unaccelerated TickProfile is added to the list instead. /// </summary> /// <param name='anArc'> /// An arc to accelerate. /// </param> /// <param name='usingPlatformStepRate'> /// The platform's step-rate. /// </param> /// <param name='forList'> /// The list to update. /// </param> static int Accelerate(Arc anArc, int usingPlatformStepRate, List <TickProfile> forList) { Contract.Assert(usingPlatformStepRate > 0, @"Expected a positive platform step rate, not {0}.", usingPlatformStepRate); TickProfile constantTick = new TickProfile(anArc, usingPlatformStepRate, PrinterExtruder.kDefaultTickRate); if (constantTick.tickLength > 0) { forList.Add(constantTick); } return(constantTick.tickLength); }
public TickProfile(TickProfile source, int aStartTick) { motor = source.motor; size = source.size; direction = source.direction; stepRate = source.stepRate; startTick = aStartTick; tickLength = source.tickLength; // NOTE: Negative tick profiles are OK // when pressurizing, so we don't // check for negative start ticks. Contract.Assert(tickLength >= 0, @"Negative tick length."); Contract.Assert(motor != null, @"No motor assigned to tick profile."); Contract.Assert(direction != StepDirection.Unknown, @"Unknown step direction."); }
static void Extrude(Arc anArc, int atRate, int usingPlatformStepRate, List <TickProfile> forList) { Contract.Assert(atRate > 0, @"Expected positive extrusion rate, not {0}.", atRate); PrinterExtruder extruder = (PrinterExtruder)anArc.motor; if (!anArc.hasVariableStepRate) { extruder.stepsExtruded += anArc.length; // Scale small arc step rate by a constant. if (anArc.length < kSmallArcLimit) { atRate = Mathf.RoundToInt(atRate / kSmallArcRateScale); } TickProfile result = new TickProfile(anArc, usingPlatformStepRate, atRate); if (result.tickLength > 0) { forList.Add(result); } } else { extruder.stepsExtruded += anArc.variableStepLocations.Length; foreach (int singleArc in anArc.variableStepLocations) { Arc aNewArc = new Arc(anArc); aNewArc.startStep = anArc.startStep + singleArc; aNewArc.endStep = aNewArc.startStep + 1; TickProfile result = new TickProfile(aNewArc, usingPlatformStepRate, usingPlatformStepRate); if (result.tickLength > 0) { forList.Add(result); } else { Text.Error("Came up with a tickprofile with no movement while processing arc " + aNewArc); } //Text.Log("For " + aNewArc + " we came up with profile " + result); } } }
/// <summary> /// Converts the queue of arcs into a list of tick profiles /// using the provided platform step-rate for conversion and /// optionally with acceleration. /// </summary> /// <param name='arcs'> /// The arc source. /// </param> /// <param name='toList'> /// The target list. /// </param> /// <param name='usingPlatformStepRate'> /// The platform step rate. /// </param> /// <param name='withAcceleration'> /// True for acceleration, false for a constant speed. /// </param> public static void Convert(List <Arc> fromArcs, List <TickProfile> toList, int usingPlatformStepRate) { toList.Clear(); // NOTE(kevin): Could try merging arcs, but this is low // priority. for (int aI = 0; aI < fromArcs.Count; aI++) { Arc a = fromArcs[aI]; if (a.length == 0) { continue; } Contract.Assert(a.motor != null, @"No motor assigned for arc {0}.", a); TickProfile result = new TickProfile(a, usingPlatformStepRate, usingPlatformStepRate); toList.Add(result); } fromArcs.Clear(); }
IEnumerator TestRoutine() { while (!startAngleTest && !startRotationTest) { yield return(null); } Init(); yield return(null); if (startAngleTest) { int stepDirection = -1; int targetAngle = smallAngle; for (int testCount = 0; testCount < 10000000; testCount++) { stepDirection = -stepDirection; targetAngle = targetAngle == smallAngle ? largeAngle : smallAngle; if (true) //!shouldUseAccel) { { pc.MoveMotorAtSteprateForTicks(workingPrinter, workingPrinter.platform, StepSize.Quarter, (StepDirection)stepDirection, stepRate, stepRate * numStepsPerRot * targetAngle / 360); } /* * else { * TickProfile aProfile; * for(int i = 0; i < rates.Length - 1; i++) { * aProfile = new TickProfile(workingPrinter.platform, * StepSize.Quarter, * (StepDirection)stepDirection, * rates[i], * 0, * rates[i]); * pc.AddTickProfileForMotorAndSend(workingPrinter, workingPrinter.platform, aProfile); * } * aProfile = new TickProfile(workingPrinter.platform, * StepSize.Quarter, * (StepDirection)stepDirection, * rates[rates.Length - 1], * 0, * rates[rates.Length - 1] * numStepsPerRot * targetAngle / 360); * pc.AddTickProfileForMotorAndSend(workingPrinter, workingPrinter.platform, aProfile); * * for(int i = rates.Length - 2; i > -1; i--) { * aProfile = new TickProfile(workingPrinter.platform, * StepSize.Quarter, * (StepDirection)stepDirection, * rates[i], * 0, * rates[i]); * pc.AddTickProfileForMotorAndSend(workingPrinter, workingPrinter.platform, aProfile); * } * } */ yield return(null); if (targetAngle == smallAngle) { smallAngleCount++; } else { largeAngleCount++; } yield return(Scheduler.StartCoroutine(pc.WaitUntilDoneMoving())); } } else if (startRotationTest) { for (int testCount = 0; testCount < 1000000000; testCount++) { TickProfile aProfile = new TickProfile(workingPrinter.platform, StepSize.Quarter, StepDirection.Ccw, stepRate, 0, stepRate * numStepsPerRot); pc.AddTickProfileForMotorAndSend(workingPrinter, workingPrinter.platform, aProfile); yield return(new WaitSeconds(2.2f)); //yield return Scheduler.StartCoroutine(pc.WaitUntilDoneMoving()); largeAngleCount++; } } }
public int UpdateState(TickProfile fromProfile, List <TxPacket> forList) { int targetMotorId = fromProfile.motor.id; PrinterMotor targetMotor = targetMotorId < kBaseMotors ? GetBaseMotor(targetMotorId) : extruders[targetMotorId - kBaseMotors]; Contract.Assert(targetMotor.id == targetMotorId, @"Found motor {0} but id isn't {1}.", targetMotor, targetMotorId); bool shouldSendDirection = targetMotor.stepDirection != fromProfile.direction; bool shouldSendStepSize = targetMotor.stepSize != fromProfile.size; bool shouldSendStepRate = targetMotor.stepRate != fromProfile.stepRate; if (shouldSendDirection || shouldSendStepSize || shouldSendStepRate) { if (currentMotorId != targetMotorId) { // Select the motor; note that we don't change the stack. if (lastEnqueuedPacket != null && lastEnqueuedPacket.aCmd == GanglionCommand.StepRate) { lastEnqueuedPacket.aCmd = kStepRateMotor[targetMotorId]; } else { lastEnqueuedPacket = new TxPacket(kMotorToCommand[targetMotorId]); forList.Add(lastEnqueuedPacket); } currentMotorId = targetMotorId; } Contract.Assert(currentMotorId == targetMotor.id, @"Motor id mismatch: {0} != {1}", currentMotorId, targetMotor.id); if (shouldSendDirection) { lastEnqueuedPacket = new TxPacket(fromProfile.direction == StepDirection.Ccw ? GanglionCommand.CounterClockwise : GanglionCommand.Clockwise); forList.Add(lastEnqueuedPacket); targetMotor.stepDirection = fromProfile.direction; } if (shouldSendStepSize) { int ganglionSize = kStepConversion[fromProfile.size]; lastEnqueuedPacket = new TxPacket(GanglionCommand.Value, ganglionSize); forList.Add(lastEnqueuedPacket); lastEnqueuedPacket = new TxPacket(GanglionCommand.StepSize); forList.Add(lastEnqueuedPacket); targetMotor.stepSize = fromProfile.size; m_lastNumberSent = ganglionSize; } if (shouldSendStepRate) { if (fromProfile.stepRate == 0) { if (lastEnqueuedPacket != null && kMotorStop.ContainsKey(lastEnqueuedPacket.aCmd)) { lastEnqueuedPacket.aCmd = kMotorStop[lastEnqueuedPacket.aCmd]; } else { lastEnqueuedPacket = new TxPacket(GanglionCommand.Stop); forList.Add(lastEnqueuedPacket); } } else { if (m_lastNumberSent != fromProfile.stepRate) { lastEnqueuedPacket = new TxPacket(GanglionCommand.Value, fromProfile.stepRate); forList.Add(lastEnqueuedPacket); m_lastNumberSent = fromProfile.stepRate; } lastEnqueuedPacket = new TxPacket(GanglionCommand.StepRate); forList.Add(lastEnqueuedPacket); } targetMotor.stepRate = fromProfile.stepRate; } } Contract.Assert(targetMotor.stepDirection == fromProfile.direction, @"Direction mismatch: {0} != {1}.", targetMotor.stepDirection, fromProfile.direction); Contract.Assert(targetMotor.stepSize == fromProfile.size, @"Step size mismatch: {0} != {1}", targetMotor.stepSize, fromProfile.size); Contract.Assert(targetMotor.stepRate == fromProfile.stepRate, @"Step rate mismatch: {0} != {1}.", targetMotor.stepRate, fromProfile.stepRate); return(m_lastNumberSent); }
public static void ConvertExtruder(List <Arc> arcs, List <TickProfile> toList, int usingPlatformStepRate, int stepsPerPlatformRotation, int withInitialPressureSteps, int withLastPlatformStep, out int shiftInTicksRequired, out int depressureRequested) { Contract.Assert(arcs.Count > 0, @"Called with empty arcs; should be handled prior."); int extrusionRate = ((PrinterExtruder) (arcs[0].motor)).SetExtrusionRate(stepsPerPlatformRotation * usingPlatformStepRate, arcs.Count); // How far before the initial tick do we start? int initialPressureTick = 0; if (withInitialPressureSteps > 0) { initialPressureTick = Pressurize(arcs[0], withInitialPressureSteps, usingPlatformStepRate, toList); } shiftInTicksRequired = Mathf.Max(-initialPressureTick, 0); Extrude(arcs[0], extrusionRate, usingPlatformStepRate, toList); for (int i = 1; i < arcs.Count; ++i) { Arc lastArc = arcs[i - 1]; Arc thisArc = arcs[i]; int halfSpaceAvailable = (thisArc.startStep - lastArc.endStep) / 2; int pressureSteps = Mathf.Min(halfSpaceAvailable, kPressureSteps); Contract.Assert(pressureSteps >= 0, @"Expected positive pressure steps, not {0}, between {1} and {2}.", pressureSteps, lastArc, thisArc); Contract.Assert(pressureSteps <= kPressureSteps, @"Pressure steps too large: {0}.", pressureSteps); if (lastArc.hasVariableStepRate && thisArc.hasVariableStepRate) { pressureSteps = 0; } if (pressureSteps > 0) { Depressurize(lastArc, pressureSteps, usingPlatformStepRate, toList); Pressurize(thisArc, pressureSteps, usingPlatformStepRate, toList); } Extrude(thisArc, extrusionRate, usingPlatformStepRate, toList); } Arc finalArc = arcs[arcs.Count - 1]; int depressureAvailable = Mathf.Min(kPressureSteps, Mathf.Max(withLastPlatformStep - finalArc.endStep, 0)); if (depressureAvailable > 0) { Depressurize(arcs[arcs.Count - 1], depressureAvailable, usingPlatformStepRate, toList); } // Return the untaken depressure steps. depressureRequested = kPressureSteps - depressureAvailable; #if UNITY_EDITOR for (int i = 1; i < toList.Count; ++i) { TickProfile p0 = toList[i - 1]; TickProfile p1 = toList[i]; Contract.Assert(p0.endTick <= p1.startTick, @"Created overlapping profiles {0} and {1}", p0, p1); } #endif }