| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- using System;
- using System.Globalization;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Media;
- using TeamAAS.Global.Devices;
- namespace TeamAAS.Motion
- {
- /// <summary>
- /// 运动卡通用调试页:轴选择 + 使能/回零/点动/定位/急停。
- /// 仿真卡与后续真实卡共用;绑定 <see cref="IMotionCard"/> 实例。
- /// </summary>
- public partial class MotionDebugView : UserControl
- {
- private IMotionCard _motion;
- private IAxis _selectedAxis;
- private bool _jogActive;
- private readonly System.Windows.Threading.DispatcherTimer _refreshTimer;
- public MotionDebugView()
- {
- InitializeComponent();
- _refreshTimer = new System.Windows.Threading.DispatcherTimer
- {
- Interval = TimeSpan.FromMilliseconds(200)
- };
- _refreshTimer.Tick += (_, __) => RefreshStatus();
- Unloaded += (_, __) => _refreshTimer.Stop();
- }
- public void Bind(object motion)
- {
- _motion = motion as IMotionCard;
- _selectedAxis = null;
- _jogActive = false;
- CmbAxis.ItemsSource = null;
- if (_motion == null)
- {
- OpsRoot.IsEnabled = false;
- _refreshTimer.Stop();
- TxtStatus.Text = "---";
- TxtMessage.Text = "未绑定运动卡";
- ClearAxisMetrics();
- SetConnDot(false);
- return;
- }
- var axes = _motion.GetAxes();
- CmbAxis.ItemsSource = axes;
- if (axes != null && axes.Count > 0)
- CmbAxis.SelectedIndex = 0;
- OpsRoot.IsEnabled = _motion.IsConnected;
- _refreshTimer.Start();
- RefreshStatus();
- }
- private IAxis CurrentAxis
- {
- get
- {
- if (_selectedAxis != null) return _selectedAxis;
- return CmbAxis.SelectedItem as IAxis;
- }
- }
- private void CmbAxis_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- _selectedAxis = CmbAxis.SelectedItem as IAxis;
- RefreshAxisInfo();
- }
- private double ParseDouble(TextBox box, double fallback)
- {
- return double.TryParse(box.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out var v)
- ? v
- : fallback;
- }
- private void Msg(string message) => TxtMessage.Text = message;
- private bool TryGetReadyAxis(out IAxis axis, string action)
- {
- axis = CurrentAxis;
- if (axis == null)
- {
- Msg("未选择轴");
- return false;
- }
- if (_motion == null || !_motion.IsConnected)
- {
- Msg("运动卡未连接");
- return false;
- }
- if (!axis.IsEnabled)
- {
- Msg($"轴未使能,无法{action}");
- return false;
- }
- return true;
- }
- private void RefreshStatus()
- {
- if (_motion == null)
- {
- TxtStatus.Text = "---";
- SetConnDot(false);
- ClearAxisMetrics();
- return;
- }
- try
- {
- var connected = _motion.IsConnected;
- TxtStatus.Text = connected ? "已连接" : "未连接";
- SetConnDot(connected);
- OpsRoot.IsEnabled = connected;
- RefreshAxisInfo();
- }
- catch { }
- }
- private void RefreshAxisInfo()
- {
- var axis = CurrentAxis;
- if (axis == null)
- {
- ClearAxisMetrics();
- return;
- }
- TxtAxisTitle.Text = $"{axis.Name} · 轴 {axis.AxisNo}";
- TxtPosActual.Text = axis.ActualPosition.ToString("F3");
- TxtPosCommand.Text = axis.CommandPosition.ToString("F3");
- TxtVelocity.Text = axis.ActualVelocity.ToString("F3");
- ApplyBanner(axis);
- SetTile(TileEnable, TxtEnable, axis.IsEnabled, "已使能", "未使能", "#2E7D32", "#C62828");
- SetTile(TileMoving, TxtMoving, axis.IsMoving, "运动中", "静止", "#EF6C00", "#757575");
- SetTile(TileHomed, TxtHomed, axis.IsHomed, "已回零", "未回零", "#1565C0", "#757575");
- var enabled = axis.IsEnabled;
- BtnEnable.IsEnabled = !enabled;
- BtnDisable.IsEnabled = enabled;
- BtnStop.IsEnabled = axis.IsMoving;
- MotionOps.IsEnabled = enabled;
- TxtNeedEnable.Visibility = enabled ? Visibility.Collapsed : Visibility.Visible;
- }
- private void ApplyBanner(IAxis axis)
- {
- string headline;
- string hint;
- string color;
- if (_motion == null || !_motion.IsConnected)
- {
- headline = "未连接";
- hint = "请先在上方连接控制卡";
- color = "#616161";
- }
- else if (axis.State == AxisState.Error)
- {
- headline = "轴故障";
- hint = "请检查报警后重新使能";
- color = "#B71C1C";
- }
- else if (!axis.IsEnabled || axis.State == AxisState.Off)
- {
- headline = "伺服未使能";
- hint = "当前无法运动,请先点击右侧「使能」";
- color = "#C62828";
- }
- else if (axis.State == AxisState.Homing)
- {
- headline = "正在回零";
- hint = "回零过程中请勿点动或定位";
- color = "#1565C0";
- }
- else if (axis.State == AxisState.ContinuousMotion || (axis.IsMoving && _jogActive))
- {
- headline = "点动中";
- hint = "松开按钮或点击「停止」即可停下";
- color = "#EF6C00";
- }
- else if (axis.State == AxisState.DiscreteMotion || axis.IsMoving)
- {
- headline = "定位运动中";
- hint = "可点击「停止」或「急停」中断";
- color = "#EF6C00";
- }
- else
- {
- headline = axis.IsHomed ? "已使能 · 静止" : "已使能 · 未回零";
- hint = axis.IsHomed ? "可以点动或定位" : "建议先回零,再做定位";
- color = "#2E7D32";
- }
- TxtStateHeadline.Text = headline;
- TxtStateHint.Text = hint;
- BannerState.Background = BrushOf(color);
- }
- private void ClearAxisMetrics()
- {
- TxtAxisTitle.Text = "---";
- TxtPosActual.Text = "---";
- TxtPosCommand.Text = "---";
- TxtVelocity.Text = "---";
- TxtStateHeadline.Text = _motion == null ? "未绑定运动卡" : (_motion.IsConnected ? "未选择轴" : "未连接");
- TxtStateHint.Text = "请选择轴并连接控制卡";
- BannerState.Background = BrushOf("#616161");
- SetTile(TileEnable, TxtEnable, false, "已使能", "未使能", "#2E7D32", "#757575");
- SetTile(TileMoving, TxtMoving, false, "运动中", "静止", "#EF6C00", "#757575");
- SetTile(TileHomed, TxtHomed, false, "已回零", "未回零", "#1565C0", "#757575");
- BtnEnable.IsEnabled = false;
- BtnDisable.IsEnabled = false;
- BtnStop.IsEnabled = false;
- MotionOps.IsEnabled = false;
- TxtNeedEnable.Visibility = Visibility.Collapsed;
- }
- private static void SetTile(Border tile, TextBlock label, bool on, string onText, string offText, string onColor, string offColor)
- {
- label.Text = on ? onText : offText;
- tile.Background = BrushOf(on ? onColor : offColor);
- }
- private static SolidColorBrush BrushOf(string hex)
- => new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
- private void SetConnDot(bool connected)
- {
- DotConn.Fill = BrushOf(connected ? "#43A047" : "#9E9E9E");
- }
- private void BtnEnable_Click(object sender, RoutedEventArgs e)
- {
- var axis = CurrentAxis;
- if (axis == null) { Msg("未选择轴"); return; }
- try
- {
- axis.Enable();
- Msg("已使能");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("使能失败: " + ex.Message); }
- }
- private void BtnDisable_Click(object sender, RoutedEventArgs e)
- {
- var axis = CurrentAxis;
- if (axis == null) { Msg("未选择轴"); return; }
- try
- {
- StopJogIfActive();
- axis.Disable();
- Msg("已下使能");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("下使能失败: " + ex.Message); }
- }
- private void BtnHome_Click(object sender, RoutedEventArgs e)
- {
- if (!TryGetReadyAxis(out var axis, "回零")) return;
- try
- {
- StopJogIfActive();
- axis.Home();
- Msg("回零完成");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("回零失败: " + ex.Message); }
- }
- private void BtnStop_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- StopJogIfActive();
- CurrentAxis?.Stop();
- Msg("已停止");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("停止失败: " + ex.Message); }
- }
- private void BtnEStop_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- _jogActive = false;
- _motion?.EmergencyStop();
- Msg("急停已触发");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("急停失败: " + ex.Message); }
- }
- private void BtnJog_Down(object sender, MouseButtonEventArgs e)
- {
- if (!TryGetReadyAxis(out var axis, "点动")) return;
- var btn = sender as UIElement;
- var tag = (sender as Button)?.Tag as string;
- double vel = ParseDouble(TxtJogVel, 50);
- if (tag == "-") vel = -vel;
- try
- {
- axis.Jog(vel);
- _jogActive = true;
- btn?.CaptureMouse();
- Msg($"点动 {tag} 速度 {vel:F1}");
- }
- catch (Exception ex) { Msg("点动失败: " + ex.Message); }
- }
- private void BtnJog_Up(object sender, MouseButtonEventArgs e)
- {
- var btn = sender as UIElement;
- if (btn != null && btn.IsMouseCaptured)
- btn.ReleaseMouseCapture();
- else
- StopJogIfActive();
- }
- private void BtnJog_LostCapture(object sender, MouseEventArgs e)
- {
- StopJogIfActive();
- }
- private void StopJogIfActive()
- {
- if (!_jogActive) return;
- _jogActive = false;
- try
- {
- CurrentAxis?.Stop();
- Msg("点动停止");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("停止失败: " + ex.Message); }
- }
- private void BtnMoveAbs_Click(object sender, RoutedEventArgs e)
- {
- if (!TryGetReadyAxis(out var axis, "定位")) return;
- try
- {
- var target = ParseDouble(TxtTargetPos, 0);
- axis.Velocity = ParseDouble(TxtMoveVel, 100);
- axis.MoveTo(target);
- Msg($"绝对定位 → {target:F3}");
- }
- catch (Exception ex) { Msg("绝对定位失败: " + ex.Message); }
- }
- private void BtnMoveRel_Click(object sender, RoutedEventArgs e)
- {
- if (!TryGetReadyAxis(out var axis, "定位")) return;
- try
- {
- var dist = ParseDouble(TxtRelativeDist, 10);
- axis.Velocity = ParseDouble(TxtMoveVel, 100);
- axis.MoveBy(dist);
- Msg($"相对定位 {dist:F3}");
- }
- catch (Exception ex) { Msg("相对定位失败: " + ex.Message); }
- }
- private void BtnSetZero_Click(object sender, RoutedEventArgs e)
- {
- var axis = CurrentAxis;
- if (axis == null) { Msg("未选择轴"); return; }
- try
- {
- axis.SetPosition(0);
- Msg("当前位置已清零");
- RefreshAxisInfo();
- }
- catch (Exception ex) { Msg("清零失败: " + ex.Message); }
- }
- }
- /// <summary>运动卡通用调试页工厂。</summary>
- public class MotionDebugPageFactory : TeamAAS.Global.Devices.IDeviceDebugPageFactory
- {
- public string DeviceCategory => "运动卡";
- public object CreatePage(object device)
- {
- var view = new MotionDebugView();
- view.Bind(device);
- return view;
- }
- }
- }
|