<fix> 위치 기록 API 재설정 및 위치 수정 시 반투명로봇 수정, 컨트롤러 Grab할당 버그 해결

This commit is contained in:
SOOBEEN HAN
2025-11-10 19:14:16 +09:00
parent 97d4916ff0
commit b5406395dc
23 changed files with 1162 additions and 92 deletions

View File

@@ -41,6 +41,8 @@ public class ProgramModel : IProgramModel
private Vector3 startMovementPosition;
private int currentToolNum = 0;
private readonly SemaphoreSlim clientLock = new SemaphoreSlim(1, 1);
public ProgramModel(string hostip, int tcpPort, int udpPort, RobotController robotController)
{
tcpBaseUrl = $"http://{hostip}:{tcpPort}";
@@ -148,8 +150,17 @@ public class ProgramModel : IProgramModel
HttpResponseMessage result = await httpClient.PostAsync(requestUri, jsonPayload);
if (result.IsSuccessStatusCode)
{
await LoadProgram(userInputId);
return true;
await LoadProgram(newProgramId);
object payload = CmdLinePayload("end", 0);
jsonString = JsonConvert.SerializeObject(payload);
jsonPayload = new StringContent(jsonString, Encoding.UTF8, "application/json");
HttpResponseMessage jsonResponse = await httpClient.PostAsync(
$"{tcpBaseUrl}/project/jobs/{CurrentProgram.ProgramId}/ins_cmd_line", jsonPayload);
if (jsonResponse.IsSuccessStatusCode)
return true;
else
return false;
}
else
return false;
@@ -218,6 +229,7 @@ public class ProgramModel : IProgramModel
{
while (!token.IsCancellationRequested)
{
//await clientLock.WaitAsync(token);
try
{
string requestUri = $"{tcpBaseUrl}/project/robot/po_cur";
@@ -232,13 +244,17 @@ public class ProgramModel : IProgramModel
robotData = tempRobotData;
hasNewData = true;
}
await Task.Delay(50);
await Task.Delay(50, token);
}
catch (Exception e)
{
Debug.Log(e);
await Task.Delay(1000); // 에러 시 더 긴 대기
}
finally
{
//clientLock.Release();
}
}
}
@@ -305,6 +321,37 @@ public class ProgramModel : IProgramModel
/// <summary>
/// 로봇 위치 기록 시스템
/// </summary>
// 프로그램에 명령문 추가
public object CmdLinePayload(string cmd_line, int sno_ref)
{
object payload;
if (cmd_line == "end")
{
payload = new
{
cmd_line = cmd_line,
sno_ref = sno_ref
};
}
else
{
payload = new
{
adjust_branch = true,
cmd_line = cmd_line,
fno_ref = -1,
mechinfo = -1,
move_cursor = 1,
ofs = 0,
save_file = true,
set_cur_pose = 1,
sno_ref = sno_ref
};
}
return payload;
}
public async Task<bool> SavePointToProgramAsync(RobotData pointData, int index = -1)
{
if (CurrentProgram == null)
@@ -325,18 +372,7 @@ public class ProgramModel : IProgramModel
// sno_ref = 마지막 스텝의 번호, 없으면 0
int sno_ref = (CurrentProgram.Steps.Count > 0) ? CurrentProgram.Steps.Last().StepNumber : 0;
payload = new
{
adjust_branch = true,
cmd_line = $"move P,spd=50%,accu=3,tool={currentToolNum}",
fno_ref = -1,
mechinfo = -1,
move_cursor = 1,
ofs = 0,
save_file = true,
set_cur_pose = -1,
sno_ref = sno_ref
};
payload = CmdLinePayload($"move P,spd=50%,accu=3,tool={currentToolNum}", sno_ref);
requestUri = $"{tcpBaseUrl}/project/jobs/{CurrentProgram.ProgramId}/ins_cmd_line";
}
@@ -429,6 +465,7 @@ public class ProgramModel : IProgramModel
// 타겟 포지션으로 이동
public async Task<bool> MoveToPoseTcpAsync(Vector3 position)
{
await clientLock.WaitAsync();
try
{
startMovementPosition.x = Convert.ToSingle(Math.Round(-1 * position.x * 1000, 2));
@@ -454,6 +491,10 @@ public class ProgramModel : IProgramModel
Debug.Log(e);
return false;
}
finally
{
clientLock.Release();
}
}
// TCP POST 이동 명령 체크

View File

@@ -300,22 +300,28 @@ public class ProgramPresenter
Vector3 startPos = interactionView.GetCurrentRayPosition();
interactionView.ShowDragArrow(startPos);
interactionView.ShowGhostRobot();
pointManagerView.kinematicsNode.enabled = true;
// 반투명 로봇의 위치를 마우스 위치와 같도록 설정
pointManagerView.kinematicsNode.targetTransform.localPosition = startPos;
pointManagerView.kinematicsNode.targetTransform.position = startPos;
originalDragPose = model.CurrentProgram.GetStepPose(index);
}
}
private void HandlePointDragUpdate(int index, Vector3 newWorldPos, Quaternion newWorldRot)
{
if (!IsDragging) return;
this.latestTargetPose = ConvertPoseToRobotData(newWorldPos, newWorldRot);
pointManagerView.kinematicsNode.targetTransform.position = newWorldPos;
pointManagerView.kinematicsNode.targetTransform.rotation = newWorldRot;
Vector3 ghostRobotPos = pointManagerView.kinematicsNode.nodes[5].jointTransform.position;
Quaternion ghostRobotRot = pointManagerView.kinematicsNode.nodes[5].jointTransform.rotation;
this.latestTargetPose = ConvertPoseToRobotData(ghostRobotPos, ghostRobotRot);
interactionView.ShowDragArrow(newWorldPos); // 마우스 이미지 변경
// 고스트 로봇, 포인트, 경로 실시간 이동
pointManagerView.kinematicsNode.targetTransform.localPosition = newWorldPos;
pointManagerView.UpdatePointPosition(index, this.latestTargetPose);
pointManagerView.UpdatePointPosition(index, ghostRobotPos);
RedrawTemporaryPath(index, latestTargetPose);
}
@@ -325,6 +331,7 @@ public class ProgramPresenter
interactionView.HideDragArrow();
interactionView.HideGhostRobot();
pointManagerView.kinematicsNode.enabled = false;
pendingPointData = this.latestTargetPose;
@@ -333,7 +340,7 @@ public class ProgramPresenter
currentPopupState = PopupState.ConfirmModifyPoint; // 상태 설정
popupView.ShowModifyPopup(popPos);
_ = WaitForRobotToStopAndShowPopup(currentPopupState);
}
// --- 팝업 응답 통합 핸들러 ---
@@ -362,7 +369,8 @@ public class ProgramPresenter
}
else if (response == PopupResponse.Cancel)
{
pointManagerView.UpdatePointPosition(activePointIndex, originalDragPose); // 원위치
Vector3 originalPos = ConvertRobotDataToVector3(originalDragPose);
pointManagerView.UpdatePointPosition(activePointIndex, originalPos); // 원위치
RedrawTemporaryPath(activePointIndex, originalDragPose); // 경로 원위치
}
break;
@@ -400,6 +408,7 @@ public class ProgramPresenter
private async Task WaitForRobotToStopAndShowPopup(PopupState nextState)
{
await Task.Delay(200);
while (await model.GetMovingState() == "1")
{
Debug.Log("로봇이 멈추기를 기다리는 중...");
@@ -416,6 +425,11 @@ public class ProgramPresenter
popupWorldPos = ConvertRobotDataToVector3(pendingPointData);
popupView.ShowConfirmPopupFromPoint(popupWorldPos); // (새 포인트 위치)
}
else if(nextState == PopupState.ConfirmModifyPoint)
{
popupWorldPos = ConvertRobotDataToVector3(pendingPointData);
popupView.ShowModifyPopup(popupWorldPos);
}
}
private async Task WaitForRobotToStop()

View File

@@ -45,27 +45,27 @@ public class InteractionView : MonoBehaviour, IInteractionView
public bool isGrabbingRobot = false;
void Start()
{
nearFarInteractor = GetComponent<NearFarInteractor>();
//void Start()
//{
// nearFarInteractor = GetComponentInChildren<NearFarInteractor>();
if (nearFarInteractor == null)
{
Debug.LogError("InteractionView: 'nearFarInteractor'가 할당되지 않았습니다", this);
return;
}
// if (nearFarInteractor == null)
// {
// Debug.LogError("InteractionView: 'nearFarInteractor'가 할당되지 않았습니다", this);
// return;
// }
baseInteractor = nearFarInteractor as XRBaseInteractor;
rayProvider = nearFarInteractor as IXRRayProvider;
// baseInteractor = nearFarInteractor as XRBaseInteractor;
// rayProvider = nearFarInteractor as IXRRayProvider;
if (baseInteractor == null)
{
Debug.LogError("NearFarInteractor를 XRBaseInteractor로 변환할 수 없습니다.", this);
return;
}
// if (baseInteractor == null)
// {
// Debug.LogError("NearFarInteractor를 XRBaseInteractor로 변환할 수 없습니다.", this);
// return;
// }
InitializeInteraction();
}
// InitializeInteraction();
//}
void Update()
{
@@ -77,7 +77,7 @@ public class InteractionView : MonoBehaviour, IInteractionView
baseInteractor = nearFarInteractor as XRBaseInteractor;
rayProvider = nearFarInteractor as IXRRayProvider;
}
if (nearFarInteractor != null && nearFarInteractor.gameObject.activeInHierarchy)
if (nearFarInteractor != null)
{
InitializeInteraction();
}
@@ -106,7 +106,6 @@ public class InteractionView : MonoBehaviour, IInteractionView
StartDragMode();
}
}
}
}

View File

@@ -47,10 +47,10 @@ public class PointManagerView : MonoBehaviour, IPointManagerView
}
}
public void UpdatePointPosition(int index, RobotData pose)
public void UpdatePointPosition(int index, Vector3 pose)
{
if (index < 0 || index >= activePoints.Count) return;
activePoints[index].transform.position = ConvertRobotDataToVector3(pose);
activePoints[index].transform.position = pose;
}
public void DeletePoint(int index)

View File

@@ -54,6 +54,7 @@ public class PopupView : MonoBehaviour, IPopupView
{
confirmPopupPanel.transform.position = popPose.position;
confirmPopupPanel.transform.LookAt(Camera.main.transform);
confirmPopupPanel.transform.Rotate(0, 180, 0);
confirmPopupPanel.SetActive(true);
}
@@ -61,13 +62,15 @@ public class PopupView : MonoBehaviour, IPopupView
{
confirmPopupPanel.transform.position = popPose;
confirmPopupPanel.transform.LookAt(Camera.main.transform);
confirmPopupPanel.transform.Rotate(0, 180, 0);
confirmPopupPanel.SetActive(true);
}
public void ShowModifyPopup(Transform popPose)
public void ShowModifyPopup(Vector3 popPose)
{
modifyPopupPanel.transform.position = popPose.position;
modifyPopupPanel.transform.position = popPose;
modifyPopupPanel.transform.LookAt(Camera.main.transform);
modifyPopupPanel.transform.Rotate(0, 180, 0);
modifyPopupPanel.SetActive(true);
}
@@ -75,6 +78,7 @@ public class PopupView : MonoBehaviour, IPopupView
{
deletePopupPanel.transform.position = popPose;
deletePopupPanel.transform.LookAt(Camera.main.transform);
deletePopupPanel.transform.Rotate(0, 180, 0);
deletePopupPanel.SetActive(true);
}
@@ -82,6 +86,7 @@ public class PopupView : MonoBehaviour, IPopupView
{
optionPopupPanel.transform.position = popPose;
optionPopupPanel.transform.LookAt(Camera.main.transform);
optionPopupPanel.transform.Rotate(0, 180, 0);
optionPopupPanel.SetActive(true);
}