From 4e652bb48e1dfcc3d1c98c15c049e90818771281 Mon Sep 17 00:00:00 2001 From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com> Date: Thu, 24 Apr 2025 09:47:44 +0530 Subject: [PATCH] feat: Enhance Robotic Arm functionality with state management and action handling --- .../instances/animator/roboticArmAnimator.tsx | 2 +- .../armInstance/roboticArmInstance.tsx | 52 ++- .../instances/roboticArmInstances.tsx | 12 +- .../simulation/roboticArm/roboticArm.tsx | 98 +++++- app/src/modules/simulation/simulation.tsx | 24 +- app/src/store/simulation/useArmBotStore.ts | 298 +++++++++--------- 6 files changed, 319 insertions(+), 167 deletions(-) diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index 0cd4fe2..6b35a43 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -1,6 +1,6 @@ import React from 'react' -function RoboticArmAnimator() { +function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase }: any) { return ( <> ) diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 2817906..42b775a 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -1,14 +1,58 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import IKInstance from '../ikInstance/ikInstance'; import RoboticArmAnimator from '../animator/roboticArmAnimator'; +import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; + +function RoboticArmInstance({ armBot }: any) { + const { isPlaying } = usePlayButtonStore(); + const [currentPhase, setCurrentPhase] = useState<(string)>("init"); + console.log('currentPhase: ', currentPhase); + const { armBots, addArmBot, addCurrentAction } = useArmBotStore(); + + useEffect(() => { + + console.log('isPlaying: ', isPlaying); + if (isPlaying) { + //Moving armBot from initial point to rest position. + + if (armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") { + addCurrentAction(armBot.modelUuid, 'action-001'); + setCurrentPhase("moving-to-rest"); + + } + //Waiting for trigger. + if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "moving-to-rest") { + setCurrentPhase("rest"); + } + // Moving armBot from rest position to pick up point. + if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "rest") { + + } + //Moving arm from start point to end point. + if (armBot?.isActive && armBot?.state == "running " && currentPhase == "rest-to-start ") { + + } + //Moving arm from end point to idle. + if (armBot?.isActive && armBot?.state == "running" && currentPhase == "end-to-start") { + + } + + } + + }, [currentPhase, armBot, isPlaying]) + + const HandleCallback = () => { + if (armBot.isActive && armBot.state == "idle" && currentPhase == "init") { + addCurrentAction('armbot-xyz-001', 'action-001'); + } + } -function RoboticArmInstance() { return ( <> - - + ) diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx index 6e8a70a..1f963c8 100644 --- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx +++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx @@ -1,11 +1,21 @@ import React from 'react' import RoboticArmInstance from './armInstance/roboticArmInstance'; +import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; function RoboticArmInstances() { + const { armBots } = useArmBotStore(); + + return ( <> + { + armBots?.map((robot: any) => ( - + + ) + ) + + } ) diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx index 1270d93..7899f56 100644 --- a/app/src/modules/simulation/roboticArm/roboticArm.tsx +++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx @@ -1,15 +1,103 @@ -import React from 'react' -import RoboticArmInstances from './instances/roboticArmInstances'; -import IkInstances from './instances/ikInstances'; +import React, { useEffect } from "react"; +import RoboticArmInstances from "./instances/roboticArmInstances"; +import IkInstances from "./instances/ikInstances"; +import { log } from "node:console"; +import { useArmBotStore } from "../../../store/simulation/useArmBotStore"; function RoboticArm() { + const { armBots, addArmBot, addCurrentAction } = useArmBotStore(); + + const armBotStatusSample: RoboticArmEventSchema[] = [ + { + state: "idle", + // currentAction: { + // actionUuid: "action-001", + // actionName: "Pick Component", + // }, + modelUuid: "armbot-xyz-001", + modelName: "ArmBot-X200", + position: [0, 0, 0], + rotation: [91.94347308985614, 0, 6.742905194869091], + type: "roboticArm", + speed: 1.5, + point: { + uuid: "point-123", + position: [0, 1.5, 0], + rotation: [0, 0, 0], + actions: [ + { + actionUuid: "action-001", + actionName: "Pick Component", + actionType: "pickAndPlace", + process: { + startPoint: [1.2, 0.3, 0.5], + endPoint: [-0.8, 1.1, 0.7], + }, + triggers: [ + { + triggerUuid: "trigger-001", + triggerName: "Start Trigger", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { + modelName: "Conveyor A1", + modelUuid: "conveyor-01", + }, + triggeredPoint: { + pointName: "Start Point", + pointUuid: "conveyor-01-point-001", + }, + triggeredAction: { + actionName: "Move Forward", + actionUuid: "conveyor-action-01", + }, + }, + }, + { + triggerUuid: "trigger-002", + triggerName: "Complete Trigger", + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { + modelName: "StaticMachine B2", + modelUuid: "machine-02", + }, + triggeredPoint: { + pointName: "Receive Point", + pointUuid: "machine-02-point-001", + }, + triggeredAction: { + actionName: "Process Part", + actionUuid: "machine-action-01", + }, + }, + }, + ], + }, + ], + }, + }, + ]; + + useEffect(() => { + addArmBot('123', armBotStatusSample[0]); + // addCurrentAction('armbot-xyz-001', 'action-001'); + }, []); + + + useEffect(() => { + console.log('armBots: ', armBots); + }, [armBots]); + return ( <> - ) + ); } -export default RoboticArm; \ No newline at end of file +export default RoboticArm; diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 1be292e..556ed01 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -1,30 +1,30 @@ -import React, { useEffect } from 'react'; -import { useEventsStore } from '../../store/simulation/useEventsStore'; -import { useProductStore } from '../../store/simulation/useProductStore'; -import Vehicles from './vehicle/vehicles'; -import Points from './events/points/points'; +import React, { useEffect } from "react"; +import { useEventsStore } from "../../store/simulation/useEventsStore"; +import { useProductStore } from "../../store/simulation/useProductStore"; +import Vehicles from "./vehicle/vehicles"; +import Points from "./events/points/points"; +import RoboticArm from "./roboticArm/roboticArm"; function Simulation() { const { events } = useEventsStore(); const { products } = useProductStore(); useEffect(() => { - console.log('events: ', events); - }, [events]) + console.log("events: ", events); + }, [events]); useEffect(() => { // console.log('products: ', products); - }, [products]) + }, [products]); return ( <> - - + - ) + ); } -export default Simulation \ No newline at end of file +export default Simulation; diff --git a/app/src/store/simulation/useArmBotStore.ts b/app/src/store/simulation/useArmBotStore.ts index 493a068..84f0ec9 100644 --- a/app/src/store/simulation/useArmBotStore.ts +++ b/app/src/store/simulation/useArmBotStore.ts @@ -1,160 +1,170 @@ -import { create } from 'zustand'; -import { immer } from 'zustand/middleware/immer'; +import { create } from "zustand"; +import { immer } from "zustand/middleware/immer"; interface ArmBotStore { - armBots: ArmBotStatus[]; + armBots: ArmBotStatus[]; - addArmBot: (productId: string, event: RoboticArmEventSchema) => void; - removeArmBot: (modelUuid: string) => void; - updateArmBot: ( - modelUuid: string, - updates: Partial> - ) => void; + addArmBot: (productId: string, event: RoboticArmEventSchema) => void; + removeArmBot: (modelUuid: string) => void; - addCurrentAction: (modelUuid: string, actionUuid: string) => void; - removeCurrentAction: (modelUuid: string) => void; + updateArmBot: ( + modelUuid: string, + updates: Partial> + ) => void; - addAction: (modelUuid: string, action: RoboticArmPointSchema['actions'][number]) => void; - removeAction: (modelUuid: string, actionUuid: string) => void; + addCurrentAction: (modelUuid: string, actionUuid: string) => void; + removeCurrentAction: (modelUuid: string) => void; - setArmBotActive: (modelUuid: string, isActive: boolean) => void; + addAction: ( + modelUuid: string, + action: RoboticArmPointSchema["actions"][number] + ) => void; + removeAction: (modelUuid: string, actionUuid: string) => void; - incrementActiveTime: (modelUuid: string, incrementBy: number) => void; - incrementIdleTime: (modelUuid: string, incrementBy: number) => void; + setArmBotActive: (modelUuid: string, isActive: boolean) => void; - getArmBotById: (modelUuid: string) => ArmBotStatus | undefined; - getArmBotsByProduct: (productId: string) => ArmBotStatus[]; - getArmBotsByState: (state: string) => ArmBotStatus[]; - getActiveArmBots: () => ArmBotStatus[]; - getIdleArmBots: () => ArmBotStatus[]; - getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[]; + incrementActiveTime: (modelUuid: string, incrementBy: number) => void; + incrementIdleTime: (modelUuid: string, incrementBy: number) => void; + + getArmBotById: (modelUuid: string) => ArmBotStatus | undefined; + getArmBotsByProduct: (productId: string) => ArmBotStatus[]; + getArmBotsByState: (state: string) => ArmBotStatus[]; + getActiveArmBots: () => ArmBotStatus[]; + getIdleArmBots: () => ArmBotStatus[]; + getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[]; } export const useArmBotStore = create()( - immer((set, get) => ({ - armBots: [], + immer((set, get) => ({ + armBots: [], - addArmBot: (productId, event) => { - set((state) => { - state.armBots.push({ - ...event, - productId, - isActive: false, - idleTime: 0, - activeTime: 0, - state: 'idle', - }); - }); - }, + addArmBot: (productId, event) => { + set((state) => { + state.armBots.push({ + ...event, + productId, + isActive: false, + idleTime: 0, + activeTime: 0, + state: "idle", + }); + }); + }, - removeArmBot: (modelUuid) => { - set((state) => { - state.armBots = state.armBots.filter(a => a.modelUuid !== modelUuid); - }); - }, + removeArmBot: (modelUuid) => { + set((state) => { + state.armBots = state.armBots.filter((a) => a.modelUuid !== modelUuid); + }); + }, - updateArmBot: (modelUuid, updates) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - Object.assign(armBot, updates); - } - }); - }, - - addCurrentAction: (modelUuid, actionUuid) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - const action = armBot.point.actions.find(a => a.actionUuid === actionUuid); - if (action) { - armBot.currentAction = { - actionUuid: action.actionUuid, - actionName: action.actionName, - }; - armBot.isActive = true; - } - } - }); - }, - - removeCurrentAction: (modelUuid) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.currentAction = undefined; - armBot.isActive = false; - } - }); - }, - - addAction: (modelUuid, action) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.point.actions.push(action); - } - }); - }, - - removeAction: (modelUuid, actionUuid) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.point.actions = armBot.point.actions.filter(a => a.actionUuid !== actionUuid); - } - }); - }, - - setArmBotActive: (modelUuid, isActive) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.isActive = isActive; - } - }); - }, - - incrementActiveTime: (modelUuid, incrementBy) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.activeTime += incrementBy; - } - }); - }, - - incrementIdleTime: (modelUuid, incrementBy) => { - set((state) => { - const armBot = state.armBots.find(a => a.modelUuid === modelUuid); - if (armBot) { - armBot.idleTime += incrementBy; - } - }); - }, - - getArmBotById: (modelUuid) => { - return get().armBots.find(a => a.modelUuid === modelUuid); - }, - - getArmBotsByProduct: (productId) => { - return get().armBots.filter(a => a.productId === productId); - }, - - getArmBotsByState: (state) => { - return get().armBots.filter(a => a.state === state); - }, - - getActiveArmBots: () => { - return get().armBots.filter(a => a.isActive); - }, - - getIdleArmBots: () => { - return get().armBots.filter(a => !a.isActive && a.state === 'idle'); - }, - - getArmBotsByCurrentAction: (actionUuid) => { - return get().armBots.filter(a => a.currentAction?.actionUuid === actionUuid); + updateArmBot: (modelUuid, updates) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + Object.assign(armBot, updates); } - })) + }); + }, + + addCurrentAction: (modelUuid, actionUuid) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + const action = armBot.point.actions.find( + (a) => a.actionUuid === actionUuid + ); + if (action) { + armBot.currentAction = { + actionUuid: action.actionUuid, + actionName: action.actionName, + }; + armBot.isActive = true; + } + } + }); + }, + + removeCurrentAction: (modelUuid) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.currentAction = undefined; + armBot.isActive = false; + } + }); + }, + + addAction: (modelUuid, action) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.point.actions.push(action); + } + }); + }, + + removeAction: (modelUuid, actionUuid) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.point.actions = armBot.point.actions.filter( + (a) => a.actionUuid !== actionUuid + ); + } + }); + }, + + setArmBotActive: (modelUuid, isActive) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.isActive = isActive; + } + }); + }, + + incrementActiveTime: (modelUuid, incrementBy) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.activeTime += incrementBy; + } + }); + }, + + incrementIdleTime: (modelUuid, incrementBy) => { + set((state) => { + const armBot = state.armBots.find((a) => a.modelUuid === modelUuid); + if (armBot) { + armBot.idleTime += incrementBy; + } + }); + }, + + getArmBotById: (modelUuid) => { + return get().armBots.find((a) => a.modelUuid === modelUuid); + }, + + getArmBotsByProduct: (productId) => { + return get().armBots.filter((a) => a.productId === productId); + }, + + getArmBotsByState: (state) => { + return get().armBots.filter((a) => a.state === state); + }, + + getActiveArmBots: () => { + return get().armBots.filter((a) => a.isActive); + }, + + getIdleArmBots: () => { + return get().armBots.filter((a) => !a.isActive && a.state === "idle"); + }, + + getArmBotsByCurrentAction: (actionUuid) => { + return get().armBots.filter( + (a) => a.currentAction?.actionUuid === actionUuid + ); + }, + })) );