183 lines
6.5 KiB
C#
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\"]";
|
|
}
|
|
} |