干翻全岛蛙蛙 发表于 2023-2-3 10:36:43

WPF开发经验-实现一种三轴机械手控件

一 引入

https://img2023.cnblogs.com/blog/2393052/202301/2393052-20230130164537945-1364671364.gif
 
考虑实现一种三轴机器人控件。
三轴机器人用来将某种工件从一个位置运送到另一个位置。
其X轴为手臂轴,可以正向和反向运动,它处于末端,直接接触工件;
其T轴为旋转轴,可以对手臂进行旋转;
其Z轴为升降轴,可以对手臂和旋转部分进行升降。
 
二 RobotControl

定义出机器人的轴动作枚举,轴的动作分为回原点,正向运动,反向运动。
public enum WaferRobotZAction
{
    Z_Origin,
    Z_CW,
    Z_CCW
}

public enum WaferRobotXAction
{
    X_Origin,
    X_CW,
    X_CCW
}

public enum WaferRobotTAction
{
    T_Origin,
    T_CW,
    T_CCW
}声明一个WaferRobotControl的自定义控件,它继承自Control类。
定义一个Wafer属性来表示WaferRobot上的工件。
定义表示X轴动作、T轴动作和Z轴动作的依赖属性,它可以被实际的业务数据源绑定。
当实际的业务数据发生改变时,轴动作属性相应改变,并VisualStateManager来转换控件的状态,以触发样式模板中的动画。
public class WaferRobotControl : Control
{
    static WaferRobotControl()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(WaferRobotControl), new FrameworkPropertyMetadata(typeof(WaferRobotControl)));
    }

    public static readonly DependencyProperty WaferProperty = DependencyProperty.Register("Wafer", typeof(int), typeof(WaferRobotControl));
    public int Wafer { get => (int)GetValue(WaferProperty); set => SetValue(WaferProperty, value); }

    public static readonly DependencyProperty RobotZActionProperty = DependencyProperty.Register(
       "RobotZAction",
       typeof(WaferRobotZAction),
       typeof(WaferRobotControl),
       new PropertyMetadata(WaferRobotZAction.Z_Origin, RobotZActionPropertyChangedCallback));

    public WaferRobotZAction RobotZAction
    {
      get => (WaferRobotZAction)GetValue(RobotZActionProperty);
      set => SetValue(RobotZActionProperty, value);
    }

    private static void RobotZActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var control = d as WaferRobotControl;
      var oldAct = (WaferRobotZAction)e.OldValue;
      var newAct = (WaferRobotZAction)e.NewValue;
      switch (newAct)
      {
            case WaferRobotZAction.Z_Origin:
                VisualStateManager.GoToState(control, newAct.ToString(), true);
                break;
            case WaferRobotZAction.Z_CW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            case WaferRobotZAction.Z_CCW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            default:
                break;
      }
    }

    public static readonly DependencyProperty RobotXActionProperty = DependencyProperty.Register(
      "RobotXAction",
      typeof(WaferRobotXAction),
      typeof(WaferRobotControl),
      new PropertyMetadata(WaferRobotXAction.X_Origin, RobotXActionPropertyChangedCallback));
    public WaferRobotXAction RobotXAction
    {
      get => (WaferRobotXAction)GetValue(RobotXActionProperty);
      set => SetValue(RobotXActionProperty, value);
    }

    private static void RobotXActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var control = d as WaferRobotControl;
      var oldAct = (WaferRobotXAction)e.OldValue;
      var newAct = (WaferRobotXAction)e.NewValue;
      switch (newAct)
      {
            case WaferRobotXAction.X_Origin:
                VisualStateManager.GoToState(control, newAct.ToString(), true);
                break;
            case WaferRobotXAction.X_CW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            case WaferRobotXAction.X_CCW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            default:
                break;
      }
    }

    public static readonly DependencyProperty RobotTActionProperty = DependencyProperty.Register(
      "RobotTAction",
      typeof(WaferRobotTAction),
      typeof(WaferRobotControl),
      new PropertyMetadata(WaferRobotTAction.T_Origin, RobotTActionPropertyChangedCallback));

    public WaferRobotTAction RobotTAction
    {
      get => (WaferRobotTAction)GetValue(RobotTActionProperty);
      set => SetValue(RobotTActionProperty, value);
    }

    private static void RobotTActionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      var control = d as WaferRobotControl;
      var oldAct = (WaferRobotTAction)e.OldValue;
      var newAct = (WaferRobotTAction)e.NewValue;
      switch (newAct)
      {
            case WaferRobotTAction.T_Origin:
                VisualStateManager.GoToState(control, newAct.ToString(), true);
                break;
            case WaferRobotTAction.T_CW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            case WaferRobotTAction.T_CCW:
                if (newAct != oldAct)
                {
                  VisualStateManager.GoToState(control, newAct.ToString(), true);
                }
                break;
            default:
                break;
      }
    }

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();
      VisualStateManager.GoToState(this, WaferRobotZAction.Z_Origin.ToString(), true);
      VisualStateManager.GoToState(this, WaferRobotXAction.X_Origin.ToString(), true);
      VisualStateManager.GoToState(this, WaferRobotTAction.T_Origin.ToString(), true);
    }


三 Style

控件模板的实现思路。
将机器人的样式分为三部分,不动的底座部分,Z轴部分,包含T轴和X轴的手臂部分。
VisualStateGroup中定义出轴动作的VisualState,编写转换动画。
https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gifhttps://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gifView Code 
四 效果演示

界面代码如下:
<Window x:Class="WpfApp1.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:wpfapp1="clr-namespace:WpfApp1"
      mc:Ignorable="d" Background="WhiteSmoke"
      Title="MainWindow" Height="800" Width="1200">
    <Canvas>
      <wpfapp1:WaferRobotControl Canvas.Left="472" Canvas.Top="171" x:Name="robot"/>
      <Button Content="Z CW" Canvas.Left="757" Canvas.Top="338" Width="60" Height="30" Click="ZCWButton_Click"   />
      <Button Content="Z CCW" Canvas.Left="757" Canvas.Top="388" Width="60" Height="30" Click="ZCCWButton_Click"/>
      <Button Content="X CW" Canvas.Left="838" Canvas.Top="338" Width="60" Height="30" Click="XCWButton_Click"/>
      <Button Content="X CCW" Canvas.Left="838" Canvas.Top="389" Width="60" Height="30" Click="XCCWButton_Click"/>
      <Button Content="T CW" Canvas.Left="919" Canvas.Top="338" Width="60" Height="30" Click="TCWButton_Click"/>
      <Button Content="T CCW" Canvas.Left="919" Canvas.Top="389" Width="60" Height="30" Click="TCCWButton_Click"/>
      <Button Content="Auto" Canvas.Left="757" Canvas.Top="439" Width="60" Height="30" Click="AutoButton_Click"/>
    </Canvas>
</Window> 
后台代码如下:
public partial class MainWindow : Window
    {
      public MainWindow()
      {
            InitializeComponent();
      }

      private void ZCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotZAction = WaferRobotZAction.Z_CW;
      }

      private void ZCCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotZAction = WaferRobotZAction.Z_CCW;
      }

      private void XCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotXAction = WaferRobotXAction.X_CW;
      }

      private void XCCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotXAction = WaferRobotXAction.X_CCW;
      }

      private void TCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotTAction = WaferRobotTAction.T_CW;
      }

      private void TCCWButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotTAction = WaferRobotTAction.T_CCW;
      }

      private async void AutoButton_Click(object sender, RoutedEventArgs e)
      {
            robot.RobotTAction = WaferRobotTAction.T_CCW;
            await Task.Delay(1000);

            robot.RobotXAction = WaferRobotXAction.X_CW;
            await Task.Delay(2000);

            robot.Wafer = 1;
            await Task.Delay(200);

            robot.RobotXAction = WaferRobotXAction.X_CCW;
            await Task.Delay(2000);

            robot.RobotZAction = WaferRobotZAction.Z_CW;
            await Task.Delay(1000);

            robot.RobotTAction = WaferRobotTAction.T_CW;
            await Task.Delay(1000);

            robot.RobotXAction = WaferRobotXAction.X_CW;
            await Task.Delay(2000);

            robot.Wafer = 0;
            await Task.Delay(200);

            robot.RobotXAction = WaferRobotXAction.X_CCW;
            await Task.Delay(2000);

            robot.RobotTAction = WaferRobotTAction.T_Origin;
            await Task.Delay(1000);

            robot.RobotZAction = WaferRobotZAction.Z_CCW;
      }
    } 
                                     本文作者: 一团静火
               本文链接: https://www.cnblogs.com/wwwen/p/17076289.html
               关于博主: 水平有限,不足或错误之处,请批评指正。如果文章对您有帮助,可以点击文章右下角【推荐】一下。
               版权声明: 本博客所有文章除特别声明外,系原创文章,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留此段内容。
            
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: WPF开发经验-实现一种三轴机械手控件