2015-08-01 14:44:53 -07:00
/ *
Copyright ( c ) 2014 , Lars Brubaker
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
using MatterHackers.Agg ;
using MatterHackers.GCodeVisualizer ;
using MatterHackers.Localizations ;
2015-08-15 16:18:49 -07:00
using MatterHackers.MatterControl.DataStorage ;
2015-08-01 15:50:39 -07:00
using MatterHackers.MatterControl.PrinterCommunication ;
2015-08-01 14:44:53 -07:00
using MatterHackers.MatterControl.SlicerConfiguration ;
using MatterHackers.VectorMath ;
2015-08-01 15:50:39 -07:00
using System ;
2015-08-01 14:44:53 -07:00
using System.Collections.Generic ;
2015-08-01 15:50:39 -07:00
using System.Text ;
2015-08-01 14:44:53 -07:00
namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
2015-08-15 16:18:49 -07:00
public class RadialLevlingFunctions
{
public int NumberOfRadialSamples { get ; set ; }
public PrintLevelingData LevelingData
{
get ; set ;
}
public Vector2 BedCenter
{
get ; set ;
}
Vector3 lastDestinationWithLevelingApplied = new Vector3 ( ) ;
public RadialLevlingFunctions ( int numberOfRadialSamples , PrintLevelingData levelingData , Vector2 bedCenter )
{
this . LevelingData = levelingData ;
this . BedCenter = bedCenter ;
this . NumberOfRadialSamples = numberOfRadialSamples ;
}
public Vector2 GetPrintLevelPositionToSample ( int index , double radius )
{
Vector2 bedCenter = ActiveSliceSettings . Instance . BedCenter ;
if ( index < NumberOfRadialSamples )
{
Vector2 position = new Vector2 ( radius , 0 ) ;
position . Rotate ( MathHelper . Tau / NumberOfRadialSamples * index ) ;
position + = bedCenter ;
return position ;
}
else
{
return bedCenter ;
}
}
public Vector3 GetPositionWithZOffset ( Vector3 currentDestination )
{
Vector2 destinationFromCenter = new Vector2 ( currentDestination ) - BedCenter ;
double angleToPoint = Math . Atan2 ( destinationFromCenter . y , destinationFromCenter . x ) ;
if ( angleToPoint < 0 )
{
angleToPoint + = MathHelper . Tau ;
}
double oneSegmentAngle = MathHelper . Tau / NumberOfRadialSamples ;
int firstIndex = ( int ) ( angleToPoint / oneSegmentAngle ) ;
int lastIndex = firstIndex + 1 ;
if ( lastIndex = = NumberOfRadialSamples )
{
lastIndex = 0 ;
}
Plane currentPlane = new Plane ( LevelingData . SampledPositions [ firstIndex ] , LevelingData . SampledPositions [ lastIndex ] , LevelingData . SampledPositions [ NumberOfRadialSamples ] ) ;
double hitDistance = currentPlane . GetDistanceToIntersection ( new Vector3 ( currentDestination . x , currentDestination . y , 0 ) , Vector3 . UnitZ ) ;
currentDestination . z + = hitDistance ;
return currentDestination ;
}
public string DoApplyLeveling ( string lineBeingSent , Vector3 currentDestination ,
PrinterMachineInstruction . MovementTypes movementMode )
{
double extruderDelta = 0 ;
GCodeFile . GetFirstNumberAfter ( "E" , lineBeingSent , ref extruderDelta ) ;
double feedRate = 0 ;
GCodeFile . GetFirstNumberAfter ( "F" , lineBeingSent , ref feedRate ) ;
StringBuilder newLine = new StringBuilder ( "G1 " ) ;
if ( lineBeingSent . Contains ( "X" ) | | lineBeingSent . Contains ( "Y" ) | | lineBeingSent . Contains ( "Z" ) )
{
Vector3 outPosition = GetPositionWithZOffset ( currentDestination ) ;
if ( movementMode = = PrinterMachineInstruction . MovementTypes . Relative )
2015-08-01 15:50:39 -07:00
{
2015-08-15 16:18:49 -07:00
Vector3 delta = outPosition - lastDestinationWithLevelingApplied ;
lastDestinationWithLevelingApplied = outPosition ;
2015-08-15 16:38:07 -07:00
outPosition = delta ;
2015-08-01 15:50:39 -07:00
}
2015-08-15 16:18:49 -07:00
else
2015-08-01 15:50:39 -07:00
{
2015-08-15 16:38:07 -07:00
lastDestinationWithLevelingApplied = outPosition ;
2015-08-01 15:50:39 -07:00
}
2015-08-15 16:18:49 -07:00
newLine = newLine . Append ( String . Format ( "X{0:0.##} Y{1:0.##} Z{2:0.###}" , outPosition . x , outPosition . y , outPosition . z ) ) ;
}
if ( extruderDelta ! = 0 )
{
newLine = newLine . Append ( String . Format ( " E{0:0.###}" , extruderDelta ) ) ;
}
if ( feedRate ! = 0 )
{
newLine = newLine . Append ( String . Format ( " F{0:0.##}" , feedRate ) ) ;
}
lineBeingSent = newLine . ToString ( ) ;
return lineBeingSent ;
}
}
public abstract class LevelWizardRadialBase : LevelWizardBase
{
protected string pageOneStepText = "Print Leveling Overview" . Localize ( ) ;
protected string pageOneInstructionsTextOne = LocalizedString . Get ( "Welcome to the print leveling wizard. Here is a quick overview on what we are going to do." ) ;
protected string pageOneInstructionsTextTwo = LocalizedString . Get ( "'Home' the printer" ) ;
protected string pageOneInstructionsTextThree = LocalizedString . Get ( "Sample the bed at seven points" ) ;
protected string pageOneInstructionsTextFour = LocalizedString . Get ( "Turn auto leveling on" ) ;
protected string pageOneInstructionsText5 = LocalizedString . Get ( "You should be done in about 5 minutes." ) ;
protected string pageOneInstructionsText6 = LocalizedString . Get ( "Note: Be sure the tip of the extrude is clean." ) ;
protected string pageOneInstructionsText7 = LocalizedString . Get ( "Click 'Next' to continue." ) ;
public LevelWizardRadialBase ( LevelWizardBase . RuningState runningState , int width , int height , int totalSteps , int numberOfRadialSamples )
: base ( width , height , totalSteps )
2015-08-01 15:50:39 -07:00
{
2015-08-15 16:18:49 -07:00
bool allowLessThanZero = ActiveSliceSettings . Instance . GetActiveValue ( "z_can_be_negative" ) = = "1" ;
string printLevelWizardTitle = LocalizedString . Get ( "MatterControl" ) ;
string printLevelWizardTitleFull = LocalizedString . Get ( "Print Leveling Wizard" ) ;
Title = string . Format ( "{0} - {1}" , printLevelWizardTitle , printLevelWizardTitleFull ) ;
ProbePosition [ ] probePositions = new ProbePosition [ numberOfRadialSamples + 1 ] ;
for ( int i = 0 ; i < probePositions . Length ; i + + )
{
probePositions [ i ] = new ProbePosition ( ) ;
}
printLevelWizard = new WizardControl ( ) ;
AddChild ( printLevelWizard ) ;
if ( runningState = = LevelWizardBase . RuningState . InitialStartupCalibration )
{
string requiredPageInstructions = "{0}\n\n{1}" . FormatWith ( requiredPageInstructions1 , requiredPageInstructions2 ) ;
printLevelWizard . AddPage ( new FirstPageInstructions ( initialPrinterSetupStepText , requiredPageInstructions ) ) ;
}
string pageOneInstructions = string . Format ( "{0}\n\n\t• {1}\n\t• {2}\n\t• {3}\n\n{4}\n\n{5}\n\n{6}" , pageOneInstructionsTextOne , pageOneInstructionsTextTwo , pageOneInstructionsTextThree , pageOneInstructionsTextFour , pageOneInstructionsText5 , pageOneInstructionsText6 , pageOneInstructionsText7 ) ;
printLevelWizard . AddPage ( new FirstPageInstructions ( pageOneStepText , pageOneInstructions ) ) ;
string homingPageInstructions = string . Format ( "{0}:\n\n\t• {1}\n\n{2}" , homingPageInstructionsTextOne , homingPageInstructionsTextTwo , homingPageInstructionsTextThree ) ;
printLevelWizard . AddPage ( new HomePrinterPage ( homingPageStepText , homingPageInstructions ) ) ;
string positionLabel = LocalizedString . Get ( "Position" ) ;
string lowPrecisionLabel = LocalizedString . Get ( "Low Precision" ) ;
string medPrecisionLabel = LocalizedString . Get ( "Medium Precision" ) ;
string highPrecisionLabel = LocalizedString . Get ( "High Precision" ) ;
double bedRadius = Math . Min ( ActiveSliceSettings . Instance . BedSize . x , ActiveSliceSettings . Instance . BedSize . y ) / 2 ;
double startProbeHeight = 5 ;
for ( int i = 0 ; i < numberOfRadialSamples + 1 ; i + + )
{
Vector2 probePosition = GetPrintLevelPositionToSample ( i , bedRadius ) ;
printLevelWizard . AddPage ( new GetCoarseBedHeight ( printLevelWizard , new Vector3 ( probePosition , startProbeHeight ) , string . Format ( "{0} {1} {2} - {3}" , GetStepString ( ) , positionLabel , i + 1 , lowPrecisionLabel ) , probePositions [ i ] , allowLessThanZero ) ) ;
printLevelWizard . AddPage ( new GetFineBedHeight ( string . Format ( "{0} {1} {2} - {3}" , GetStepString ( ) , positionLabel , i + 1 , medPrecisionLabel ) , probePositions [ i ] , allowLessThanZero ) ) ;
printLevelWizard . AddPage ( new GetUltraFineBedHeight ( string . Format ( "{0} {1} {2} - {3}" , GetStepString ( ) , positionLabel , i + 1 , highPrecisionLabel ) , probePositions [ i ] , allowLessThanZero ) ) ;
}
string doneInstructions = string . Format ( "{0}\n\n\t• {1}\n\n{2}" , doneInstructionsText , doneInstructionsTextTwo , doneInstructionsTextThree ) ;
printLevelWizard . AddPage ( new LastPageRadialInstructions ( "Done" . Localize ( ) , doneInstructions , probePositions ) ) ;
}
static RadialLevlingFunctions currentLevelingFunctions = null ;
public static RadialLevlingFunctions GetLevelingFunctions ( int numberOfRadialSamples , PrintLevelingData levelingData , Vector2 bedCenter )
{
if ( currentLevelingFunctions = = null
| | currentLevelingFunctions . NumberOfRadialSamples ! = numberOfRadialSamples
| | currentLevelingFunctions . BedCenter ! = bedCenter
| | currentLevelingFunctions . LevelingData ! = levelingData )
{
currentLevelingFunctions = new RadialLevlingFunctions ( numberOfRadialSamples , levelingData , bedCenter ) ;
}
return currentLevelingFunctions ;
}
public abstract Vector2 GetPrintLevelPositionToSample ( int index , double radius ) ;
}
public class LevelWizard7PointRadial : LevelWizardRadialBase
{
static readonly int numberOfRadialSamples = 6 ;
public LevelWizard7PointRadial ( LevelWizardBase . RuningState runningState )
: base ( runningState , 500 , 370 , 21 , numberOfRadialSamples )
2015-08-01 14:44:53 -07:00
{
}
2015-08-15 16:18:49 -07:00
public static string ApplyLeveling ( string lineBeingSent , Vector3 currentDestination , PrinterMachineInstruction . MovementTypes movementMode )
{
Printer activePrinter = PrinterConnectionAndCommunication . Instance . ActivePrinter ;
if ( activePrinter ! = null
& & activePrinter . DoPrintLeveling
& & ( lineBeingSent . StartsWith ( "G0 " ) | | lineBeingSent . StartsWith ( "G1 " ) )
& & lineBeingSent . Length > 2
& & lineBeingSent [ 2 ] = = ' ' )
{
PrintLevelingData levelingData = PrintLevelingData . GetForPrinter ( activePrinter ) ;
return GetLevelingFunctions ( numberOfRadialSamples , levelingData , ActiveSliceSettings . Instance . BedCenter )
. DoApplyLeveling ( lineBeingSent , currentDestination , movementMode ) ;
}
return lineBeingSent ;
}
public override Vector2 GetPrintLevelPositionToSample ( int index , double radius )
{
Printer activePrinter = PrinterConnectionAndCommunication . Instance . ActivePrinter ;
PrintLevelingData levelingData = PrintLevelingData . GetForPrinter ( activePrinter ) ;
return GetLevelingFunctions ( numberOfRadialSamples , levelingData , ActiveSliceSettings . Instance . BedCenter )
. GetPrintLevelPositionToSample ( index , radius ) ;
}
public static List < string > ProcessCommand ( string lineBeingSent )
{
int commentIndex = lineBeingSent . IndexOf ( ';' ) ;
if ( commentIndex > 0 ) // there is content in front of the ;
{
lineBeingSent = lineBeingSent . Substring ( 0 , commentIndex ) . Trim ( ) ;
}
List < string > lines = new List < string > ( ) ;
lines . Add ( lineBeingSent ) ;
if ( lineBeingSent . StartsWith ( "G28" ) )
{
lines . Add ( "M114" ) ;
}
return lines ;
}
2015-08-01 14:44:53 -07:00
}
}