轴控制 API 文档
文档信息
| 项目 | 内容 |
|---|---|
| 版本 | 1.0.0 |
| 状态 | 正式版 |
| 编写日期 | 2025-12-16 |
| 最后更新 | 2025-12-16 |
| 编写人 | SISO 开发团队 |
更新日志
| 版本 | 日期 | 更新内容 | 编写人 |
|---|---|---|---|
| 1.0.0 | 2025-12-16 | 初始版本,包含轴管理器接口、轴控制方法、数据结构和异常处理 | SISO 开发团队 |
1. 概述
本文档详细介绍了 SISO 系统中轴控制相关的 API 接口,包括轴管理器接口、轴控制方法以及相关数据结构。这些 API 提供了对运动轴的初始化、控制、状态监控等功能的抽象和实现。
2. 轴管理器接口
2.1 IAxisManager 接口
IAxisManager 是轴控制模块的核心接口,定义了对运动轴进行管理和控制的基本操作。
public interface IAxisManager
{
#region 初始化与关闭
/// <summary>
/// 初始化轴管理器
/// </summary>
/// <returns>初始化是否成功</returns>
bool Initialize();
/// <summary>
/// 使用指定配置初始化轴管理器
/// </summary>
/// <param name="configPath">配置文件路径</param>
/// <returns>初始化是否成功</returns>
bool Initialize(string configPath);
/// <summary>
/// 关闭轴管理器,释放资源
/// </summary>
void Close();
#endregion
#region 轴信息获取
/// <summary>
/// 获取所有轴的信息
/// </summary>
/// <returns>轴信息列表</returns>
List<AxisBean> GetAllAxes();
/// <summary>
/// 根据轴ID获取轴信息
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴信息对象,如果未找到返回null</returns>
AxisBean GetAxisById(int axisId);
/// <summary>
/// 获取轴的当前状态
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴状态枚举值</returns>
AxisStatus GetAxisStatus(int axisId);
/// <summary>
/// 获取轴的当前位置
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴的当前位置值</returns>
double GetAxisCurrentPosition(int axisId);
/// <summary>
/// 获取轴的当前速度
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴的当前速度值</returns>
double GetAxisCurrentSpeed(int axisId);
#endregion
#region 运动控制
/// <summary>
/// 控制轴点动
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="speed">点动速度</param>
/// <param name="isPositive">是否正方向</param>
/// <returns>操作是否成功</returns>
bool MoveAxisJog(int axisId, double speed, bool isPositive);
/// <summary>
/// 停止指定轴的运动
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>操作是否成功</returns>
bool StopAxis(int axisId);
/// <summary>
/// 停止所有轴的运动
/// </summary>
/// <returns>操作是否成功</returns>
bool StopAllAxes();
/// <summary>
/// 控制轴进行相对运动
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="distance">相对运动距离</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
bool MoveAxisRelative(int axisId, double distance, double speed);
/// <summary>
/// 控制轴进行绝对运动
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="position">目标位置</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
bool MoveAxisAbsolute(int axisId, double position, double speed);
/// <summary>
/// 控制轴回零
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>操作是否成功</returns>
bool HomeAxis(int axisId);
/// <summary>
/// 控制轴回零(带参数)
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="homeMode">回零模式</param>
/// <param name="homeSpeed">回零速度</param>
/// <returns>操作是否成功</returns>
bool HomeAxis(int axisId, HomeMode homeMode, double homeSpeed);
/// <summary>
/// 多轴同步运动(绝对位置)
/// </summary>
/// <param name="targetPositions">各轴目标位置映射表,key为轴ID,value为目标位置</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
bool MoveMultipleAxesSynchronously(Dictionary<int, double> targetPositions, double speed);
/// <summary>
/// 多轴同步运动(绝对位置,带加速度和减速度)
/// </summary>
/// <param name="targetPositions">各轴目标位置映射表,key为轴ID,value为目标位置</param>
/// <param name="speed">运动速度</param>
/// <param name="acceleration">加速度</param>
/// <param name="deceleration">减速度</param>
/// <returns>操作是否成功</returns>
bool MoveMultipleAxesSynchronously(Dictionary<int, double> targetPositions, double speed, double acceleration, double deceleration);
/// <summary>
/// 多轴同步相对运动
/// </summary>
/// <param name="relativeDistances">各轴相对运动距离映射表,key为轴ID,value为相对距离</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
bool MoveMultipleAxesSynchronouslyRelative(Dictionary<int, double> relativeDistances, double speed);
/// <summary>
/// 等待所有指定轴运动完成
/// </summary>
/// <param name="axisIds">轴ID列表,若为null或空则等待所有轴</param>
/// <param name="timeout">超时时间(毫秒),0表示无限等待</param>
/// <returns>是否在超时前完成运动</returns>
bool WaitForMotionCompletion(List<int> axisIds = null, int timeout = 0);
#endregion
#region 参数设置
/// <summary>
/// 设置轴的位置值(直接修改系统中的位置值,非运动命令)
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="position">要设置的位置值</param>
/// <returns>操作是否成功</returns>
bool SetAxisPosition(int axisId, double position);
/// <summary>
/// 设置轴的最大速度
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="maxSpeed">最大速度值</param>
/// <returns>操作是否成功</returns>
bool SetAxisMaxSpeed(int axisId, double maxSpeed);
/// <summary>
/// 设置轴的加速度
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="acceleration">加速度值</param>
/// <returns>操作是否成功</returns>
bool SetAxisAcceleration(int axisId, double acceleration);
/// <summary>
/// 设置轴的减速度
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="deceleration">减速度值</param>
/// <returns>操作是否成功</returns>
bool SetAxisDeceleration(int axisId, double deceleration);
#endregion
#region 事件处理
/// <summary>
/// 注册轴状态变化事件处理器
/// </summary>
/// <param name="handler">事件处理函数</param>
void RegisterAxisStatusChangeHandler(Action<int, AxisStatus> handler);
/// <summary>
/// 注册轴位置到达事件处理器
/// </summary>
/// <param name="handler">事件处理函数</param>
void RegisterAxisPositionReachedHandler(Action<int> handler);
#endregion
}
3. 数据结构
3.1 AxisBean 类
AxisBean 类用于表示轴的属性和状态信息。
public class AxisBean
{
/// <summary>
/// 轴ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 轴名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 当前位置
/// </summary>
public double CurrentPosition { get; set; }
/// <summary>
/// 目标位置
/// </summary>
public double TargetPosition { get; set; }
/// <summary>
/// 当前速度
/// </summary>
public double CurrentSpeed { get; set; }
/// <summary>
/// 最大速度
/// </summary>
public double MaxSpeed { get; set; }
/// <summary>
/// 加速度
/// </summary>
public double Acceleration { get; set; }
/// <summary>
/// 减速度
/// </summary>
public double Deceleration { get; set; }
/// <summary>
/// 轴状态
/// </summary>
public AxisStatus Status { get; set; }
/// <summary>
/// 是否已回零
/// </summary>
public bool IsHomed { get; set; }
/// <summary>
/// 是否处于报警状态
/// </summary>
public bool IsInAlarm { get; set; }
/// <summary>
/// 正向限位状态
/// </summary>
public bool PositiveLimit { get; set; }
/// <summary>
/// 负向限位状态
/// </summary>
public bool NegativeLimit { get; set; }
/// <summary>
/// 原点信号状态
/// </summary>
public bool HomeSignal { get; set; }
}
3.2 枚举类型
3.2.1 AxisStatus 枚举
表示轴的运行状态。
public enum AxisStatus
{
/// <summary>
/// 未知状态
/// </summary>
Unknown = 0,
/// <summary>
/// 空闲状态
/// </summary>
Idle = 1,
/// <summary>
/// 运动中
/// </summary>
Moving = 2,
/// <summary>
/// 回零中
/// </summary>
Homing = 3,
/// <summary>
/// 已回零
/// </summary>
Homed = 4,
/// <summary>
/// 报警状态
/// </summary>
Alarm = 5,
/// <summary>
/// 错误状态
/// </summary>
Error = 6,
/// <summary>
/// 限位状态
/// </summary>
InLimit = 7
}
3.2.2 HomeMode 枚举
表示回零模式。
public enum HomeMode
{
/// <summary>
/// 主动回零(向限位方向运动找原点)
/// </summary>
ActiveHome = 0,
/// <summary>
/// 被动回零(等待外部触发回零信号)
/// </summary>
PassiveHome = 1,
/// <summary>
/// 感应回零(通过原点传感器信号回零)
/// </summary>
SensorHome = 2
}
4. 具体实现类
4.1 AxisManager 类
AxisManager 是 IAxisManager 接口的具体实现类,负责实际的轴控制操作。
public class AxisManager : IAxisManager
{
#region 成员变量
private bool _isInitialized = false;
private Dictionary<int, AxisBean> _axisMap = new Dictionary<int, AxisBean>();
private Dictionary<int, Action<int, AxisStatus>> _statusChangeHandlers = new Dictionary<int, Action<int, AxisStatus>>();
private Dictionary<int, Action<int>> _positionReachedHandlers = new Dictionary<int, Action<int>>();
private object _lockObj = new object();
#endregion
#region 构造函数
/// <summary>
/// 默认构造函数
/// </summary>
public AxisManager()
{
// 初始化默认配置
InitializeDefaultConfig();
}
/// <summary>
/// 使用配置文件路径构造
/// </summary>
/// <param name="configPath">配置文件路径</param>
public AxisManager(string configPath)
{
if (string.IsNullOrEmpty(configPath))
{
throw new ArgumentNullException(nameof(configPath));
}
Initialize(configPath);
}
#endregion
#region IAxisManager 接口实现
/// <summary>
/// 初始化轴管理器
/// </summary>
/// <returns>初始化是否成功</returns>
public bool Initialize()
{
return Initialize("DefaultAxisConfig.xml");
}
/// <summary>
/// 使用指定配置初始化轴管理器
/// </summary>
/// <param name="configPath">配置文件路径</param>
/// <returns>初始化是否成功</returns>
public bool Initialize(string configPath)
{
lock (_lockObj)
{
if (_isInitialized)
{
return true;
}
try
{
// 加载配置文件
var config = LoadConfig(configPath);
// 初始化轴映射
InitializeAxisMap(config);
// 初始化硬件连接
InitializeHardware();
_isInitialized = true;
return true;
}
catch (Exception ex)
{
Console.WriteLine($"初始化轴管理器失败: {ex.Message}");
return false;
}
}
}
/// <summary>
/// 关闭轴管理器,释放资源
/// </summary>
public void Close()
{
lock (_lockObj)
{
if (!_isInitialized)
{
return;
}
try
{
// 停止所有轴运动
StopAllAxes();
// 释放硬件资源
ReleaseHardware();
// 清空事件处理器
_statusChangeHandlers.Clear();
_positionReachedHandlers.Clear();
// 清空轴映射
_axisMap.Clear();
_isInitialized = false;
}
catch (Exception ex)
{
Console.WriteLine($"关闭轴管理器失败: {ex.Message}");
}
}
}
/// <summary>
/// 获取所有轴的信息
/// </summary>
/// <returns>轴信息列表</returns>
public List<AxisBean> GetAllAxes()
{
lock (_lockObj)
{
if (!_isInitialized)
{
throw new AxisInitializationException("轴管理器尚未初始化");
}
return _axisMap.Values.ToList();
}
}
/// <summary>
/// 根据轴ID获取轴信息
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴信息对象,如果未找到返回null</returns>
public AxisBean GetAxisById(int axisId)
{
lock (_lockObj)
{
if (!_isInitialized)
{
throw new AxisInitializationException("轴管理器尚未初始化");
}
_axisMap.TryGetValue(axisId, out var axis);
return axis;
}
}
/// <summary>
/// 获取轴的当前状态
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴状态枚举值</returns>
public AxisStatus GetAxisStatus(int axisId)
{
var axis = GetAxisById(axisId);
if (axis == null)
{
throw new AxisOperationException($"未找到ID为{axisId}的轴");
}
// 实时更新轴状态
UpdateAxisStatus(axis);
return axis.Status;
}
/// <summary>
/// 获取轴的当前位置
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴的当前位置值</returns>
public double GetAxisCurrentPosition(int axisId)
{
var axis = GetAxisById(axisId);
if (axis == null)
{
throw new AxisOperationException($"未找到ID为{axisId}的轴");
}
// 实时更新轴位置
UpdateAxisPosition(axis);
return axis.CurrentPosition;
}
/// <summary>
/// 获取轴的当前速度
/// </summary>
/// <param name="axisId">轴ID</param>
/// <returns>轴的当前速度值</returns>
public double GetAxisCurrentSpeed(int axisId)
{
var axis = GetAxisById(axisId);
if (axis == null)
{
throw new AxisOperationException($"未找到ID为{axisId}的轴");
}
// 实时更新轴速度
UpdateAxisSpeed(axis);
return axis.CurrentSpeed;
}
/// <summary>
/// 控制轴点动
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="speed">点动速度</param>
/// <param name="isPositive">是否正方向</param>
/// <returns>操作是否成功</returns>
public bool MoveAxisJog(int axisId, double speed, bool isPositive)
{
var axis = GetAxisById(axisId);
if (axis == null)
{
throw new AxisOperationException($"未找到ID为{axisId}的轴");
}
if (speed <= 0)
{
throw new ArgumentException("速度必须大于0", nameof(speed));
}
lock (_lockObj)
{
try
{
// 发送点动命令到硬件
SendJogCommandToHardware(axis, speed, isPositive);
// 更新轴状态
axis.Status = AxisStatus.Moving;
OnAxisStatusChanged(axisId, axis.Status);
return true;
}
catch (Exception ex)
{
throw new AxisOperationException($"轴{axisId}点动失败: {ex.Message}", ex);
}
}
}
// 其他IAxisManager接口方法的实现...
// 由于篇幅限制,此处省略部分实现代码
// 完整实现请参考源代码
/// <summary>
/// 多轴同步运动(绝对位置)
/// </summary>
/// <param name="targetPositions">各轴目标位置映射表,key为轴ID,value为目标位置</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
public bool MoveMultipleAxesSynchronously(Dictionary<int, double> targetPositions, double speed)
{
return MoveMultipleAxesSynchronously(targetPositions, speed, 0, 0);
}
/// <summary>
/// 多轴同步运动(绝对位置,带加速度和减速度)
/// </summary>
/// <param name="targetPositions">各轴目标位置映射表,key为轴ID,value为目标位置</param>
/// <param name="speed">运动速度</param>
/// <param name="acceleration">加速度</param>
/// <param name="deceleration">减速度</param>
/// <returns>操作是否成功</returns>
public bool MoveMultipleAxesSynchronously(Dictionary<int, double> targetPositions, double speed, double acceleration, double deceleration)
{
if (targetPositions == null || targetPositions.Count == 0)
{
throw new ArgumentException("目标位置映射表不能为空", nameof(targetPositions));
}
if (speed <= 0)
{
throw new ArgumentException("速度必须大于0", nameof(speed));
}
lock (_lockObj)
{
try
{
// 验证所有轴是否存在
foreach (int axisId in targetPositions.Keys)
{
if (!_axisMap.ContainsKey(axisId))
{
throw new AxisOperationException(axisId, "MoveMultiple", $"未找到ID为{axisId}的轴");
}
}
// 计算各轴运动参数
Dictionary<int, MotionParams> motionParams = CalculateMotionParams(targetPositions, speed, acceleration, deceleration);
// 发送同步运动命令到硬件
SendSyncMotionCommandToHardware(motionParams);
// 更新各轴状态
foreach (int axisId in targetPositions.Keys)
{
_axisMap[axisId].Status = AxisStatus.Moving;
_axisMap[axisId].TargetPosition = targetPositions[axisId];
OnAxisStatusChanged(axisId, AxisStatus.Moving);
}
return true;
}
catch (Exception ex)
{
throw new AxisOperationException(0, "MoveMultiple", $"多轴同步运动失败: {ex.Message}", ex);
}
}
}
/// <summary>
/// 多轴同步相对运动
/// </summary>
/// <param name="relativeDistances">各轴相对运动距离映射表,key为轴ID,value为相对距离</param>
/// <param name="speed">运动速度</param>
/// <returns>操作是否成功</returns>
public bool MoveMultipleAxesSynchronouslyRelative(Dictionary<int, double> relativeDistances, double speed)
{
if (relativeDistances == null || relativeDistances.Count == 0)
{
throw new ArgumentException("相对距离映射表不能为空", nameof(relativeDistances));
}
// 计算绝对目标位置
Dictionary<int, double> targetPositions = new Dictionary<int, double>();
foreach (var kvp in relativeDistances)
{
int axisId = kvp.Key;
double distance = kvp.Value;
if (!_axisMap.ContainsKey(axisId))
{
throw new AxisOperationException(axisId, "MoveMultipleRelative", $"未找到ID为{axisId}的轴");
}
double currentPos = _axisMap[axisId].CurrentPosition;
targetPositions[axisId] = currentPos + distance;
}
// 调用绝对运动方法
return MoveMultipleAxesSynchronously(targetPositions, speed);
}
/// <summary>
/// 等待所有指定轴运动完成
/// </summary>
/// <param name="axisIds">轴ID列表,若为null或空则等待所有轴</param>
/// <param name="timeout">超时时间(毫秒),0表示无限等待</param>
/// <returns>是否在超时前完成运动</returns>
public bool WaitForMotionCompletion(List<int> axisIds = null, int timeout = 0)
{
if (!_isInitialized)
{
throw new AxisInitializationException("轴管理器尚未初始化");
}
List<int> axesToWait = axisIds;
if (axesToWait == null || axesToWait.Count == 0)
{
axesToWait = _axisMap.Keys.ToList();
}
long startTime = DateTime.Now.Ticks;
long timeoutTicks = timeout * 10000; // 转换为 ticks
while (true)
{
bool allCompleted = true;
// 检查所有指定轴的状态
foreach (int axisId in axesToWait)
{
if (!_axisMap.ContainsKey(axisId))
{
continue;
}
// 实时更新轴状态
UpdateAxisStatus(_axisMap[axisId]);
// 检查轴是否不在运动状态
if (_axisMap[axisId].Status == AxisStatus.Moving || _axisMap[axisId].Status == AxisStatus.Homing)
{
allCompleted = false;
break;
}
}
if (allCompleted)
{
return true;
}
// 检查是否超时
if (timeout > 0)
{
long elapsedTicks = DateTime.Now.Ticks - startTime;
if (elapsedTicks > timeoutTicks)
{
throw new AxisTimeoutException(0, timeout, "多轴运动等待超时");
}
}
// 短暂休眠,避免CPU占用过高
Thread.Sleep(50);
}
}
#endregion
#region 内部辅助方法
/// <summary>
/// 运动参数类
/// </summary>
private class MotionParams
{
/// <summary>
/// 轴ID
/// </summary>
public int AxisId { get; set; }
/// <summary>
/// 目标位置
/// </summary>
public double TargetPosition { get; set; }
/// <summary>
/// 运动速度
/// </summary>
public double Speed { get; set; }
/// <summary>
/// 加速度
/// </summary>
public double Acceleration { get; set; }
/// <summary>
/// 减速度
/// </summary>
public double Deceleration { get; set; }
/// <summary>
/// 运动距离
/// </summary>
public double Distance { get; set; }
/// <summary>
/// 运动时间
/// </summary>
public double MotionTime { get; set; }
}
/// <summary>
/// 初始化默认配置
/// </summary>
private void InitializeDefaultConfig()
{
// 初始化默认轴配置
// ...
}
/// <summary>
/// 加载配置文件
/// </summary>
/// <param name="configPath">配置文件路径</param>
/// <returns>配置对象</returns>
private AxisConfig LoadConfig(string configPath)
{
// 加载并解析配置文件
// ...
return new AxisConfig();
}
/// <summary>
/// 初始化轴映射
/// </summary>
/// <param name="config">轴配置对象</param>
private void InitializeAxisMap(AxisConfig config)
{
// 根据配置初始化轴映射
// ...
}
/// <summary>
/// 初始化硬件连接
/// </summary>
private void InitializeHardware()
{
// 初始化硬件驱动和连接
// ...
}
/// <summary>
/// 释放硬件资源
/// </summary>
private void ReleaseHardware()
{
// 释放硬件驱动和连接
// ...
}
/// <summary>
/// 实时更新轴状态
/// </summary>
/// <param name="axis">轴对象</param>
private void UpdateAxisStatus(AxisBean axis)
{
// 从硬件获取最新状态并更新
// ...
}
/// <summary>
/// 实时更新轴位置
/// </summary>
/// <param name="axis">轴对象</param>
private void UpdateAxisPosition(AxisBean axis)
{
// 从硬件获取最新位置并更新
// ...
}
/// <summary>
/// 实时更新轴速度
/// </summary>
/// <param name="axis">轴对象</param>
private void UpdateAxisSpeed(AxisBean axis)
{
// 从硬件获取最新速度并更新
// ...
}
/// <summary>
/// 发送点动命令到硬件
/// </summary>
/// <param name="axis">轴对象</param>
/// <param name="speed">点动速度</param>
/// <param name="isPositive">是否正方向</param>
private void SendJogCommandToHardware(AxisBean axis, double speed, bool isPositive)
{
// 实际的硬件通信代码
// ...
}
/// <summary>
/// 计算运动参数
/// </summary>
/// <param name="targetPositions">目标位置映射表</param>
/// <param name="speed">运动速度</param>
/// <param name="acceleration">加速度</param>
/// <param name="deceleration">减速度</param>
/// <returns>运动参数映射表</returns>
private Dictionary<int, MotionParams> CalculateMotionParams(Dictionary<int, double> targetPositions, double speed, double acceleration, double deceleration)
{
Dictionary<int, MotionParams> motionParamsMap = new Dictionary<int, MotionParams>();
double maxMotionTime = 0;
// 第一遍计算:计算各轴运动距离和所需时间
foreach (int axisId in targetPositions.Keys)
{
AxisBean axis = _axisMap[axisId];
double currentPos = axis.CurrentPosition;
double targetPos = targetPositions[axisId];
double distance = Math.Abs(targetPos - currentPos);
// 使用默认加速度和减速度(如果未指定)
double axisAcc = acceleration > 0 ? acceleration : axis.Acceleration;
double axisDec = deceleration > 0 ? deceleration : axis.Deceleration;
// 计算运动时间
double motionTime = CalculateMotionTime(distance, speed, axisAcc, axisDec);
MotionParams params = new MotionParams
{
AxisId = axisId,
TargetPosition = targetPos,
Speed = speed,
Acceleration = axisAcc,
Deceleration = axisDec,
Distance = distance,
MotionTime = motionTime
};
motionParamsMap.Add(axisId, @params);
// 更新最大运动时间
if (motionTime > maxMotionTime)
{
maxMotionTime = motionTime;
}
}
// 第二遍计算:调整各轴速度,确保同步完成
foreach (var kvp in motionParamsMap)
{
MotionParams @params = kvp.Value;
// 如果轴的运动时间小于最大时间,调整其速度以匹配最大时间
if (@params.MotionTime < maxMotionTime && @params.MotionTime > 0)
{
double speedRatio = @params.MotionTime / maxMotionTime;
@params.Speed = speed * speedRatio;
// 重新计算加速度和减速度,保持比例
@params.Acceleration *= speedRatio;
@params.Deceleration *= speedRatio;
// 更新运动时间
@params.MotionTime = maxMotionTime;
}
}
return motionParamsMap;
}
/// <summary>
/// 计算运动时间
/// </summary>
/// <param name="distance">运动距离</param>
/// <param name="speed">运动速度</param>
/// <param name="acceleration">加速度</param>
/// <param name="deceleration">减速度</param>
/// <returns>运动时间(秒)</returns>
private double CalculateMotionTime(double distance, double speed, double acceleration, double deceleration)
{
// 计算运动时间的公式
// ...
return distance / speed;
}
/// <summary>
/// 发送同步运动命令到硬件
/// </summary>
/// <param name="motionParams">运动参数映射表</param>
private void SendSyncMotionCommandToHardware(Dictionary<int, MotionParams> motionParams)
{
// 发送同步运动命令到硬件
// ...
}
/// <summary>
/// 触发轴状态变化事件
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="status">新状态</param>
private void OnAxisStatusChanged(int axisId, AxisStatus status)
{
// 触发状态变化事件
// ...
}
/// <summary>
/// 触发轴位置到达事件
/// </summary>
/// <param name="axisId">轴ID</param>
private void OnAxisPositionReached(int axisId)
{
// 触发位置到达事件
// ...
}
#endregion
}
4.2 AxisConfig 类
AxisConfig 类用于存储轴管理器的配置信息。
public class AxisConfig
{
/// <summary>
/// 轴配置列表
/// </summary>
public List<SingleAxisConfig> AxesConfig { get; set; }
/// <summary>
/// 通信超时时间(毫秒)
/// </summary>
public int CommunicationTimeout { get; set; } = 5000;
/// <summary>
/// 状态更新间隔(毫秒)
/// </summary>
public int StatusUpdateInterval { get; set; } = 100;
/// <summary>
/// 是否启用日志
/// </summary>
public bool EnableLogging { get; set; } = true;
}
/// <summary>
/// 单轴配置类
/// </summary>
public class SingleAxisConfig
{
/// <summary>
/// 轴ID
/// </summary>
public int AxisId { get; set; }
/// <summary>
/// 轴名称
/// </summary>
public string AxisName { get; set; }
/// <summary>
/// 最大速度
/// </summary>
public double MaxSpeed { get; set; }
/// <summary>
/// 加速度
/// </summary>
public double Acceleration { get; set; }
/// <summary>
/// 减速度
/// </summary>
public double Deceleration { get; set; }
/// <summary>
/// 回零模式
/// </summary>
public HomeMode HomeMode { get; set; }
/// <summary>
/// 回零速度
/// </summary>
public double HomeSpeed { get; set; }
}
5. 异常处理
轴控制模块定义了特定的异常类型,用于表示不同类型的轴操作异常。所有轴相关异常都继承自 DeviceException 基类,提供统一的异常处理机制。
5.1 异常类层次结构
DeviceException
└── AxisException
├── AxisInitializationException
├── AxisCommunicationException
├── AxisOperationException
├── AxisTimeoutException
├── AxisLimitException
└── AxisAlarmException
5.2 异常类具体定义
/// <summary>
/// 轴异常基类
/// </summary>
public class AxisException : DeviceException
{
/// <summary>
/// 轴ID
/// </summary>
public int? AxisId { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">异常消息</param>
public AxisException(string message) : base(message)
{}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">异常消息</param>
/// <param name="innerException">内部异常</param>
public AxisException(string message, Exception innerException) : base(message, innerException)
{}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="message">异常消息</param>
public AxisException(int axisId, string message) : base(message)
{
AxisId = axisId;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="message">异常消息</param>
/// <param name="innerException">内部异常</param>
public AxisException(int axisId, string message, Exception innerException) : base(message, innerException)
{
AxisId = axisId;
}
}
/// <summary>
/// 轴初始化异常
/// </summary>
public class AxisInitializationException : AxisException
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">异常消息</param>
public AxisInitializationException(string message) : base(message) {}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">异常消息</param>
/// <param name="innerException">内部异常</param>
public AxisInitializationException(string message, Exception innerException) : base(message, innerException) {}
}
/// <summary>
/// 轴通信异常
/// </summary>
public class AxisCommunicationException : AxisException
{
/// <summary>
/// 通信端口
/// </summary>
public string Port { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="port">通信端口</param>
/// <param name="message">异常消息</param>
public AxisCommunicationException(int axisId, string port, string message) : base(axisId, message)
{
Port = port;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="port">通信端口</param>
/// <param name="message">异常消息</param>
/// <param name="innerException">内部异常</param>
public AxisCommunicationException(int axisId, string port, string message, Exception innerException)
: base(axisId, message, innerException)
{
Port = port;
}
}
/// <summary>
/// 轴操作异常
/// </summary>
public class AxisOperationException : AxisException
{
/// <summary>
/// 操作类型
/// </summary>
public string OperationType { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="operationType">操作类型</param>
/// <param name="message">异常消息</param>
public AxisOperationException(int axisId, string operationType, string message) : base(axisId, message)
{
OperationType = operationType;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="operationType">操作类型</param>
/// <param name="message">异常消息</param>
/// <param name="innerException">内部异常</param>
public AxisOperationException(int axisId, string operationType, string message, Exception innerException)
: base(axisId, message, innerException)
{
OperationType = operationType;
}
}
/// <summary>
/// 轴操作超时异常
/// </summary>
public class AxisTimeoutException : AxisException
{
/// <summary>
/// 超时时间(毫秒)
/// </summary>
public int Timeout { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="timeout">超时时间(毫秒)</param>
/// <param name="message">异常消息</param>
public AxisTimeoutException(int axisId, int timeout, string message) : base(axisId, message)
{
Timeout = timeout;
}
}
/// <summary>
/// 轴限位异常
/// </summary>
public class AxisLimitException : AxisException
{
/// <summary>
/// 是否为正向限位
/// </summary>
public bool IsPositiveLimit { get; private set; }
/// <summary>
/// 当前位置
/// </summary>
public double CurrentPosition { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="isPositiveLimit">是否为正向限位</param>
/// <param name="currentPosition">当前位置</param>
/// <param name="message">异常消息</param>
public AxisLimitException(int axisId, bool isPositiveLimit, double currentPosition, string message)
: base(axisId, message)
{
IsPositiveLimit = isPositiveLimit;
CurrentPosition = currentPosition;
}
}
/// <summary>
/// 轴报警异常
/// </summary>
public class AxisAlarmException : AxisException
{
/// <summary>
/// 报警代码
/// </summary>
public int AlarmCode { get; private set; }
/// <summary>
/// 报警描述
/// </summary>
public string AlarmDescription { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="axisId">轴ID</param>
/// <param name="alarmCode">报警代码</param>
/// <param name="alarmDescription">报警描述</param>
/// <param name="message">异常消息</param>
public AxisAlarmException(int axisId, int alarmCode, string alarmDescription, string message)
: base(axisId, message)
{
AlarmCode = alarmCode;
AlarmDescription = alarmDescription;
}
}
5.3 异常使用示例
// 异常捕获和处理示例
IAxisManager axisManager = new AxisManager();
try
{
// 初始化轴管理器
if (!axisManager.Initialize())
{
throw new AxisInitializationException("轴管理器初始化失败");
}
// 回零操作
if (!axisManager.HomeAxis(1))
{
throw new AxisOperationException(1, "Home", "轴1回零失败");
}
// 绝对运动
if (!axisManager.MoveAxisAbsolute(1, 100.0, 10.0))
{
throw new AxisOperationException(1, "MoveAbsolute", "轴1绝对运动失败");
}
// 等待运动完成
Thread.Sleep(2000);
// 获取当前位置
double currentPosition = axisManager.GetAxisCurrentPosition(1);
Console.WriteLine($"轴1当前位置: {currentPosition}");
}
catch (AxisTimeoutException ex)
{
Console.WriteLine($"轴{ex.AxisId}操作超时: {ex.Message}, 超时时间: {ex.Timeout}ms");
// 处理超时异常,例如重试操作
}
catch (AxisLimitException ex)
{
Console.WriteLine($"轴{ex.AxisId}限位异常: {ex.Message}, 方向: {(ex.IsPositiveLimit ? "正向" : "负向")}, 当前位置: {ex.CurrentPosition}");
// 处理限位异常,例如反向运动解除限位
}
catch (AxisAlarmException ex)
{
Console.WriteLine($"轴{ex.AxisId}报警: {ex.Message}, 报警代码: {ex.AlarmCode}, 报警描述: {ex.AlarmDescription}");
// 处理报警异常,例如重置报警
}
catch (AxisException ex)
{
Console.WriteLine($"轴{ex.AxisId}异常: {ex.Message}");
// 处理其他轴异常
}
catch (Exception ex)
{
Console.WriteLine($"未知异常: {ex.Message}");
// 处理其他非轴异常
}
finally
{
// 关闭轴管理器,释放资源
axisManager?.Close();
}
5.4 异常处理最佳实践
分层捕获:根据异常类型进行分层捕获,优先处理特定类型的异常,再处理通用异常。
详细日志:在捕获异常时,记录详细的异常信息,包括轴ID、操作类型、错误代码等,便于问题定位。
合理重试:对于通信异常或超时异常,可以考虑进行合理的重试机制,但需设置最大重试次数,避免无限重试。
安全停止:在捕获到严重异常时,应确保所有轴停止运动,避免发生安全事故。
用户友好:将技术异常转换为用户友好的错误信息,避免直接向用户展示底层技术细节。
资源清理:在
finally块中确保释放所有资源,包括轴管理器、硬件连接等。
6. 使用示例
6.1 基本用法
// 创建并初始化轴管理器
IAxisManager axisManager = new AxisManager();
if (axisManager.Initialize())
{
try
{
// 获取轴1的信息
AxisBean axis1 = axisManager.GetAxisById(1);
Console.WriteLine($"Axis 1 current position: {axis1.CurrentPosition}");
// 检查轴是否已回零
if (!axis1.IsHomed)
{
Console.WriteLine("Axis 1 is not homed. Homing now...");
axisManager.HomeAxis(1);
Console.WriteLine("Homing completed.");
}
// 控制轴1以10mm/s的速度移动到100mm位置
Console.WriteLine("Moving axis 1 to position 100mm...");
if (axisManager.MoveAxisAbsolute(1, 100.0, 10.0))
{
Console.WriteLine("Move command sent successfully.");
}
}
catch (AxisException ex)
{
Console.WriteLine($"Axis error: {ex.Message}");
}
finally
{
// 关闭轴管理器
axisManager.Close();
}
}
else
{
Console.WriteLine("Failed to initialize axis manager.");
}
6.2 事件处理
// 创建并初始化轴管理器
IAxisManager axisManager = new AxisManager();
if (axisManager.Initialize())
{
// 注册轴状态变化事件处理函数
axisManager.RegisterAxisStatusChangeHandler((axisId, status) => {
Console.WriteLine($"Axis {axisId} status changed to: {status}");
});
// 注册轴位置到达事件处理函数
axisManager.RegisterAxisPositionReachedHandler(axisId => {
Console.WriteLine($"Axis {axisId} has reached target position.");
});
// 执行轴运动操作
// ...
}
6.3 多轴同步运动
// 创建并初始化轴管理器
IAxisManager axisManager = new AxisManager();
if (axisManager.Initialize())
{
try
{
// 假设我们有一个多轴同步运动的扩展方法
// 控制轴1和轴2同时运动到指定位置
Dictionary<int, double> targetPositions = new Dictionary<int, double>
{
{ 1, 100.0 },
{ 2, 200.0 }
};
double speed = 10.0;
// 执行多轴同步运动(这是一个扩展的高级功能)
// axisManager.MoveMultipleAxesSynchronously(targetPositions, speed);
Console.WriteLine("Multi-axis synchronous movement completed.");
}
catch (AxisException ex)
{
Console.WriteLine($"Multi-axis movement error: {ex.Message}");
}
finally
{
// 关闭轴管理器
axisManager.Close();
}
}
7. 最佳实践
初始化和资源释放:始终确保在使用轴管理器后正确关闭它,以释放资源。
错误处理:捕获并处理所有可能的轴操作异常,确保系统稳定运行。
状态检查:在执行关键操作前,始终检查轴的当前状态,确保操作安全。
回零操作:在执行精确位置控制前,确保轴已经正确回零。
事件驱动编程:使用事件机制响应轴状态变化,而不是轮询。
参数验证:在调用API前,验证所有输入参数的有效性。
8. 注意事项
轴控制操作是实时性要求较高的任务,应避免在主线程中执行耗时操作。
在多线程环境中使用轴管理器时,需要注意线程安全问题。
不同的物理轴可能有不同的特性和限制,使用时应参考具体的硬件说明书。
轴的运动参数(速度、加速度、减速度等)应根据实际设备情况和应用需求合理设置。
轴操作异常时,应及时停止相关操作,并采取适当的安全措施。