Files
HDRobotics/Assets/Scripts/Model/RobotMoveStep.cs
2025-12-03 21:19:07 +09:00

183 lines
6.5 KiB
C#

using System.Text.RegularExpressions;
using UnityEngine;
/// <summary>
/// 로봇 프로그램의 개별 이동 명령(Step) 한 줄을 나타내는 클래스
/// 로봇 제어기로부터 받은 문자열(Raw String)을 파싱하여 속성별로 관리하고,
/// 수정 사항이 생길 경우 다시 문자열로 조합하는 기능을 담당
/// </summary>
public class RobotMoveStep
{
// --- 기본 속성 ---
/// <summary>
/// 로봇 제어기에서 사용하는 원본 명령줄 전체
/// 예: "S1 move P,spd=50%,accu=3,tool=1 [0,0,0,0,0,0,"robot"]"
/// </summary>
public string FullLine { get; private set; }
/// <summary>
/// 해당 스텝의 목표 위치 및 회전 정보 (x, y, z, rx, ry, rz)
/// </summary>
public RobotPose Pose { get; private set; }
public int StepNumber { get; private set; }
public int Speed { get; private set; }
public int Accu { get; private set; }
public int Tool { get; private set; }
/// <summary>
/// 좌표를 제외한 이동 명령 (예: "move P,spd=50%,accu=3,tool=1")
/// </summary>
public string MoveCommand { get; private set; }
// --- 정규표현식 (Regex) 정의 ---
// 성능 최적화를 위해 Compiled 옵션을 사용하며 static readonly로 선언
// 전체 라인 파싱용 Regex
// 구조: [시작(S번호)] + [공백] + [명령어(move...)] + [공백] + [좌표([...])]
// 그룹 2: 스텝 번호 숫자 (예: 1)
// 그룹 3: 이동 명령어 문자열 (예: move P...)
private static readonly Regex StepRegex = new Regex(@"^(S([0-9]+))\s+(move.*?)(\s+\[.*\])", RegexOptions.Compiled);
// 명령어 내부 파라미터 추출용 Regex
private static readonly Regex SpeedRegex = new Regex(@"spd=([0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex AccuRegex = new Regex(@"accu=([0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex ToolRegex = new Regex(@"tool=([0-9]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
/// <summary>
/// 생성자: 문자열 라인을 받아 객체를 초기화합니다.
/// </summary>
/// <param name="line">스텝 번호와 명령어가 포함된 앞부분 문자열 (좌표 포함될 수도 있음)</param>
/// <param name="coordString">대괄호 안의 좌표 데이터 문자열 (예: "0,0,0,0,0,0,"robot"")</param>
public RobotMoveStep(string line, string coordString)
{
this.FullLine = line;
// 1. 좌표 데이터 파싱
// 쉼표로 분리하여 x, y, z, rx, ry, rz 값을 추출
string[] values = coordString.Split(',');
if (values.Length >= 6)
{
this.Pose = new RobotPose(
float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2]),
float.Parse(values[3]), float.Parse(values[4]), float.Parse(values[5])
);
}
else
{
Debug.LogError($"좌표 파싱 실패: {coordString}");
this.Pose = new RobotPose(0, 0, 0, 0, 0, 0);
}
// 2. 명령어 라인 파싱 (Regex 사용)
Match match = StepRegex.Match(line);
if (match.Success)
{
// 그룹 2: 스텝 번호 추출
this.StepNumber = int.Parse(match.Groups[2].Value);
// 그룹 3: 이동 명령어 추출 (앞뒤 공백 제거)
this.MoveCommand = match.Groups[3].Value.Trim();
// 3. 명령어 내부 세부 파라미터 파싱
Match speedMatch = SpeedRegex.Match(this.MoveCommand);
Match accuMatch = AccuRegex.Match(this.MoveCommand);
Match toolMatch = ToolRegex.Match(this.MoveCommand);
if (speedMatch.Success)
this.Speed = int.Parse(speedMatch.Groups[1].Value);
else
Debug.LogWarning($"'spd='를 찾을 수 없음: {this.MoveCommand}");
if (accuMatch.Success)
this.Accu = int.Parse(accuMatch.Groups[1].Value);
else
Debug.LogWarning($"'accu='를 찾을 수 없음: {this.MoveCommand}");
if (toolMatch.Success)
this.Tool = int.Parse(toolMatch.Groups[1].Value);
else
Debug.LogWarning($"'tool='을 찾을 수 없음: {this.MoveCommand}");
}
else
{
Debug.LogError($"스텝 라인 파싱 실패: {line}");
this.StepNumber = -1;
this.MoveCommand = "move P,spd=50%,accu=3,tool=0"; // 기본값
this.Speed = 50; // 기본값
}
}
/// <summary>
/// 스텝 번호를 업데이트할 때 사용 (예: 중간 스텝 삭제 후 번호 재정렬 시)
/// 번호가 바뀌면 FullLine 문자열도 새로 조합하여 갱신
/// </summary>
/// <param name="newStepNumber">새로운 스텝 번호</param>
/// <param name="newMoveCommand">명령어를 변경할 경우 입력 (null이면 기존 명령 유지)</param>
public void UpdateStepNumber(int newStepNumber, string newMoveCommand = null)
{
this.StepNumber = newStepNumber;
if (newMoveCommand != null)
{
this.MoveCommand = newMoveCommand;
}
// 포맷: "S{번호} {명령어} {좌표}" 형태로 문자열 재조립
this.FullLine = $"S{this.StepNumber} {this.MoveCommand} {this.Pose.ToString()}";
}
/// <summary>
/// 로봇의 위치(Pose) 정보를 업데이트할 때 사용
/// 위치가 바뀌면 FullLine 문자열도 새로 조합하여 갱신
/// </summary>
/// <param name="newPose">새로운 위치/회전 정보</param>
public void UpdatePose(RobotPose newPose)
{
this.Pose = newPose;
// 변경된 Pose의 ToString()을 사용하여 FullLine 갱신
this.FullLine = $"S{this.StepNumber} {this.MoveCommand} {this.Pose.ToString()}";
}
}
/// <summary>
/// 로봇의 6축 좌표 데이터(위치 및 회전)를 관리하는 데이터 클래스
/// </summary>
public class RobotPose
{
public float x, y, z, rx, ry, rz;
public RobotPose(float x, float y, float z, float rx, float ry, float rz)
{
this.x = x; this.y = y; this.z = z;
this.rx = rx; this.ry = ry; this.rz = rz;
}
/// <summary>
/// RobotData(Model)를 RobotPose(Program)로 변환
/// </summary>
public RobotPose(RobotData data)
{
this.x = data.x; this.y = data.y; this.z = data.z;
this.rx = data.rx; this.ry = data.ry; this.rz = data.rz;
}
/// <summary>
/// RobotPose(Program)를 RobotData(Model)로 변환
/// </summary>
public RobotData ToRobotData()
{
return new RobotData
{
x = this.x,
y = this.y,
z = this.z,
rx = this.rx,
ry = this.ry,
rz = this.rz
};
}
/// <summary>
/// API에서 요구하는 좌표 문자열 형식으로 변환
/// </summary>
public override string ToString()
{
return $"[{x},{y},{z},{rx},{ry},{rz},\"robot\"]";
}
}