/// <summary> /// Tries assigning an extruder to the arcs. /// </summary> /// <returns> /// True if successful; false if another extruder /// has already been assigned. /// </returns> /// <param name='anExtruder'> /// The extruder to assign. /// </param> /// <param name='toRing'> /// The ring number we care about. /// </param> public bool TryAssigning(PrinterExtruder anExtruder) { int toRing = Mathf.Abs(anExtruder.relativeRing); foreach (Arc anArc in m_arcs[toRing]) { if (anArc.material == anExtruder.materialNumber) { // If we find an arc with another motor assigned, // then we have to handle the conflicts. if (anArc.motor == null) { anArc.motor = anExtruder; } else { Contract.Assert((PrinterExtruder)anArc.motor != anExtruder, @"Arc's motor {0} same as tested extruder; TryAssigning() called multiple times for same ring {1}.", anArc.motor, toRing); return(false); } } } // The arcs, if any, were successfully assigned. return(true); }
/// <summary> /// Clones this instance. /// </summary> public override PrinterMotor Clone() { PrinterExtruder result = new PrinterExtruder(); Populate(result); return(result); }
/// <summary> /// Clones this instance. /// </summary> public void Populate(PrinterExtruder result) { base.Populate(result); result.ringNumber = ringNumber; result.targetTemperatureC = targetTemperatureC; result.firstLayerTemperature = firstLayerTemperature; result.materialNumber = materialNumber; }
public MotorRateMover(PrinterExtruder anExtruder, StepDirection aDirection, StepSize aSize, int aRate, int aGlobalStepStart, int totalStepCount) { motor = (PrinterMotor)anExtruder; direction = aDirection; size = aSize; stepRate = aRate; globalStartStep = aGlobalStepStart; stepCount = totalStepCount; }
/// <summary> /// Fills the provided queue with normalized arcs for the /// provided extruder. Should be called after StartExtraction(). /// </summary> /// <param name='anExtruder'> /// The extruder we're searching for. /// </param> /// <param name='destination'> /// The final arc location. /// </param> public void ExtractArcsFor(PrinterExtruder anExtruder, List <Arc>[] destination) { int atRing = Mathf.Abs(anExtruder.relativeRing); // We're done if it's more than the outer ring. if (atRing > m_outerRing) { return; } List <Arc> arcs = m_arcs[atRing]; int initialArcCount = m_arcCount; for (int anArcId = 0; anArcId < arcs.Count; /* NOP */) { Arc anArc = arcs[anArcId]; if (anArc.motor == anExtruder) { destination[anExtruder.id].Add(anArc); arcs.RemoveAt(anArcId); m_earliestStep = Mathf.Min(m_earliestStep, anArc.startStep); m_latestStep = Mathf.Max(m_latestStep, anArc.endStep); --m_arcCount; } else { ++anArcId; } } Contract.Assert(m_arcCount == initialArcCount ? true : m_earliestStep <= m_latestStep, @"Ring {0}: Earliest step ({1}) larger than latest step ({2})", atRing, m_earliestStep, m_latestStep); // Did we empty a ring? if (m_arcCount < initialArcCount && arcs.Count == 0) { --m_ringCount; } }
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); } } }
static int ApplyPressure(PrinterMotor forMotor, StepDirection inDirection, int usingPressureSteps, int usingPlatformRotation, List <TickProfile> toList) { Contract.Assert(usingPressureSteps <= kPressureSteps, @"Requested {0} pressure steps; maximum is {1}.", usingPressureSteps, kPressureSteps); // NOTE: We don't know how many steps it'll take to // accelerate over usingPressureSteps. So we need // to treat everything as if it stepped from // [0, usingPressureSteps) and then scale the // resulting ticks by anArc.startingStep. Arc pressureArc = new Arc(forMotor, 0); pressureArc.startStep = 0; pressureArc.endStep = usingPressureSteps; pressureArc.direction = inDirection; PrinterExtruder extruder = (PrinterExtruder)forMotor; if (inDirection == StepDirection.Ccw) { extruder.pressureRequired -= usingPressureSteps; Contract.Assert(extruder.pressureRequired >= 0, @"Pressurized more than {0} steps.", kPressureSteps); } else { extruder.pressureRequired += usingPressureSteps; Contract.Assert(extruder.pressureRequired <= kPressureSteps, @"Motor {0} required pressure of {1} exceeds max of {2}.", extruder.id, extruder.pressureRequired, kPressureSteps); } int ticksTaken = Accelerate(pressureArc, usingPlatformRotation, toList); Contract.Assert(ticksTaken > 0, @"Non-positive ticks taken over {0} step{1}.", ticksTaken, Text.S(ticksTaken)); return(ticksTaken); }
void Extrude(PrinterExtruder anExtruder) { List <Vector4> points = extrudedPoints[anExtruder.id]; int prevIndex = points.Count - 1; int pressureDelta = anExtruder.stepDirection == StepDirection.Ccw ? 1 : -1; anExtruder.pressureRequired = Mathf.Clamp(anExtruder.pressureRequired - pressureDelta, 0, TickProfile.kPressureSteps); if (onlyCollectExtruded && anExtruder.pressureRequired > 0) { if (prevIndex >= 0 && points[prevIndex] != gap) { points.Add(gap); } return; } float relativePosition = -(m_simulation.platformRadiusInMm - (float)m_simulation.horizTrack.position); float distFromCenter = anExtruder.DistanceFromPlatCenterInMm(relativePosition); float angleInRad = m_simulation.platform.rotationInDegrees * Mathf.Deg2Rad; float colorIndex = ((anExtruder.id - kExtruderBase) * 2) + ((anExtruder.stepDirection == StepDirection.Ccw) ? 0 : 1); Vector4 point = new Vector4(distFromCenter * Mathf.Cos(angleInRad) + m_simulation.platformRadiusInMm, m_trans.position.y, distFromCenter * Mathf.Sin(angleInRad), colorIndex); /* * if (points.Count > 1 * && (points[prevIndex].w == point.w) * && ((Vector3)(point - points[prevIndex])).sqrMagnitude < kSqrThreshold) return; */ extrudedPoints[anExtruder.id].Add(point); }
void StepMotors() { //Text.Log(string.Format("Steps remaining: {0}, {1}", m_motorSteps[0], m_motorSteps[1])); for (int aMotorId = 0; aMotorId < m_motors.Length; ++aMotorId) { PrinterMotor aMotor = m_motors[aMotorId]; if (aMotor.stepRate == 0) { continue; } --aMotor.stepCounter; if (aMotor.stepCounter == 0) { aMotor.stepCounter = aMotor.stepRate; m_motorSteps[aMotorId] = 1; } } bool hasMoved = false; for (int aMotorId = 0; aMotorId < kExtruderBase; ++aMotorId) { if (m_motorSteps[aMotorId] > 0) { m_motors[aMotorId].Step(); --m_motorSteps[aMotorId]; hasMoved = true; } } for (int aMotorId = kExtruderBase; aMotorId < m_motorSteps.Length; ++aMotorId) { if (m_motorSteps[aMotorId] > 0) { m_motors[aMotorId].Step(); --m_motorSteps[aMotorId]; Extrude((PrinterExtruder)m_motors[aMotorId]); hasMoved = false; } } if (hasMoved && !onlyCollectExtruded) { PrinterExtruder anExtruder = (PrinterExtruder)m_motors[4]; float relativePosition = m_simulation.platformRadiusInMm - (float)m_simulation.horizTrack.position; float distFromCenter = anExtruder.DistanceFromPlatCenterInMm(relativePosition); float angleInRad = m_simulation.platform.rotationInDegrees * Mathf.Deg2Rad; Vector4 point = new Vector4(distFromCenter * Mathf.Cos(angleInRad) + m_simulation.platformRadiusInMm, -m_trans.position.y, distFromCenter * Mathf.Sin(angleInRad), 4); movementWithoutExtrusion.Add(point); } m_globalSteps = (m_globalSteps + 1) & 0xFFFFFFFF; Vector3 platformPosition = new Vector3(-(float)m_simulation.horizTrack.position, (float)m_simulation.vertTrack[0].position, 0); m_trans.position = platformPosition; m_trans.rotation = Quaternion.Euler(0, m_simulation.platform.rotationInDegrees, 0); }
public Vector3 GetExtruderCartesianPosition(PrinterExtruder anExtruder) { return(MathUtil.PolarToCartesian(GetExtruderPolarPosition(anExtruder))); }
public Vector3 GetExtruderPolarPosition(PrinterExtruder anExtruder) { return(PolarPosition + new Vector3(PrinterExtruder.kStandardNozzleWidth * anExtruder.ringNumber, 0, 0)); }
/// <summary> /// Assign the specified extruder to arcs if the relative /// ring matches; otherwise, uses the existing extruder. /// </summary> /// <param name='forSecondExtruder'> /// The extruder we're trying to assign. /// </param> /// <param name='usingStepsPerRotation'> /// Steps required for 1 platform rotation (excluding step-rate). /// </param> public void ResolveAssignments(PrinterExtruder forSecondExtruder, int usingStepsPerRotation) { PrinterExtruder firstExtruder = (PrinterExtruder)m_arcs[Mathf.Abs(forSecondExtruder.relativeRing)][0].motor; Contract.Assert(firstExtruder.materialNumber == forSecondExtruder.materialNumber, @"Extruder materials differ (#{0}: {1}; #{2}: {3}).", firstExtruder.id, firstExtruder.materialNumber, forSecondExtruder.id, forSecondExtruder.materialNumber); PrinterExtruder positiveExtruder = (firstExtruder.relativeRing < 0) ? forSecondExtruder : firstExtruder; PrinterExtruder negativeExtruder = (firstExtruder.relativeRing < 0) ? firstExtruder : forSecondExtruder; Contract.Assert(positiveExtruder != negativeExtruder, @"Extruder ids {0} and {1} are identical.", firstExtruder.id, forSecondExtruder.id); Contract.Assert(positiveExtruder.relativeRing > 0, @"Relative ring ({0}) isn't positive for extruder {1}.", positiveExtruder.relativeRing, positiveExtruder.id); Contract.Assert(negativeExtruder.relativeRing < 0, @"Relative ring ({0}) isn't negative for extruder {1}.", negativeExtruder.relativeRing, negativeExtruder.id); Contract.Assert(positiveExtruder.relativeRing == -negativeExtruder.relativeRing, @"Extruder {0}'s relative ring ({1}) doesn't match extruder {2}'s -relative ring ({3}).", positiveExtruder.id, positiveExtruder.relativeRing, negativeExtruder.id, negativeExtruder.relativeRing); List <Arc> arcs = m_arcs[positiveExtruder.relativeRing]; int stepsPerHalfRotation = usingStepsPerRotation / 2; for (int arcId = 0; arcId < arcs.Count; ++arcId) { Arc anArc = arcs[arcId]; // Skip arcs if they are for different materials. if (anArc.material != positiveExtruder.materialNumber) { continue; } if (anArc.startStep < stepsPerHalfRotation && anArc.endStep < stepsPerHalfRotation) { // Case 1: Everything happens before 180°, so use the positive extruder. anArc.motor = positiveExtruder; } else if (anArc.startStep >= stepsPerHalfRotation && anArc.endStep >= stepsPerHalfRotation) { // Case 2: Everything happens after 180°, so use the negative extruder. anArc.motor = negativeExtruder; } else { // Case 3: The arc straddles the 180° line; split it into two. Arc secondHalf = new Arc(anArc); // NOTE: We can't normalize the arcs yet because arcs // assigned to a single extruder with a negative // relative ring also need to get normalized. secondHalf.startStep = stepsPerHalfRotation; secondHalf.motor = negativeExtruder; anArc.endStep = stepsPerHalfRotation; anArc.motor = positiveExtruder; arcs.Insert(arcId + 1, secondHalf); // Skip the arc we just added. ++arcId; } } }