685 lines
24 KiB
C#
685 lines
24 KiB
C#
|
|
using MainShell.Common;
|
|||
|
|
using MainShell.Filewritable;
|
|||
|
|
using MainShell.Hardware;
|
|||
|
|
using MainShell.Log;
|
|||
|
|
using MainShell.Models;
|
|||
|
|
using MainShell.Recipe.Models;
|
|||
|
|
using MainShell.Recipe.Models.PID;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Collections.ObjectModel;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Reflection;
|
|||
|
|
using StyletIoC;
|
|||
|
|
|
|||
|
|
namespace MainShell.Recipe.ViewModel
|
|||
|
|
{
|
|||
|
|
public class ProcessRecipeViewModel : RecipeViewModelBase<ProcessRecipe>
|
|||
|
|
{
|
|||
|
|
private readonly HardwareManager _hardwareManager;
|
|||
|
|
private readonly PIDOperater _pidOperater;
|
|||
|
|
|
|||
|
|
private static readonly string[] _fixedProfileNames = new string[]
|
|||
|
|
{
|
|||
|
|
"默认PID组"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
private static readonly string[] _fixedCompensationAxisNames = new string[]
|
|||
|
|
{
|
|||
|
|
"PHS-X1",
|
|||
|
|
"PHS-Y1",
|
|||
|
|
"WS-X",
|
|||
|
|
"Stage-Y"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
private ProcessRecipe _processRecipe;
|
|||
|
|
public ProcessRecipe ProcessRecipe
|
|||
|
|
{
|
|||
|
|
get { return _processRecipe; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (SetAndNotify(ref _processRecipe, value))
|
|||
|
|
{
|
|||
|
|
if (ProcessCompensationViewModel != null)
|
|||
|
|
{
|
|||
|
|
ProcessCompensationViewModel.ProcessRecipe = value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProcessRecipeState();
|
|||
|
|
SyncProfileSelection();
|
|||
|
|
NotifyOfPropertyChange(() => AxisPIDParameters);
|
|||
|
|
NotifyOfPropertyChange(() => AxisOptions);
|
|||
|
|
NotifyOfPropertyChange(() => SelectedAxes);
|
|||
|
|
NotifyOfPropertyChange(() => SelectedFilteringParameters);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override ProcessRecipe CurrentRecipe
|
|||
|
|
{
|
|||
|
|
get { return ProcessRecipe; }
|
|||
|
|
set { ProcessRecipe = value; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override string RecipeFolderPath => Paths.ProcessRecipe;
|
|||
|
|
protected override string EmptyRecipeDisplayName => "当前工艺配方";
|
|||
|
|
|
|||
|
|
protected override string GetActiveRecipeName()
|
|||
|
|
{
|
|||
|
|
return RecipeManager.CurrentProcessRecipe != null ? RecipeManager.CurrentProcessRecipe.RecipeName : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ObservableCollection<PIDProfile> AxisPIDParameters => ProcessRecipe != null ? ProcessRecipe.AxisPIDParameters : null;
|
|||
|
|
|
|||
|
|
private PIDProfile _selectedPIDProfile;
|
|||
|
|
public PIDProfile SelectedPIDProfile
|
|||
|
|
{
|
|||
|
|
get { return _selectedPIDProfile; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (SetAndNotify(ref _selectedPIDProfile, value))
|
|||
|
|
{
|
|||
|
|
EnsureProfileState(_selectedPIDProfile);
|
|||
|
|
NotifyOfPropertyChange(() => SelectedAxes);
|
|||
|
|
NotifyOfPropertyChange(() => SelectedFilteringParameters);
|
|||
|
|
SyncFilteringSelection();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ObservableCollection<AxisPIDParameter> SelectedAxes => SelectedPIDProfile != null ? SelectedPIDProfile.Axes : null;
|
|||
|
|
|
|||
|
|
public ObservableCollection<AxisFilteringParameter> SelectedFilteringParameters => SelectedPIDProfile != null ? SelectedPIDProfile.FilteringParameters : null;
|
|||
|
|
|
|||
|
|
private ObservableCollection<PidAxisOption> _axisOptions = new ObservableCollection<PidAxisOption>();
|
|||
|
|
public ObservableCollection<PidAxisOption> AxisOptions
|
|||
|
|
{
|
|||
|
|
get { return _axisOptions; }
|
|||
|
|
set { SetAndNotify(ref _axisOptions, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private AxisPIDParameter _selectedAxisParameter;
|
|||
|
|
public AxisPIDParameter SelectedAxisParameter
|
|||
|
|
{
|
|||
|
|
get { return _selectedAxisParameter; }
|
|||
|
|
set { SetAndNotify(ref _selectedAxisParameter, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private AxisFilteringParameter _selectedFilteringParameter;
|
|||
|
|
public AxisFilteringParameter SelectedFilteringParameter
|
|||
|
|
{
|
|||
|
|
get { return _selectedFilteringParameter; }
|
|||
|
|
set { SetAndNotify(ref _selectedFilteringParameter, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private AxisFilteringParameter _selectedNotchFilteringParameter;
|
|||
|
|
public AxisFilteringParameter SelectedNotchFilteringParameter
|
|||
|
|
{
|
|||
|
|
get { return _selectedNotchFilteringParameter; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (SetAndNotify(ref _selectedNotchFilteringParameter, value) && value != null)
|
|||
|
|
{
|
|||
|
|
SelectedFilteringParameter = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private AxisFilteringParameter _selectedLowPassFilteringParameter;
|
|||
|
|
public AxisFilteringParameter SelectedLowPassFilteringParameter
|
|||
|
|
{
|
|||
|
|
get { return _selectedLowPassFilteringParameter; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (SetAndNotify(ref _selectedLowPassFilteringParameter, value) && value != null)
|
|||
|
|
{
|
|||
|
|
SelectedFilteringParameter = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private int _selectedParameterTabIndex;
|
|||
|
|
public int SelectedParameterTabIndex
|
|||
|
|
{
|
|||
|
|
get { return _selectedParameterTabIndex; }
|
|||
|
|
set { SetAndNotify(ref _selectedParameterTabIndex, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private ProcessCompensationViewModel _processCompensationViewModel;
|
|||
|
|
[Inject]
|
|||
|
|
public ProcessCompensationViewModel ProcessCompensationViewModel
|
|||
|
|
{
|
|||
|
|
get { return _processCompensationViewModel; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (SetAndNotify(ref _processCompensationViewModel, value) && value != null)
|
|||
|
|
{
|
|||
|
|
value.ProcessRecipe = ProcessRecipe;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ProcessRecipeViewModel(RecipeWrapManager wrapManager, RecipeManager recipeManager, HardwareManager hardwareManager, PIDOperater pidOperater)
|
|||
|
|
: base(recipeManager)
|
|||
|
|
{
|
|||
|
|
_hardwareManager = hardwareManager;
|
|||
|
|
_pidOperater = pidOperater;
|
|||
|
|
RecipeWraps = wrapManager.ProcessRecipeWraps;
|
|||
|
|
RegisterButtonGroupEvents();
|
|||
|
|
AxisOptions = BuildAxisOptions();
|
|||
|
|
PidAxisCatalog.SetAxisOptions(AxisOptions);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void OnViewLoaded()
|
|||
|
|
{
|
|||
|
|
base.OnViewLoaded();
|
|||
|
|
|
|||
|
|
AxisOptions = BuildAxisOptions();
|
|||
|
|
PidAxisCatalog.SetAxisOptions(AxisOptions);
|
|||
|
|
InitializeSelection(RecipeManager.CurrentProcessRecipe != null ? RecipeManager.CurrentProcessRecipe.RecipeName : null);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void SwitchActiveRecipe(string recipeName)
|
|||
|
|
{
|
|||
|
|
RecipeManager.SwitchProcessRecipe(recipeName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void ClearActiveRecipe()
|
|||
|
|
{
|
|||
|
|
RecipeManager.ClearProcessRecipe();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override void OnRecipeLoaded(ProcessRecipe recipe, RecipeWrap recipeWrap)
|
|||
|
|
{
|
|||
|
|
EnsureProcessRecipeState();
|
|||
|
|
SyncProfileSelection();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void OnCopyRecipe(object sender, EventArgs eventArgs)
|
|||
|
|
{
|
|||
|
|
base.OnCopyRecipe(sender, eventArgs);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void OnImportRecipe(object sender, EventArgs eventArgs)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void OnExportRecipe(object sender, EventArgs eventArgs)
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void OnReNameRecipe(object sender, EventArgs eventArgs)
|
|||
|
|
{
|
|||
|
|
RecipeRenameEventArgs args = eventArgs as RecipeRenameEventArgs;
|
|||
|
|
if (args != null)
|
|||
|
|
{
|
|||
|
|
TryRenameRecipe(args);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void AddAxis()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null)
|
|||
|
|
{
|
|||
|
|
MwMessageBox.Show("请先选择一个 PID 配置组");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProfileState(SelectedPIDProfile);
|
|||
|
|
|
|||
|
|
PidAxisOption axisOption = GetNextAxisOption(SelectedPIDProfile.Axes.Select(item => item.AxisIndex));
|
|||
|
|
AxisPIDParameter axis = new AxisPIDParameter();
|
|||
|
|
if (axisOption != null)
|
|||
|
|
{
|
|||
|
|
axis.ModuleName = axisOption.AxisName;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
axis.ModuleName = string.Format("Axis{0}", SelectedPIDProfile.Axes.Count + 1);
|
|||
|
|
axis.AxisIndex = SelectedPIDProfile.Axes.Count;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SelectedPIDProfile.Axes.Add(axis);
|
|||
|
|
SelectedAxisParameter = axis;
|
|||
|
|
NotifyOfPropertyChange(() => SelectedAxes);
|
|||
|
|
NotifyOfPropertyChange(() => HasUnsavedChanges);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void DeleteAxis()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null || SelectedAxisParameter == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProfileState(SelectedPIDProfile);
|
|||
|
|
|
|||
|
|
int index = SelectedPIDProfile.Axes.IndexOf(SelectedAxisParameter);
|
|||
|
|
SelectedPIDProfile.Axes.Remove(SelectedAxisParameter);
|
|||
|
|
SelectedAxisParameter = SelectedPIDProfile.Axes.Count == 0
|
|||
|
|
? null
|
|||
|
|
: SelectedPIDProfile.Axes[Math.Min(index, SelectedPIDProfile.Axes.Count - 1)];
|
|||
|
|
NotifyOfPropertyChange(() => SelectedAxes);
|
|||
|
|
NotifyOfPropertyChange(() => HasUnsavedChanges);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void AddFilteringParameter()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null)
|
|||
|
|
{
|
|||
|
|
MwMessageBox.Show("请先选择一个 PID 配置组");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProfileState(SelectedPIDProfile);
|
|||
|
|
|
|||
|
|
PidAxisOption axisOption = GetNextAxisOption(SelectedPIDProfile.FilteringParameters.Select(item => item.AxisIndex));
|
|||
|
|
AxisFilteringParameter filteringParameter = new AxisFilteringParameter
|
|||
|
|
{
|
|||
|
|
AxisIndex = axisOption != null ? axisOption.AxisIndex : GetDefaultAxisIndex()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SelectedPIDProfile.FilteringParameters.Add(filteringParameter);
|
|||
|
|
SelectedFilteringParameter = filteringParameter;
|
|||
|
|
NotifyOfPropertyChange(() => SelectedFilteringParameters);
|
|||
|
|
NotifyOfPropertyChange(() => HasUnsavedChanges);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void ReadParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null)
|
|||
|
|
{
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidNoProfileSelected, MessageKey.TitleWarning);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (SelectedParameterTabIndex == 1)
|
|||
|
|
{
|
|||
|
|
ReadFilteringParameters();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ReadPidAxisParameters();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
NotifyOfPropertyChange(() => SelectedAxes);
|
|||
|
|
NotifyOfPropertyChange(() => SelectedFilteringParameters);
|
|||
|
|
NotifyOfPropertyChange(() => HasUnsavedChanges);
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidReadSucceeded, MessageKey.TitleInfo);
|
|||
|
|
}
|
|||
|
|
catch (Exception exception)
|
|||
|
|
{
|
|||
|
|
$"PID参数读取失败: {exception}".LogSysError();
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidReadFailed, MessageKey.TitleError);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void WriteParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null)
|
|||
|
|
{
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidNoProfileSelected, MessageKey.TitleWarning);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (SelectedParameterTabIndex == 1)
|
|||
|
|
{
|
|||
|
|
WriteFilteringParameters();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
WritePidAxisParameters();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidWriteSucceeded, MessageKey.TitleInfo);
|
|||
|
|
}
|
|||
|
|
catch (Exception exception)
|
|||
|
|
{
|
|||
|
|
$"PID参数写入失败: {exception}".LogSysError();
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidWriteFailed, MessageKey.TitleError);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void DeleteFilteringParameter()
|
|||
|
|
{
|
|||
|
|
if (SelectedPIDProfile == null || SelectedFilteringParameter == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProfileState(SelectedPIDProfile);
|
|||
|
|
|
|||
|
|
int index = SelectedPIDProfile.FilteringParameters.IndexOf(SelectedFilteringParameter);
|
|||
|
|
SelectedPIDProfile.FilteringParameters.Remove(SelectedFilteringParameter);
|
|||
|
|
SelectedFilteringParameter = SelectedPIDProfile.FilteringParameters.Count == 0
|
|||
|
|
? null
|
|||
|
|
: SelectedPIDProfile.FilteringParameters[Math.Min(index, SelectedPIDProfile.FilteringParameters.Count - 1)];
|
|||
|
|
NotifyOfPropertyChange(() => SelectedFilteringParameters);
|
|||
|
|
NotifyOfPropertyChange(() => HasUnsavedChanges);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void EnsureProcessRecipeState()
|
|||
|
|
{
|
|||
|
|
if (ProcessRecipe == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ProcessRecipe.AxisPIDParameters == null)
|
|||
|
|
{
|
|||
|
|
ProcessRecipe.AxisPIDParameters = new ObservableCollection<PIDProfile>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ProcessRecipe.ProcessCompensationParameters == null)
|
|||
|
|
{
|
|||
|
|
ProcessRecipe.ProcessCompensationParameters = new ObservableCollection<ProcessAxisCompensationParameter>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureFixedProfiles();
|
|||
|
|
EnsureFixedCompensationParameters();
|
|||
|
|
|
|||
|
|
foreach (PIDProfile profile in ProcessRecipe.AxisPIDParameters)
|
|||
|
|
{
|
|||
|
|
EnsureProfileState(profile);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SyncProfileSelection()
|
|||
|
|
{
|
|||
|
|
if (AxisPIDParameters == null || AxisPIDParameters.Count == 0)
|
|||
|
|
{
|
|||
|
|
SelectedPIDProfile = null;
|
|||
|
|
SelectedAxisParameter = null;
|
|||
|
|
SelectedFilteringParameter = null;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SelectedPIDProfile == null || !AxisPIDParameters.Contains(SelectedPIDProfile))
|
|||
|
|
{
|
|||
|
|
SelectedPIDProfile = AxisPIDParameters[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
EnsureProfileState(SelectedPIDProfile);
|
|||
|
|
|
|||
|
|
if (SelectedAxes == null || SelectedAxes.Count == 0)
|
|||
|
|
{
|
|||
|
|
SelectedAxisParameter = null;
|
|||
|
|
}
|
|||
|
|
else if (SelectedAxisParameter == null || !SelectedAxes.Contains(SelectedAxisParameter))
|
|||
|
|
{
|
|||
|
|
SelectedAxisParameter = SelectedAxes[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SyncFilteringSelection();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void EnsureProfileState(PIDProfile profile)
|
|||
|
|
{
|
|||
|
|
if (profile == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
profile.EnsureAxes();
|
|||
|
|
|
|||
|
|
if (profile.FilteringParameters == null)
|
|||
|
|
{
|
|||
|
|
profile.FilteringParameters = new ObservableCollection<AxisFilteringParameter>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (profile.FilteringParameters.Count == 0)
|
|||
|
|
{
|
|||
|
|
AxisFilteringParameter filteringParameter = new AxisFilteringParameter();
|
|||
|
|
filteringParameter.AxisIndex = GetDefaultAxisIndex();
|
|||
|
|
profile.FilteringParameters.Add(filteringParameter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SyncFilteringSelection()
|
|||
|
|
{
|
|||
|
|
if (SelectedFilteringParameters == null || SelectedFilteringParameters.Count == 0)
|
|||
|
|
{
|
|||
|
|
SelectedFilteringParameter = null;
|
|||
|
|
SelectedNotchFilteringParameter = null;
|
|||
|
|
SelectedLowPassFilteringParameter = null;
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SelectedFilteringParameter == null || !SelectedFilteringParameters.Contains(SelectedFilteringParameter))
|
|||
|
|
{
|
|||
|
|
SelectedFilteringParameter = SelectedFilteringParameters[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SelectedNotchFilteringParameter == null || !SelectedFilteringParameters.Contains(SelectedNotchFilteringParameter))
|
|||
|
|
{
|
|||
|
|
SelectedNotchFilteringParameter = SelectedFilteringParameter;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (SelectedLowPassFilteringParameter == null || !SelectedFilteringParameters.Contains(SelectedLowPassFilteringParameter))
|
|||
|
|
{
|
|||
|
|
SelectedLowPassFilteringParameter = SelectedFilteringParameter;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void EnsureFixedProfiles()
|
|||
|
|
{
|
|||
|
|
foreach (string profileName in _fixedProfileNames)
|
|||
|
|
{
|
|||
|
|
PIDProfile profile = AxisPIDParameters.FirstOrDefault(item => string.Equals(item.Name, profileName, StringComparison.OrdinalIgnoreCase));
|
|||
|
|
if (profile == null)
|
|||
|
|
{
|
|||
|
|
profile = new PIDProfile(profileName);
|
|||
|
|
profile.Description = "程序初始化固定配置组";
|
|||
|
|
AxisPIDParameters.Add(profile);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void EnsureFixedCompensationParameters()
|
|||
|
|
{
|
|||
|
|
foreach (string axisName in _fixedCompensationAxisNames)
|
|||
|
|
{
|
|||
|
|
ProcessAxisCompensationParameter parameter = ProcessRecipe.ProcessCompensationParameters
|
|||
|
|
.FirstOrDefault(item => string.Equals(item.AxisName, axisName, StringComparison.OrdinalIgnoreCase));
|
|||
|
|
|
|||
|
|
if (parameter == null)
|
|||
|
|
{
|
|||
|
|
parameter = new ProcessAxisCompensationParameter();
|
|||
|
|
parameter.AxisName = axisName;
|
|||
|
|
parameter.CompensationValue = 0d;
|
|||
|
|
ProcessRecipe.ProcessCompensationParameters.Add(parameter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ReadPidAxisParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedAxes == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (AxisPIDParameter axisParameter in SelectedAxes)
|
|||
|
|
{
|
|||
|
|
AxisPIDParameter deviceParameter = _pidOperater.ReadPIDParametersFromDevice(axisParameter.ModuleName);
|
|||
|
|
CopyAxisParameterValues(deviceParameter, axisParameter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void WritePidAxisParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedAxes == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (AxisPIDParameter axisParameter in SelectedAxes)
|
|||
|
|
{
|
|||
|
|
_pidOperater.SendPIDParameters(axisParameter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ReadFilteringParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedFilteringParameter == null)
|
|||
|
|
{
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidNoFilteringParameterSelected, MessageKey.TitleWarning);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AxisFilteringParameter deviceParameter = _pidOperater.ReadPIDFilteringParametersFromDevice();
|
|||
|
|
CopyFilteringParameterValues(deviceParameter, SelectedFilteringParameter);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void WriteFilteringParameters()
|
|||
|
|
{
|
|||
|
|
if (SelectedFilteringParameter == null)
|
|||
|
|
{
|
|||
|
|
LocalizedMessageBox.Show(MessageKey.PidNoFilteringParameterSelected, MessageKey.TitleWarning);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_pidOperater.SendPIDFilteringParameters(SelectedFilteringParameter);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CopyAxisParameterValues(AxisPIDParameter source, AxisPIDParameter target)
|
|||
|
|
{
|
|||
|
|
if (source == null || target == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
target.PA_SLVKP.Value = source.PA_SLVKP.Value;
|
|||
|
|
target.PA_SLVKI.Value = source.PA_SLVKI.Value;
|
|||
|
|
target.PA_SLVKPSF.Value = source.PA_SLVKPSF.Value;
|
|||
|
|
target.PA_SLVKPIF.Value = source.PA_SLVKPIF.Value;
|
|||
|
|
target.PA_SLVKISF.Value = source.PA_SLVKISF.Value;
|
|||
|
|
target.PA_SLVKIIF.Value = source.PA_SLVKIIF.Value;
|
|||
|
|
target.PA_SLPKP.Value = source.PA_SLPKP.Value;
|
|||
|
|
target.PA_SLPKPIF.Value = source.PA_SLPKPIF.Value;
|
|||
|
|
target.PA_SLPKPSF.Value = source.PA_SLPKPSF.Value;
|
|||
|
|
target.PA_SLAFF.Value = source.PA_SLAFF.Value;
|
|||
|
|
target.PA_SLJFF.Value = source.PA_SLJFF.Value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CopyFilteringParameterValues(AxisFilteringParameter source, AxisFilteringParameter target)
|
|||
|
|
{
|
|||
|
|
if (source == null || target == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
target.IsUseNotch.Value = source.IsUseNotch.Value;
|
|||
|
|
target.NotchFrequency.Value = source.NotchFrequency.Value;
|
|||
|
|
target.NotchWidth.Value = source.NotchWidth.Value;
|
|||
|
|
target.NotchFalloff.Value = source.NotchFalloff.Value;
|
|||
|
|
target.IsUseFiltering.Value = source.IsUseFiltering.Value;
|
|||
|
|
target.FilteringFrequency.Value = source.FilteringFrequency.Value;
|
|||
|
|
target.FilteringDamping.Value = source.FilteringDamping.Value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private PidAxisOption GetNextAxisOption(IEnumerable<int> usedAxisIndices)
|
|||
|
|
{
|
|||
|
|
if (AxisOptions == null || AxisOptions.Count == 0)
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
HashSet<int> usedAxisSet = new HashSet<int>();
|
|||
|
|
if (usedAxisIndices != null)
|
|||
|
|
{
|
|||
|
|
foreach (int axisIndex in usedAxisIndices)
|
|||
|
|
{
|
|||
|
|
usedAxisSet.Add(axisIndex);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (PidAxisOption axisOption in AxisOptions)
|
|||
|
|
{
|
|||
|
|
if (!usedAxisSet.Contains(axisOption.AxisIndex))
|
|||
|
|
{
|
|||
|
|
return axisOption;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return AxisOptions[0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private int GetDefaultAxisIndex()
|
|||
|
|
{
|
|||
|
|
if (AxisOptions == null || AxisOptions.Count == 0)
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return AxisOptions[0].AxisIndex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private ObservableCollection<PidAxisOption> BuildAxisOptions()
|
|||
|
|
{
|
|||
|
|
ObservableCollection<PidAxisOption> axisOptions = new ObservableCollection<PidAxisOption>();
|
|||
|
|
|
|||
|
|
if (_hardwareManager != null && _hardwareManager.AxesDic != null && _hardwareManager.AxesDic.Count > 0)
|
|||
|
|
{
|
|||
|
|
int order = 0;
|
|||
|
|
foreach (string axisName in _hardwareManager.AxesDic.Keys.OrderBy(item => item))
|
|||
|
|
{
|
|||
|
|
axisOptions.Add(new PidAxisOption
|
|||
|
|
{
|
|||
|
|
AxisName = axisName,
|
|||
|
|
AxisIndex = ExtractAxisIndex(axisName, order)
|
|||
|
|
});
|
|||
|
|
order++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (axisOptions.Count > 0)
|
|||
|
|
{
|
|||
|
|
return axisOptions;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
FieldInfo[] fields = typeof(AxisName).GetFields(BindingFlags.Public | BindingFlags.Static);
|
|||
|
|
int fallbackOrder = 0;
|
|||
|
|
foreach (FieldInfo fieldInfo in fields.OrderBy(item => item.Name))
|
|||
|
|
{
|
|||
|
|
object value = fieldInfo.GetValue(null);
|
|||
|
|
string axisName = value as string;
|
|||
|
|
if (string.IsNullOrWhiteSpace(axisName))
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
axisOptions.Add(new PidAxisOption
|
|||
|
|
{
|
|||
|
|
AxisName = axisName,
|
|||
|
|
AxisIndex = ExtractAxisIndex(axisName, fallbackOrder)
|
|||
|
|
});
|
|||
|
|
fallbackOrder++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return axisOptions;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private int ExtractAxisIndex(string axisName, int fallbackValue)
|
|||
|
|
{
|
|||
|
|
if (string.IsNullOrWhiteSpace(axisName))
|
|||
|
|
{
|
|||
|
|
return fallbackValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
string digits = new string(axisName.Reverse().TakeWhile(char.IsDigit).Reverse().ToArray());
|
|||
|
|
int axisIndex;
|
|||
|
|
if (int.TryParse(digits, out axisIndex))
|
|||
|
|
{
|
|||
|
|
return axisIndex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return fallbackValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|