diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
index 12a424c..d6b4ac8 100644
--- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
+++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
@@ -90,7 +90,7 @@ const Simulations: React.FC = () => {
(product) => product.productId === selectedProduct.productId
);
- const events: Event[] = selectedProductData?.eventsData.map((event) => ({
+ const events: Event[] = selectedProductData?.eventDatas.map((event) => ({
pathName: event.modelName,
})) || [];
diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
index 6f578e9..415c1d3 100644
--- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
@@ -8,11 +8,10 @@ function RoboticArmInstances() {
return (
<>
- {
- armBots?.map((robot) => (
-
- ))
- }
+
+ {armBots?.map((robot) => (
+
+ ))}
>
)
diff --git a/app/src/services/simulation/UpsertProductOrEventApi.ts b/app/src/services/simulation/UpsertProductOrEventApi.ts
new file mode 100644
index 0000000..27fa126
--- /dev/null
+++ b/app/src/services/simulation/UpsertProductOrEventApi.ts
@@ -0,0 +1,26 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const addProductOrEventApi = async (body: any) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/UpsertProductOrEvent`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(body),
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to add product or event");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/simulation/deleteEventDataApi.ts b/app/src/services/simulation/deleteEventDataApi.ts
new file mode 100644
index 0000000..f263065
--- /dev/null
+++ b/app/src/services/simulation/deleteEventDataApi.ts
@@ -0,0 +1,26 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteEventDataApi = async (body: any) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/EventDataDelete`, {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(body),
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to delete event data");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/simulation/deleteProductDataApi.ts b/app/src/services/simulation/deleteProductDataApi.ts
new file mode 100644
index 0000000..06718f8
--- /dev/null
+++ b/app/src/services/simulation/deleteProductDataApi.ts
@@ -0,0 +1,25 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteProductDataApi = async (productId: string, organization: string) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/productDataDelete?productId=${productId}&organization=${organization}`, {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to delete product data");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/simulation/getProductApi.ts b/app/src/services/simulation/getProductApi.ts
new file mode 100644
index 0000000..cf80013
--- /dev/null
+++ b/app/src/services/simulation/getProductApi.ts
@@ -0,0 +1,25 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getProductApi = async (productId: string, organization: string) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/productDatas?productId=${productId}&organization=${organization}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to fetch product data");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
\ No newline at end of file
diff --git a/app/src/services/simulation/getallProductsApi.ts b/app/src/services/simulation/getallProductsApi.ts
new file mode 100644
index 0000000..46627f9
--- /dev/null
+++ b/app/src/services/simulation/getallProductsApi.ts
@@ -0,0 +1,25 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getAllProductsApi = async ( organization: string) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/v2/AllProducts/${organization}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("Failed to fetch all products data");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ if (error instanceof Error) {
+ throw new Error(error.message);
+ } else {
+ throw new Error("An unknown error occurred");
+ }
+ }
+};
\ No newline at end of file
diff --git a/app/src/services/simulation/temp.md b/app/src/services/simulation/temp.md
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts
index 91576c7..8ec74cf 100644
--- a/app/src/store/simulation/useProductStore.ts
+++ b/app/src/store/simulation/useProductStore.ts
@@ -7,7 +7,7 @@ type ProductsStore = {
// Product-level actions
addProduct: (productName: string, productId: string) => void;
removeProduct: (productId: string) => void;
- updateProduct: (productId: string, updates: Partial<{ productName: string; eventsData: EventsSchema[] }>) => void;
+ updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
// Event-level actions
addEvent: (productId: string, event: EventsSchema) => void;
@@ -54,7 +54,7 @@ type ProductsStore = {
renameTrigger: (triggerUuid: string, newName: string) => void;
// Helper functions
- getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
+ getProductById: (productId: string) => { productName: string; productId: string; eventDatas: EventsSchema[] } | undefined;
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
@@ -72,7 +72,7 @@ export const useProductStore = create
()(
const newProduct = {
productName,
productId: productId,
- eventsData: []
+ eventDatas: []
};
state.products.push(newProduct);
});
@@ -98,7 +98,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- product.eventsData.push(event);
+ product.eventDatas.push(event);
}
});
},
@@ -107,7 +107,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- product.eventsData = product.eventsData.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
+ product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
}
});
},
@@ -116,7 +116,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event) {
Object.assign(event, updates);
}
@@ -129,7 +129,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
} else if (event && 'point' in event) {
@@ -143,7 +143,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
@@ -157,7 +157,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
if (point) {
@@ -175,7 +175,7 @@ export const useProductStore = create()(
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
if (point) {
@@ -195,7 +195,7 @@ export const useProductStore = create()(
removeAction: (actionUuid: string) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
// Handle ConveyorEventSchema
for (const point of (event as ConveyorEventSchema).points) {
@@ -219,7 +219,7 @@ export const useProductStore = create()(
updateAction: (actionUuid, updates) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
@@ -249,7 +249,7 @@ export const useProductStore = create()(
addTrigger: (actionUuid, trigger) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
@@ -278,7 +278,7 @@ export const useProductStore = create()(
removeTrigger: (triggerUuid) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
@@ -305,7 +305,7 @@ export const useProductStore = create()(
updateTrigger: (triggerUuid, updates) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
@@ -354,7 +354,7 @@ export const useProductStore = create()(
renameAction: (actionUuid, newName) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
@@ -383,7 +383,7 @@ export const useProductStore = create()(
renameTrigger: (triggerUuid, newName) => {
set((state) => {
for (const product of state.products) {
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
@@ -427,7 +427,7 @@ export const useProductStore = create()(
getEventByModelUuid: (productId, modelUuid) => {
const product = get().getProductById(productId);
if (!product) return undefined;
- return product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
},
getPointByUuid: (productId, modelUuid, pointUuid) => {
@@ -446,7 +446,7 @@ export const useProductStore = create()(
const product = get().products.find(p => p.productId === productId);
if (!product) return undefined;
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.actionUuid === actionUuid) {
@@ -470,7 +470,7 @@ export const useProductStore = create()(
const product = get().products.find(p => p.productId === productId);
if (!product) return undefined;
- for (const event of product.eventsData) {
+ for (const event of product.eventDatas) {
if ('points' in event) {
for (const point of (event as ConveyorEventSchema).points) {
for (const trigger of point.action?.triggers || []) {
@@ -504,7 +504,7 @@ export const useProductStore = create()(
getIsEventInProduct: (productId, modelUuid) => {
const product = get().getProductById(productId);
if (!product) return false;
- return product.eventsData.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ return product.eventDatas.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
}
}))
);
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index 12c0dc2..eb49368 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -126,7 +126,7 @@ type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSc
type productsSchema = {
productName: string;
productId: string;
- eventsData: EventsSchema[];
+ eventDatas: EventsSchema[];
}[]
@@ -135,6 +135,7 @@ interface ConveyorStatus extends ConveyorEventSchema {
isActive: boolean;
idleTime: number;
activeTime: number;
+
}
interface MachineStatus extends MachineEventSchema {
From d7a22f5bfbd4e5c9edc717aa1bbecb4414833fa5 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B
Date: Fri, 25 Apr 2025 16:06:24 +0530
Subject: [PATCH 08/13] feat: Refactor PickAndPlaceAction component to accept
props for pick and place points; enhance RoboticArmMechanics with action
handling and state management
---
.../actions/PickAndPlaceAction.tsx | 26 +-
.../mechanics/roboticArmMechanics.tsx | 366 +++++++++++-------
app/src/components/ui/list/List.tsx | 3 -
.../simulation/roboticArm/roboticArm.tsx | 2 +
app/src/modules/simulation/simulation.tsx | 2 +-
.../store/simulation/useSimulationStore.ts | 24 ++
6 files changed, 281 insertions(+), 142 deletions(-)
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/PickAndPlaceAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/PickAndPlaceAction.tsx
index 9574669..175a824 100644
--- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/PickAndPlaceAction.tsx
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/PickAndPlaceAction.tsx
@@ -1,13 +1,25 @@
import React from "react";
import EyeDropInput from "../../../../../ui/inputs/EyeDropInput";
-const PickAndPlaceAction: React.FC = () => {
- return (
- <>
- {}} />
- {}} />
- >
- );
+interface PickAndPlaceActionProps {
+ pickPointValue: string;
+ pickPointOnChange: (value: string) => void;
+ placePointValue: string;
+ placePointOnChange: (value: string) => void;
+}
+
+const PickAndPlaceAction: React.FC = ({
+ pickPointValue,
+ pickPointOnChange,
+ placePointValue,
+ placePointOnChange,
+}) => {
+ return (
+ <>
+
+
+ >
+ );
};
export default PickAndPlaceAction;
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx
index 9a044ac..78a32f5 100644
--- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx
@@ -4,7 +4,7 @@ import InputWithDropDown from '../../../../../ui/inputs/InputWithDropDown'
import RenameInput from '../../../../../ui/inputs/RenameInput'
import LabledDropdown from '../../../../../ui/inputs/LabledDropdown'
import Trigger from '../trigger/Trigger'
-import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
+import { useSelectedEventData, useSelectedProduct, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { AddIcon, RemoveIcon, ResizeHeightIcon } from '../../../../../icons/ExportCommonIcons'
import { handleResize } from '../../../../../../functions/handleResizePannel'
@@ -12,159 +12,263 @@ import PickAndPlaceAction from '../actions/PickAndPlaceAction'
function RoboticArmMechanics() {
const actionsContainerRef = useRef(null);
-
- const [activeOption, setActiveOption] = useState("pickAndPlace");
- const [selectedItem, setSelectedItem] = useState<{ item: { uuid: string; name: string } | null; }>({ item: null });
+ const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default");
+ const [selectedPointData, setSelectedPointData] = useState();
const { selectedEventData } = useSelectedEventData();
- const { getEventByModelUuid, addAction } = useProductStore();
+ const { getPointByUuid, updateEvent, updateAction, addAction, removeAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
-
- const availableActions = {
- defaultOption: "pickAndPlace",
- options: ["pickAndPlace"]
- };
- const [actions, setActions] = useState<{ uuid: string; name: string }[]>([]);
+ const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
useEffect(() => {
- const event = getCurrentEventData();
- const actionList = getActionList(event as RoboticArmEventSchema);
- setActions(actionList);
-
- if (actionList.length > 0 && !selectedItem.item) {
- setSelectedItem({ item: actionList[0] });
+ if (selectedEventData) {
+ const point = getPointByUuid(
+ selectedProduct.productId,
+ selectedEventData.data.modelUuid,
+ selectedEventData.selectedPoint
+ ) as RoboticArmPointSchema | undefined;
+ if (point) {
+ setSelectedPointData(point);
+ setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace");
+ if (point.actions.length > 0 && !selectedAction.actionId) {
+ setSelectedAction(point.actions[0].actionUuid, point.actions[0].actionName);
+ }
+ }
+ } else {
+ clearSelectedAction();
}
}, [selectedEventData, selectedProduct]);
- const getCurrentEventData = () => {
- if (!selectedEventData?.data || !selectedProduct) return null;
- return getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid) || null;
- };
-
- const getActionList = (event: RoboticArmEventSchema) => {
- if (!event || !('point' in event)) return [];
-
- return event.point.actions.flatMap(
- (action) =>
- action.triggers.map((trigger) => ({
- uuid: trigger.triggerUuid,
- name: trigger.triggerName,
- }))
- ) || [];
- };
-
- const handleActionToggle = (actionUuid: string) => {
- const action = actions.find(a => a.uuid === actionUuid);
- if (action) {
- setSelectedItem({ item: action });
- }
+ const handleActionSelect = (actionUuid: string, actionName: string) => {
+ setSelectedAction(actionUuid, actionName);
};
const handleAddAction = () => {
- if (selectedEventData) {
- const newEvent = {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: `Action ${actions.length + 1}`,
- actionType: "pickAndPlace" as const,
- process: {
- startPoint: null as [number, number, number] | null,
- endPoint: null as [number, number, number] | null
- },
- triggers: [] as TriggerSchema[]
- }
- addAction(
- selectedProduct.productId,
- selectedEventData?.data.modelUuid,
- selectedEventData?.selectedPoint,
- newEvent
- )
- }
+ if (!selectedEventData || !selectedPointData) return;
+
+ const newAction = {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: `Action ${selectedPointData.actions.length + 1}`,
+ actionType: "pickAndPlace" as "pickAndPlace",
+ process: {
+ startPoint: null,
+ endPoint: null
+ },
+ triggers: [] as TriggerSchema[]
+ };
+
+ addAction(
+ selectedProduct.productId,
+ selectedEventData.data.modelUuid,
+ selectedEventData.selectedPoint,
+ newAction
+ );
+
+ const updatedPoint = {
+ ...selectedPointData,
+ actions: [...selectedPointData.actions, newAction]
+ };
+ setSelectedPointData(updatedPoint);
+ setSelectedAction(newAction.actionUuid, newAction.actionName);
};
const handleDeleteAction = (actionUuid: string) => {
+ if (!selectedPointData) return;
+ removeAction(actionUuid);
+ const newActions = selectedPointData.actions.filter(a => a.actionUuid !== actionUuid);
+
+ const updatedPoint = {
+ ...selectedPointData,
+ actions: newActions
+ };
+ setSelectedPointData(updatedPoint);
+
+ if (selectedAction.actionId === actionUuid) {
+ if (newActions.length > 0) {
+ setSelectedAction(newActions[0].actionUuid, newActions[0].actionName);
+ } else {
+ clearSelectedAction();
+ }
+ }
};
+ const handleRenameAction = (newName: string) => {
+ if (!selectedAction.actionId) return;
+ updateAction(
+ selectedAction.actionId,
+ { actionName: newName }
+ );
+
+ if (selectedPointData) {
+ const updatedActions = selectedPointData.actions.map(action =>
+ action.actionUuid === selectedAction.actionId
+ ? { ...action, actionName: newName }
+ : action
+ );
+ setSelectedPointData({
+ ...selectedPointData,
+ actions: updatedActions
+ });
+ }
+ };
+
+ const handleSpeedChange = (value: string) => {
+ if (!selectedEventData) return;
+ updateEvent(
+ selectedProduct.productId,
+ selectedEventData.data.modelUuid,
+ { speed: parseFloat(value) }
+ );
+ };
+
+ const handlePickPointChange = (value: string) => {
+ if (!selectedAction.actionId || !selectedPointData) return;
+ const [x, y, z] = value.split(',').map(Number);
+
+ updateAction(
+ selectedAction.actionId,
+ {
+ process: {
+ startPoint: [x, y, z] as [number, number, number],
+ endPoint: selectedPointData.actions.find(a => a.actionUuid === selectedAction.actionId)?.process.endPoint || null
+ }
+ }
+ );
+ };
+
+ const handlePlacePointChange = (value: string) => {
+ if (!selectedAction.actionId || !selectedPointData) return;
+ const [x, y, z] = value.split(',').map(Number);
+
+ updateAction(
+ selectedAction.actionId,
+ {
+ process: {
+ startPoint: selectedPointData.actions.find(a => a.actionUuid === selectedAction.actionId)?.process.startPoint || null,
+ endPoint: [x, y, z] as [number, number, number]
+ }
+ }
+ );
+ };
+
+ const availableActions = {
+ defaultOption: "pickAndPlace",
+ options: ["pickAndPlace"],
+ };
+
+ const currentSpeed = selectedEventData?.data.type === "roboticArm"
+ ? selectedEventData.data.speed.toString()
+ : "0.5";
+
+ const currentAction = selectedPointData?.actions.find(a => a.actionUuid === selectedAction.actionId);
+ const currentPickPoint = currentAction?.process.startPoint
+ ? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}`
+ : "";
+ const currentPlacePoint = currentAction?.process.endPoint
+ ? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}`
+ : "";
+
return (
<>
-
-
-
- { }}
- onChange={(value) => console.log(value)}
- />
-
-
-
-
-
-
-
Actions
-
handleAddAction()}>
-
Add
+ {selectedEventData && selectedPointData && (
+ <>
+
+
+
+ { }}
+ onChange={handleSpeedChange}
+ />
+
-
-
- {actions.map((action) => (
-
-
handleActionToggle(action.uuid)}
- >
-
-
- {actions.length > 1 && (
-
handleDeleteAction(action.uuid)}
- >
-
-
- )}
+
+
+
+
-
handleResize(e, actionsContainerRef)}
- >
-
+
+
+
+ {selectedPointData.actions.map((action) => (
+
+
handleActionSelect(action.actionUuid, action.actionName)}
+ >
+
+
+ {selectedPointData.actions.length > 1 && (
+
handleDeleteAction(action.actionUuid)}
+ >
+
+
+ )}
+
+ ))}
+
+
handleResize(e, actionsContainerRef)}
+ >
+
+
+
-
-
-
-
-
-
-
-
setActiveOption(option)}
- />
- {activeOption === "pickAndPlace" && }
-
-
-
-
-
+
+ {selectedAction.actionId && currentAction && (
+
+
+
+
+
+
{ }}
+ disabled={true}
+ />
+
+
+
+
+
+
+ )}
+ >
+ )}
>
)
}
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index cac0b43..ac21c5a 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -142,9 +142,6 @@ const List: React.FC
= ({ items = [], remove }) => {
)
);
}
-
- console.log('newName: ', newName);
-
}
const checkZoneNameDuplicate = (name: string) => {
return zones.some(
diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx
index 89f6b76..d403c6a 100644
--- a/app/src/modules/simulation/roboticArm/roboticArm.tsx
+++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx
@@ -94,6 +94,8 @@ function RoboticArm() {
+ <>>
+
>
);
}
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 5ca0ec5..757a9ef 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -23,7 +23,7 @@ function Simulation() {
}, [events])
useEffect(() => {
- // console.log('products: ', products);
+ console.log('products: ', products);
}, [products])
return (
diff --git a/app/src/store/simulation/useSimulationStore.ts b/app/src/store/simulation/useSimulationStore.ts
index ae6ac81..5085688 100644
--- a/app/src/store/simulation/useSimulationStore.ts
+++ b/app/src/store/simulation/useSimulationStore.ts
@@ -90,4 +90,28 @@ export const useSelectedProduct = create()(
});
},
}))
+);
+
+interface SelectedActionState {
+ selectedAction: { actionId: string; actionName: string };
+ setSelectedAction: (actionId: string, actionName: string) => void;
+ clearSelectedAction: () => void;
+}
+
+export const useSelectedAction = create()(
+ immer((set) => ({
+ selectedAction: { actionId: '', actionName: '' },
+ setSelectedAction: (actionId, actionName) => {
+ set((state) => {
+ state.selectedAction.actionId = actionId;
+ state.selectedAction.actionName = actionName;
+ });
+ },
+ clearSelectedAction: () => {
+ set((state) => {
+ state.selectedAction.actionId = '';
+ state.selectedAction.actionName = '';
+ });
+ },
+ }))
);
\ No newline at end of file
From 70a99316ba3f4d1385f05f05fcd100bc1cb44c0e Mon Sep 17 00:00:00 2001
From: Poovizhi99
Date: Fri, 25 Apr 2025 17:57:38 +0530
Subject: [PATCH 09/13] added stationed-pickup and pickup to drop functionality
added
---
.../instances/animator/vehicleAnimator.tsx | 206 ++++++++++++++----
.../instances/instance/vehicleInstance.tsx | 139 ++++++++----
.../vehicle/instances/vehicleInstances.tsx | 6 +-
.../modules/simulation/vehicle/vehicles.tsx | 68 +++---
4 files changed, 288 insertions(+), 131 deletions(-)
diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
index 137d679..0d59f2b 100644
--- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
+++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
@@ -1,61 +1,179 @@
import { useFrame, useThree } from '@react-three/fiber';
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useRef, useState } from 'react';
+import { useFloorItems } from '../../../../../store/store';
+import * as THREE from 'three';
+import { Line } from '@react-three/drei';
+import { useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
+import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
interface VehicleAnimatorProps {
- path: [number, number, number][];
- handleCallBack: () => void;
- currentPhase: string;
- agvUuid: number
+ path: [number, number, number][];
+ handleCallBack: () => void;
+ currentPhase: string;
+ agvUuid: number;
+ agvDetail: any;
}
+function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail }: VehicleAnimatorProps) {
+ const { updateVehicleLoad, vehicles } = useVehicleStore();
+ const { isPaused } = usePauseButtonStore();
+ const { speed } = useAnimationPlaySpeed();
+ const { isReset } = useResetButtonStore();
+ const [restRotation, setRestingRotation] = useState(true);
+ const [progress, setProgress] = useState(0);
+ const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
+ const { scene } = useThree();
+ const progressRef = useRef(0);
+ const movingForward = useRef(true);
+ const completedRef = useRef(false);
+ let startTime: number;
+ let pausedTime: number;
+ let fixedInterval: number;
-function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid }: VehicleAnimatorProps) {
- const [progress, setProgress] = useState(0)
- const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
- const { scene } = useThree();
+ useEffect(() => {
+ if (currentPhase === 'stationed-pickup' && path.length > 0) {
+ setCurrentPath(path);
+ } else if (currentPhase === 'pickup-drop' && path.length > 0) {
+ setCurrentPath(path);
+ } else if (currentPhase === 'drop-pickup' && path.length > 0) {
+ setCurrentPath(path);
+ }
+ }, [currentPhase, path]);
- useEffect(() => {
+ useEffect(() => {
+ setProgress(0);
+ completedRef.current = false;
+ }, [currentPath]);
- if (currentPhase === 'stationed-pickup' && path.length > 0) {
- setCurrentPath(path);
+ useFrame((_, delta) => {
+ const object = scene.getObjectByProperty('uuid', agvUuid);
+ if (!object || currentPath.length < 2) return;
+ if (isPaused) return;
+
+ let totalDistance = 0;
+ const distances = [];
+
+ for (let i = 0; i < currentPath.length - 1; i++) {
+ const start = new THREE.Vector3(...currentPath[i]);
+ const end = new THREE.Vector3(...currentPath[i + 1]);
+ const segmentDistance = start.distanceTo(end);
+ distances.push(segmentDistance);
+ totalDistance += segmentDistance;
+ }
+
+ let coveredDistance = progressRef.current;
+ let accumulatedDistance = 0;
+ let index = 0;
+
+ while (
+ index < distances.length &&
+ coveredDistance > accumulatedDistance + distances[index]
+ ) {
+ accumulatedDistance += distances[index];
+ index++;
+ }
+
+ if (index < distances.length) {
+ const start = new THREE.Vector3(...currentPath[index]);
+ const end = new THREE.Vector3(...currentPath[index + 1]);
+ const segmentDistance = distances[index];
+
+ const currentDirection = new THREE.Vector3().subVectors(end, start).normalize();
+ const targetAngle = Math.atan2(currentDirection.x, currentDirection.z);
+ const rotationSpeed = 2.0;
+ const currentAngle = object.rotation.y;
+
+ let angleDifference = targetAngle - currentAngle;
+ if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI;
+ if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI;
+
+ const maxRotationStep = rotationSpeed * delta;
+ object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep);
+
+ const isAligned = Math.abs(angleDifference) < 0.01;
+
+ if (isAligned) {
+ progressRef.current += delta * (speed * agvDetail.speed);
+ coveredDistance = progressRef.current;
+
+ const t = (coveredDistance - accumulatedDistance) / segmentDistance;
+ const position = start.clone().lerp(end, t);
+ object.position.copy(position);
+ }
+ }
+
+ if (progressRef.current >= totalDistance) {
+ if (restRotation) {
+ const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));
+ object.quaternion.slerp(targetQuaternion, delta * 2);
+ const angleDiff = object.quaternion.angleTo(targetQuaternion);
+ if (angleDiff < 0.01) {
+ let objectRotation = agvDetail.point.rotation
+ object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]);
+ setRestingRotation(false);
}
+ return;
+ }
+ }
- }, [currentPhase, path])
- useFrame((_, delta) => {
- if (!path || path.length < 2) return;
+ if (progressRef.current >= totalDistance) {
+ setRestingRotation(true);
+ progressRef.current = 0;
+ movingForward.current = !movingForward.current;
+ setCurrentPath([]);
+ handleCallBack();
+ if (currentPhase === 'pickup-drop') {
+ requestAnimationFrame(firstFrame);
+ }
+ }
+ });
- const object = scene.getObjectByProperty("uuid", agvUuid)
- if (!object) return;
+ function firstFrame() {
+ const unLoadDuration = agvDetail.point.action.unLoadDuration;
+ const droppedMaterial = agvDetail.currentLoad;
+ fixedInterval = (unLoadDuration / droppedMaterial) * 1000;
+ if (!isPaused) {
+ step(droppedMaterial);
+ } else {
+ pausedTime = performance.now();
+ step(droppedMaterial);
+ }
+ }
- setProgress(prev => {
- const next = prev + delta * 0.1; // speed
- return next >= 1 ? 1 : next;
- });
+ function step(droppedMaterial: number) {
+ if (!isPaused) {
+ startTime = performance.now();
+ const elapsedTime = performance.now() - startTime - pausedTime;
+ if (elapsedTime >= fixedInterval) {
+ let droppedMat = droppedMaterial - 1;
+ updateVehicleLoad(agvDetail.modelUuid, droppedMat);
+ if (droppedMat === 0) return;
+ startTime = performance.now();
+ pausedTime = 0;
+ requestAnimationFrame(() => step(droppedMat));
+ } else {
+ requestAnimationFrame(() => step(droppedMaterial));
+ }
+ } else {
+ requestAnimationFrame(() => firstFrame);
+ }
+ }
- const totalSegments = path.length - 1;
- const segmentIndex = Math.floor(progress * totalSegments);
- const t = progress * totalSegments - segmentIndex;
-
- const start = path[segmentIndex];
- const end = path[segmentIndex + 1] || start;
-
- // Directly set position without creating a new Vector3
- object.position.x = start[0] + (end[0] - start[0]) * t;
- object.position.y = start[1] + (end[1] - start[1]) * t;
- object.position.z = start[2] + (end[2] - start[2]) * t;
- });
- // useFrame(() => {
- // if (currentPath.length === 0) return;
- // const object = scene.getObjectByProperty("uuid", agvUuid);
- // if (!object) return;
-
-
-
- // })
- return (
+ return (
+ <>
+ {currentPath.length > 0 && (
<>
+
+ {currentPath.map((point, index) => (
+
+
+
+
+ ))}
>
- )
+ )}
+ >
+ );
}
-export default VehicleAnimator
\ No newline at end of file
+export default VehicleAnimator;
\ No newline at end of file
diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
index 646dabd..98d037c 100644
--- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
+++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
@@ -1,67 +1,122 @@
-import React, { useCallback, useEffect, useState } from 'react'
-import VehicleAnimator from '../animator/vehicleAnimator'
-import * as THREE from "three";
+import React, { useCallback, useEffect, useState } from 'react';
+import VehicleAnimator from '../animator/vehicleAnimator';
+import * as THREE from 'three';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/store';
import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
-function VehicleInstance({ agvDetails }: any) {
+function VehicleInstance({ agvDetail }: any) {
const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore();
- const { setVehicleActive, setVehicleState } = useVehicleStore();
- const [currentPhase, setCurrentPhase] = useState<(string)>("stationed");
+ const { vehicles, setVehicleActive, setVehicleState, updateVehicleLoad } = useVehicleStore();
+ const [currentPhase, setCurrentPhase] = useState('stationed');
const [path, setPath] = useState<[number, number, number][]>([]);
- const computePath = useCallback((start: any, end: any) => {
+ const computePath = useCallback(
+ (start: any, end: any) => {
+ try {
+ const navMeshQuery = new NavMeshQuery(navMesh);
+ const { path: segmentPath } = navMeshQuery.computePath(start, end);
+ return (
+ segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || []
+ );
+ } catch {
+ return [];
+ }
+ },
+ [navMesh]
+ );
-
- try {
- const navMeshQuery = new NavMeshQuery(navMesh);
- const { path: segmentPath } = navMeshQuery.computePath(start, end);
- return (
- segmentPath?.map(
- ({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]
- ) || []
- );
- } catch {
- return [];
- }
- }, [navMesh]);
+ function vehicleStatus(modelid: string, status: string) {
+ // console.log(`AGV ${modelid}: ${status}`);
+ }
useEffect(() => {
- // const pickupToDropPath = computePath(pickup, drop);
- // const dropToPickupPath = computePath(drop, pickup);
-
if (isPlaying) {
- if (!agvDetails.isActive && agvDetails.state == "idle" && currentPhase == "stationed") {
- const toPickupPath = computePath(new THREE.Vector3(agvDetails.position[0], agvDetails.position[1], agvDetails.position[2]), agvDetails.point.action.pickUpPoint);
- setPath(toPickupPath)
- setVehicleActive(agvDetails.modelUuid, true)
- setVehicleState(agvDetails.modelUuid, "running")
- setCurrentPhase("stationed-pickup")
- //
+ if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') {
+ const toPickupPath = computePath(
+ new THREE.Vector3(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]),
+ agvDetail.point.action.pickUpPoint
+ );
+ setPath(toPickupPath);
+ setVehicleActive(agvDetail.modelUuid, true);
+ setVehicleState(agvDetail.modelUuid, 'running');
+ setCurrentPhase('stationed-pickup');
+ vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup');
+ return;
+ } else if (
+ !agvDetail.isActive &&
+ agvDetail.state === 'idle' &&
+ currentPhase === 'picking'
+ ) {
+ setTimeout(() => {
+ updateVehicleLoad(agvDetail.modelUuid, 2);
+ }, 5000);
+
+ if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) {
+ const toDrop = computePath(
+ agvDetail.point.action.pickUpPoint,
+ agvDetail.point.action.unLoadPoint
+ );
+ setPath(toDrop);
+ setVehicleActive(agvDetail.modelUuid, true);
+ setVehicleState(agvDetail.modelUuid, 'running');
+ setCurrentPhase('pickup-drop');
+ vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point');
+ }
+ } else if (
+ !agvDetail.isActive &&
+ agvDetail.state === 'idle' &&
+ currentPhase === 'dropping' &&
+ agvDetail.currentLoad === 0
+ ) {
+ const dropToPickup = computePath(
+ agvDetail.point.action.unLoadPoint,
+ agvDetail.point.action.pickUpPoint
+ );
+ setPath(dropToPickup);
+ setVehicleActive(agvDetail.modelUuid, true);
+ setVehicleState(agvDetail.modelUuid, 'running');
+ setCurrentPhase('drop-pickup');
+ vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point');
}
}
- }, [agvDetails, currentPhase, path, isPlaying])
+ }, [vehicles, currentPhase, path, isPlaying]);
function handleCallBack() {
- if (currentPhase === "stationed-pickup") {
- setVehicleActive(agvDetails.modelUuid, false)
- setVehicleState(agvDetails.modelUuid, "idle")
- setCurrentPhase("picking")
- setPath([])
+ if (currentPhase === 'stationed-pickup') {
+ setVehicleActive(agvDetail.modelUuid, false);
+ setVehicleState(agvDetail.modelUuid, 'idle');
+ setCurrentPhase('picking');
+ vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material');
+ setPath([]);
+ } else if (currentPhase === 'pickup-drop') {
+ setVehicleActive(agvDetail.modelUuid, false);
+ setVehicleState(agvDetail.modelUuid, 'idle');
+ setCurrentPhase('dropping');
+ vehicleStatus(agvDetail.modelUuid, 'Reached drop point');
+ setPath([]);
+ } else if (currentPhase === 'drop-pickup') {
+ setVehicleActive(agvDetail.modelUuid, false);
+ setVehicleState(agvDetail.modelUuid, 'idle');
+ setCurrentPhase('picking');
+ setPath([]);
+ vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete');
}
}
-
return (
<>
-
-
-
+
>
- )
+ );
}
-export default VehicleInstance
\ No newline at end of file
+export default VehicleInstance;
\ No newline at end of file
diff --git a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx
index f3f1435..2a0070b 100644
--- a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx
+++ b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx
@@ -1,12 +1,14 @@
import React from 'react'
import VehicleInstance from './instance/vehicleInstance'
+import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'
-function VehicleInstances({ vehicles }: any) {
+function VehicleInstances() {
+ const { vehicles } = useVehicleStore();
return (
<>
{vehicles.map((val: any, i: any) =>
-
+
)}
>
diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx
index b9bc07b..6c5ea34 100644
--- a/app/src/modules/simulation/vehicle/vehicles.tsx
+++ b/app/src/modules/simulation/vehicle/vehicles.tsx
@@ -1,34 +1,36 @@
import React, { useEffect } from 'react'
import VehicleInstances from './instances/vehicleInstances';
-
import { useVehicleStore } from '../../../store/simulation/useVehicleStore';
+import { useFloorItems } from '../../../store/store';
function Vehicles() {
const { vehicles, addVehicle } = useVehicleStore();
- const vehicleStatusSample: VehicleStatus[] = [
+ const { floorItems } = useFloorItems();
+
+ const vehicleStatusSample: VehicleEventSchema[] = [
{
- modelUuid: "2c01ed76-359a-485b-83d4-052cfcdb9d89",
+ modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74",
modelName: "AGV",
- position: [10, 0, 5],
+ position: [97.9252965204558, 0, 37.96138815638661],
rotation: [0, 0, 0],
state: "idle",
type: "vehicle",
speed: 2.5,
point: {
uuid: "point-789",
- position: [93.42159216649789, 0, 23.790878603572857],
+ position: [0, 1, 0],
rotation: [0, 0, 0],
action: {
actionUuid: "action-456",
actionName: "Deliver to Zone A",
actionType: "travel",
material: "crate",
- unLoadDuration: 15,
- loadCapacity: 5,
- pickUpPoint: { x: 5, y: 0, z: 3 },
- unLoadPoint: { x: 20, y: 0, z: 10 },
+ unLoadDuration: 10,
+ loadCapacity: 2,
+ pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 },
+ unLoadPoint: { x: 105.71483985219794, y: 0, z: 28.66321267938962 },
triggers: [
{
triggerUuid: "trig-001",
@@ -50,18 +52,12 @@ function Vehicles() {
}
]
}
- },
- productId: "prod-890",
- isActive: false,
- idleTime: 0,
- activeTime: 0,
- currentLoad: 0,
- distanceTraveled: 0
+ }
},
{
- modelUuid: "311130b9-4f2e-425a-b3b5-5039cb348806",
+ modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4",
modelName: "AGV",
- position: [95.69567023145055, 0, 33.18042399595448],
+ position: [89.61609306554463, 0, 33.634136622267356],
rotation: [0, 0, 0],
state: "idle",
type: "vehicle",
@@ -75,9 +71,9 @@ function Vehicles() {
actionName: "Deliver to Zone A",
actionType: "travel",
material: "crate",
- unLoadDuration: 15,
- loadCapacity: 5,
- pickUpPoint: { x: 5, y: 0, z: 3 },
+ unLoadDuration: 10,
+ loadCapacity: 2,
+ pickUpPoint: { x: 90, y: 0, z: 28 },
unLoadPoint: { x: 20, y: 0, z: 10 },
triggers: [
{
@@ -100,17 +96,11 @@ function Vehicles() {
}
]
}
- },
- productId: "prod-890",
- isActive: false,
- idleTime: 0,
- activeTime: 0,
- currentLoad: 0,
- distanceTraveled: 0
+ }
}, {
- modelUuid: "fa54132c-8333-4832-becb-5281f5e11549",
- modelName: "AGV",
- position: [102.71483985219794, 0, 23.66321267938962],
+ modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79",
+ modelName: "forklift",
+ position: [98.85729337188162, 0, 38.36616546567653],
rotation: [0, 0, 0],
state: "idle",
type: "vehicle",
@@ -126,7 +116,7 @@ function Vehicles() {
material: "crate",
unLoadDuration: 15,
loadCapacity: 5,
- pickUpPoint: { x: 5, y: 0, z: 3 },
+ pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 },
unLoadPoint: { x: 20, y: 0, z: 10 },
triggers: [
{
@@ -149,13 +139,7 @@ function Vehicles() {
}
]
}
- },
- productId: "prod-890",
- isActive: false,
- idleTime: 0,
- activeTime: 0,
- currentLoad: 0,
- distanceTraveled: 0
+ }
}
];
@@ -163,7 +147,7 @@ function Vehicles() {
useEffect(() => {
addVehicle('123', vehicleStatusSample[0]);
addVehicle('123', vehicleStatusSample[1]);
- addVehicle('123', vehicleStatusSample[2]);
+ // addVehicle('123', vehicleStatusSample[2]);
}, [])
useEffect(() => {
@@ -173,9 +157,7 @@ function Vehicles() {
return (
<>
-
-
-
+
>
)
}
From 81b353307b01bee7c6f15ff3eb2d755a76e7c456 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B
Date: Fri, 25 Apr 2025 18:29:01 +0530
Subject: [PATCH 10/13] feat: Integrate upsertProductOrEventApi in Simulations
and Products components; adjust loadInitialFloorItems to accept
renderDistance parameter; update material handling in addAssetModel and
Vehicles components
---
.../sidebarRight/simulation/Simulations.tsx | 6 ++++++
.../builder/IntialLoad/loadInitialFloorItems.ts | 4 ++--
.../builder/geomentries/assets/addAssetModel.ts | 15 +++++++--------
.../modules/builder/groups/floorItemsGroup.tsx | 4 ++--
app/src/modules/simulation/products/products.tsx | 14 ++++++++++++++
.../roboticArm/instances/roboticArmInstances.tsx | 1 -
.../modules/simulation/roboticArm/roboticArm.tsx | 9 ++-------
app/src/modules/simulation/vehicle/vehicles.tsx | 2 --
.../simulation/UpsertProductOrEventApi.ts | 2 +-
app/src/types/simulationTypes.d.ts | 1 -
10 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
index d6b4ac8..926ce44 100644
--- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
+++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
@@ -12,6 +12,7 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
import { generateUUID } from "three/src/math/MathUtils";
import RenderOverlay from "../../../templates/Overlay";
import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
+import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
interface Event {
pathName: string;
@@ -75,6 +76,11 @@ const Simulations: React.FC = () => {
const handleAddEventToProduct = () => {
if (selectedAsset) {
addEvent(selectedProduct.productId, selectedAsset);
+ // upsertProductOrEventApi({
+ // productName: selectedProduct.productName,
+ // productId: selectedProduct.productId,
+ // eventDatas: selectedAsset
+ // });
clearSelectedAsset();
}
};
diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
index 0359f1f..c46c0e7 100644
--- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
@@ -14,6 +14,7 @@ async function loadInitialFloorItems(
itemsGroup: Types.RefGroup,
setFloorItems: Types.setFloorItemSetState,
addEvent: (event: EventsSchema) => void,
+ renderDistance: number
): Promise {
if (!itemsGroup.current) return;
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -65,7 +66,7 @@ async function loadInitialFloorItems(
const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z);
- if (cameraPosition.distanceTo(itemPosition) < 50) {
+ if (cameraPosition.distanceTo(itemPosition) < renderDistance) {
await new Promise(async (resolve) => {
// Check Three.js Cache
@@ -210,7 +211,6 @@ function processLoadedModel(
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Vehicle Action",
actionType: "travel",
- material: null,
unLoadDuration: 5,
loadCapacity: 10,
pickUpPoint: null,
diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
index 670c7b5..d7c278c 100644
--- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts
+++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
@@ -202,7 +202,7 @@ async function handleModelLoad(
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index}`,
actionType: 'default',
- material: 'inherit',
+ material: 'Default Material',
delay: 0,
spawnInterval: 5,
spawnCount: 1,
@@ -226,9 +226,8 @@ async function handleModelLoad(
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Vehicle Action",
+ actionName: "Action 1",
actionType: "travel",
- material: null,
unLoadDuration: 5,
loadCapacity: 10,
pickUpPoint: null,
@@ -254,11 +253,11 @@ async function handleModelLoad(
actions: [
{
actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Pick and Place",
+ actionName: "Action 1",
actionType: "pickAndPlace",
process: {
- startPoint: [0, 0, 0],
- endPoint: [0, 0, 0]
+ startPoint: null,
+ endPoint: null
},
triggers: []
}
@@ -280,10 +279,10 @@ async function handleModelLoad(
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Process Action",
+ actionName: "Action 1",
actionType: "process",
processTime: 10,
- swapMaterial: "material-id",
+ swapMaterial: "Default Material",
triggers: []
}
}
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index 241f628..f3f5050 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -75,7 +75,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
gltfLoaderWorker.postMessage({ floorItems: data });
} else {
gltfLoaderWorker.postMessage({ floorItems: [] });
- loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
+ loadInitialFloorItems(itemsGroup, setFloorItems, addEvent, renderDistance);
updateLoadingProgress(100);
}
});
@@ -94,7 +94,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
updateLoadingProgress(progress);
if (loadedAssets === totalAssets) {
- loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
+ loadInitialFloorItems(itemsGroup, setFloorItems, addEvent, renderDistance);
updateLoadingProgress(100);
}
});
diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx
index 2ddd7d1..b883824 100644
--- a/app/src/modules/simulation/products/products.tsx
+++ b/app/src/modules/simulation/products/products.tsx
@@ -2,6 +2,8 @@ import React, { useEffect } from 'react'
import { useProductStore } from '../../../store/simulation/useProductStore'
import * as THREE from 'three';
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
+import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProductOrEventApi';
+import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
function Products() {
const { products, addProduct } = useProductStore();
@@ -12,10 +14,22 @@ function Products() {
const id = THREE.MathUtils.generateUUID();
const name = 'Product 1';
addProduct(name, id);
+ // upsertProductOrEventApi({ productName: name, productId: id }).then((data) => {
+ // console.log('data: ', data);
+ // });
setSelectedProduct(id, name);
}
}, [products])
+ useEffect(() => {
+ // const email = localStorage.getItem('email')
+ // const organization = (email!.split("@")[1]).split(".")[0];
+ // console.log(organization);
+ // getAllProductsApi(organization).then((data) => {
+ // console.log('data: ', data);
+ // })
+ }, [])
+
return (
<>
>
diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
index 415c1d3..46125db 100644
--- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
@@ -5,7 +5,6 @@ import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
function RoboticArmInstances() {
const { armBots } = useArmBotStore();
-
return (
<>
diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx
index d403c6a..52382db 100644
--- a/app/src/modules/simulation/roboticArm/roboticArm.tsx
+++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx
@@ -3,15 +3,11 @@ import RoboticArmInstances from "./instances/roboticArmInstances";
import { useArmBotStore } from "../../../store/simulation/useArmBotStore";
function RoboticArm() {
- const { armBots, addArmBot, addCurrentAction } = useArmBotStore();
+ const { armBots, addArmBot, removeArmBot, 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],
@@ -80,6 +76,7 @@ function RoboticArm() {
];
useEffect(() => {
+ removeArmBot(armBotStatusSample[0].modelUuid);
addArmBot('123', armBotStatusSample[0]);
// addCurrentAction('armbot-xyz-001', 'action-001');
}, []);
@@ -94,8 +91,6 @@ function RoboticArm() {
- <>>
-
>
);
}
diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx
index 3364717..1da7ced 100644
--- a/app/src/modules/simulation/vehicle/vehicles.tsx
+++ b/app/src/modules/simulation/vehicle/vehicles.tsx
@@ -24,7 +24,6 @@ function Vehicles() {
actionUuid: "action-456",
actionName: "Deliver to Zone A",
actionType: "travel",
- material: "crate",
unLoadDuration: 15,
loadCapacity: 5,
pickUpPoint: { x: 5, y: 0, z: 3 },
@@ -68,7 +67,6 @@ function Vehicles() {
actionUuid: "action-456",
actionName: "Deliver to Zone A",
actionType: "travel",
- material: "crate",
unLoadDuration: 15,
loadCapacity: 5,
pickUpPoint: { x: 5, y: 0, z: 3 },
diff --git a/app/src/services/simulation/UpsertProductOrEventApi.ts b/app/src/services/simulation/UpsertProductOrEventApi.ts
index 27fa126..e2f45d1 100644
--- a/app/src/services/simulation/UpsertProductOrEventApi.ts
+++ b/app/src/services/simulation/UpsertProductOrEventApi.ts
@@ -1,6 +1,6 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-export const addProductOrEventApi = async (body: any) => {
+export const upsertProductOrEventApi = async (body: any) => {
try {
const response = await fetch(`${url_Backend_dwinzo}/api/v2/UpsertProductOrEvent`, {
method: "POST",
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index eb49368..3293699 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -42,7 +42,6 @@ interface VehiclePointSchema {
actionUuid: string;
actionName: string;
actionType: "travel";
- material: string | null;
unLoadDuration: number;
loadCapacity: number;
pickUpPoint: { x: number; y: number, z: number } | null;
From 1ad0243204a9741ac21ed8f1b5144a72135d57cb Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B
Date: Fri, 25 Apr 2025 19:31:56 +0530
Subject: [PATCH 11/13] feat: Add AddOrRemoveEventsInProducts component for
event management in products; refactor TriggerConnector and update
PointsCreator to improve event handling and mesh identification
---
.../events/points/creator/pointsCreator.tsx | 4 +
.../events/addOrRemoveEventsInProducts.tsx | 124 ++++++++++++++++++
.../modules/simulation/products/products.tsx | 8 +-
app/src/modules/simulation/simulation.tsx | 2 +-
.../simulation/simulator/simulator.tsx | 11 +-
.../triggers/connector/triggerConnector.tsx | 75 ++++-------
6 files changed, 170 insertions(+), 54 deletions(-)
create mode 100644 app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
index 1b3defa..bc2f4db 100644
--- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
+++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
@@ -66,6 +66,7 @@ function PointsCreator() {
{event.points.map((point, j) => (
(sphereRefs.current[point.uuid] = el!)}
onClick={(e) => {
@@ -90,6 +91,7 @@ function PointsCreator() {
return (
(sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
@@ -112,6 +114,7 @@ function PointsCreator() {
return (
(sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
@@ -134,6 +137,7 @@ function PointsCreator() {
return (
(sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
diff --git a/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx b/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
new file mode 100644
index 0000000..9eececc
--- /dev/null
+++ b/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
@@ -0,0 +1,124 @@
+import { useThree } from '@react-three/fiber'
+import { useEffect } from 'react'
+import { Object3D } from 'three';
+import { useSubModuleStore } from '../../../../store/useModuleStore';
+import { useLeftData, useTopData } from '../../../../store/visualization/useZone3DWidgetStore';
+import { useEventsStore } from '../../../../store/simulation/useEventsStore';
+import { useProductStore } from '../../../../store/simulation/useProductStore';
+import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
+import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
+
+function AddOrRemoveEventsInProducts() {
+ const { gl, raycaster, scene } = useThree();
+ const { subModule } = useSubModuleStore();
+ const { setTop } = useTopData();
+ const { setLeft } = useLeftData();
+ const { getIsEventInProduct } = useProductStore();
+ const { getEventByModelUuid } = useEventsStore();
+ const { selectedProduct } = useSelectedProduct();
+ const { selectedAsset, setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
+
+ useEffect(() => {
+
+ const canvasElement = gl.domElement;
+
+ let drag = false;
+ let isRightMouseDown = false;
+
+ const onMouseDown = (evt: MouseEvent) => {
+ if (selectedAsset) {
+ clearSelectedAsset();
+ }
+ if (evt.button === 2) {
+ isRightMouseDown = true;
+ drag = false;
+ }
+ };
+
+ const onMouseUp = (evt: MouseEvent) => {
+ if (evt.button === 2) {
+ isRightMouseDown = false;
+ }
+ }
+
+ const onMouseMove = () => {
+ if (isRightMouseDown) {
+ drag = true;
+ }
+ };
+
+ const handleRightClick = (evt: MouseEvent) => {
+ if (drag) return;
+ evt.preventDefault();
+ const canvasElement = gl.domElement;
+ if (!canvasElement) return;
+
+ let intersects = raycaster.intersectObjects(scene.children, true);
+ if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
+ let currentObject = intersects[0].object;
+
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as Object3D;
+ }
+ if (currentObject) {
+ const isInProduct = getIsEventInProduct(selectedProduct.productId, currentObject.uuid);
+
+ if (isInProduct) {
+ const event = getEventByModelUuid(currentObject.uuid);
+ if (event) {
+ setSelectedAsset(event)
+ const canvasRect = canvasElement.getBoundingClientRect();
+ const relativeX = evt.clientX - canvasRect.left;
+ const relativeY = evt.clientY - canvasRect.top;
+
+ setTop(relativeY);
+ setLeft(relativeX);
+ } else {
+ clearSelectedAsset()
+ }
+ } else {
+ const event = getEventByModelUuid(currentObject.uuid);
+ if (event) {
+ setSelectedAsset(event)
+ const canvasRect = canvasElement.getBoundingClientRect();
+ const relativeX = evt.clientX - canvasRect.left;
+ const relativeY = evt.clientY - canvasRect.top;
+
+ setTop(relativeY);
+ setLeft(relativeX);
+ } else {
+ clearSelectedAsset()
+ }
+ }
+
+ }
+ } else {
+ clearSelectedAsset()
+ }
+
+ };
+
+ if (subModule === 'simulations') {
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ canvasElement.addEventListener('contextmenu', handleRightClick);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener('contextmenu', handleRightClick);
+ };
+
+ }, [gl, subModule, selectedProduct, selectedAsset]);
+ return (
+ <>>
+ )
+}
+
+export default AddOrRemoveEventsInProducts
\ No newline at end of file
diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx
index b883824..38175e2 100644
--- a/app/src/modules/simulation/products/products.tsx
+++ b/app/src/modules/simulation/products/products.tsx
@@ -1,7 +1,8 @@
-import React, { useEffect } from 'react'
-import { useProductStore } from '../../../store/simulation/useProductStore'
import * as THREE from 'three';
+import { useEffect } from 'react';
+import { useProductStore } from '../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
+import AddOrRemoveEventsInProducts from './events/addOrRemoveEventsInProducts';
import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProductOrEventApi';
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
@@ -32,6 +33,9 @@ function Products() {
return (
<>
+
+
+
>
)
}
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 757a9ef..5ca0ec5 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -23,7 +23,7 @@ function Simulation() {
}, [events])
useEffect(() => {
- console.log('products: ', products);
+ // console.log('products: ', products);
}, [products])
return (
diff --git a/app/src/modules/simulation/simulator/simulator.tsx b/app/src/modules/simulation/simulator/simulator.tsx
index 8cc22d6..c4f1c40 100644
--- a/app/src/modules/simulation/simulator/simulator.tsx
+++ b/app/src/modules/simulation/simulator/simulator.tsx
@@ -1,9 +1,16 @@
-import React from 'react'
+import { useEffect } from 'react'
+import { useProductStore } from '../../../store/simulation/useProductStore'
function Simulator() {
+ const { products } = useProductStore();
+
+ useEffect(() => {
+ // console.log('products: ', products);
+ }, [products])
+
return (
<>
-
+
>
)
}
diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
index b38e6dd..f836ea4 100644
--- a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
+++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
@@ -1,22 +1,16 @@
-import { useThree } from '@react-three/fiber'
-import React, { useEffect } from 'react'
-import { Object3D } from 'three';
-import { useSubModuleStore } from '../../../../store/useModuleStore';
-import { useLeftData, useTopData } from '../../../../store/visualization/useZone3DWidgetStore';
-import { useEventsStore } from '../../../../store/simulation/useEventsStore';
-import { useProductStore } from '../../../../store/simulation/useProductStore';
-import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
-import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
+import { useEffect } from "react";
+import { useThree } from "@react-three/fiber";
+import { useSubModuleStore } from "../../../../store/useModuleStore";
+import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
+import { useProductStore } from "../../../../store/simulation/useProductStore";
+import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
function TriggerConnector() {
const { gl, raycaster, scene } = useThree();
const { subModule } = useSubModuleStore();
- const { setTop } = useTopData();
- const { setLeft } = useLeftData();
- const { getIsEventInProduct } = useProductStore();
- const { getEventByModelUuid } = useEventsStore();
+ const { getPointByUuid, getIsEventInProduct } = useProductStore();
+ const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct();
- const { selectedAsset, setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
useEffect(() => {
@@ -57,48 +51,31 @@ function TriggerConnector() {
if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
let currentObject = intersects[0].object;
- while (currentObject) {
- if (currentObject.name === "Scene") {
- break;
- }
- currentObject = currentObject.parent as Object3D;
- }
- if (currentObject) {
- const isInProduct = getIsEventInProduct(selectedProduct.productId, currentObject.uuid);
+ if (currentObject && currentObject.name === 'Event-Sphere') {
+
+ const isInProduct = getIsEventInProduct(
+ selectedProduct.productId,
+ currentObject.userData.modelUuid
+ );
+
+ // You left Here
if (isInProduct) {
- const event = getEventByModelUuid(currentObject.uuid);
- if (event) {
- setSelectedAsset(event)
- const canvasRect = canvasElement.getBoundingClientRect();
- const relativeX = evt.clientX - canvasRect.left;
- const relativeY = evt.clientY - canvasRect.top;
- setTop(relativeY);
- setLeft(relativeX);
- } else {
- clearSelectedAsset()
- }
+ const event = getPointByUuid(
+ selectedProduct.productId,
+ currentObject.userData.modelUuid,
+ currentObject.userData.pointUuid
+ );
+ console.log('event: ', event);
} else {
- const event = getEventByModelUuid(currentObject.uuid);
- if (event) {
- setSelectedAsset(event)
- const canvasRect = canvasElement.getBoundingClientRect();
- const relativeX = evt.clientX - canvasRect.left;
- const relativeY = evt.clientY - canvasRect.top;
- setTop(relativeY);
- setLeft(relativeX);
- } else {
- clearSelectedAsset()
- }
}
-
}
- } else {
- clearSelectedAsset()
- }
+ } else {
+
+ }
};
if (subModule === 'simulations') {
@@ -115,7 +92,7 @@ function TriggerConnector() {
canvasElement.removeEventListener('contextmenu', handleRightClick);
};
- }, [gl, subModule, selectedProduct, selectedAsset]);
+ }, [gl, subModule]);
return (
<>
From 05d8405188a9748994bf1a23c2b996cf1e9ef44d Mon Sep 17 00:00:00 2001
From: Gomathi9520
Date: Fri, 25 Apr 2025 19:40:15 +0530
Subject: [PATCH 12/13] armbot trigger
---
.../instances/animator/roboticArmAnimator.tsx | 62 ++++++-
.../armInstance/roboticArmInstance.tsx | 175 +++++++++++++++---
.../instances/ikInstance/ikInstance.tsx | 85 ++++++++-
.../roboticArm/instances/ikInstances.tsx | 14 --
.../instances/roboticArmInstances.tsx | 12 +-
.../simulation/roboticArm/roboticArm.tsx | 91 +++++++--
app/src/store/simulation/useArmBotStore.ts | 13 +-
app/src/store/simulation/useVehicleStore.ts | 1 +
8 files changed, 382 insertions(+), 71 deletions(-)
delete mode 100644 app/src/modules/simulation/roboticArm/instances/ikInstances.tsx
diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
index 6b35a43..fd7590e 100644
--- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
@@ -1,6 +1,64 @@
-import React from 'react'
+import React, { useEffect, useMemo, useRef, useState } from 'react'
+import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore';
+import { useFrame, useThree } from '@react-three/fiber';
+import * as THREE from "three"
+import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
+
+function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase, ikSolver, targetBone, robot, logStatus, groupRef, processes, armBotCurveRef, path }: any) {
+ const { armBots } = useArmBotStore();
+ const { scene } = useThree();
+ const restSpeed = 0.1;
+ const restPosition = new THREE.Vector3(0, 2, 1.6);
+ const initialCurveRef = useRef(null);
+ const initialStartPositionRef = useRef(null);
+ const [initialProgress, setInitialProgress] = useState(0);
+ const [progress, setProgress] = useState(0);
+ const [needsInitialMovement, setNeedsInitialMovement] = useState(true);
+ const [isInitializing, setIsInitializing] = useState(true);
+ const { isPlaying } = usePlayButtonStore();
+ const statusRef = useRef("idle");
+ // Create a ref for initialProgress
+ const initialProgressRef = useRef(0);
+ const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
+
+ useEffect(() => {
+ setCurrentPath(path)
+ }, [path])
+
+ useEffect(() => {
+
+ }, [currentPath])
+
+ useFrame((_, delta) => {
+ if (!ikSolver || !currentPath || currentPath.length === 0) return;
+
+ const bone = ikSolver.mesh.skeleton.bones.find(
+ (b: any) => b.name === targetBone
+ );
+ if (!bone) return;
+
+ // Ensure currentPath is a valid array of 3D points, create a CatmullRomCurve3 from it
+ const curve = new THREE.CatmullRomCurve3(
+ currentPath.map(point => new THREE.Vector3(point[0], point[1], point[2]))
+ );
+
+ const next = initialProgressRef.current + delta * 0.5;
+ if (next >= 1) {
+ bone.position.copy(restPosition);
+ HandleCallback(); // Call the callback when the path is completed
+ initialProgressRef.current = 0; // Set ref to 1 when done
+ } else {
+
+ const point = curve.getPoint(next); // Get the interpolated point from the curve
+ bone.position.copy(point); // Update the bone position along the curve
+ initialProgressRef.current = next; // Update progress
+ }
+
+ ikSolver.update();
+ });
+
+
-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 42b775a..86eee6a 100644
--- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
@@ -1,58 +1,179 @@
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useRef, useState } from 'react'
import IKInstance from '../ikInstance/ikInstance';
import RoboticArmAnimator from '../animator/roboticArmAnimator';
import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore';
+import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_4.glb";
+import { useThree } from "@react-three/fiber";
+import { useFloorItems } from '../../../../../store/store';
+import useModuleStore from '../../../../../store/useModuleStore';
+import { Vector3 } from "three";
+import * as THREE from "three";
+
+interface Process {
+ triggerId: string;
+ startPoint?: Vector3;
+ endPoint?: Vector3;
+ speed: number;
+}
+function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
-function RoboticArmInstance({ armBot }: any) {
const { isPlaying } = usePlayButtonStore();
const [currentPhase, setCurrentPhase] = useState<(string)>("init");
- console.log('currentPhase: ', currentPhase);
- const { armBots, addArmBot, addCurrentAction } = useArmBotStore();
+ const { scene } = useThree();
+ const targetBone = "Target";
+ const { activeModule } = useModuleStore();
+ const [ikSolver, setIkSolver] = useState(null);
+ const { addCurrentAction, setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore();
+ const { floorItems } = useFloorItems();
+ const groupRef = useRef(null);
+ const [processes, setProcesses] = useState([]);
+ const [armBotCurvePoints, setArmBotCurvePoints] = useState({ start: [], end: [] })
+ const restPosition = new THREE.Vector3(0, 2, 1.6);
+ let armBotCurveRef = useRef(null)
+ const [path, setPath] = useState<[number, number, number][]>([]);
useEffect(() => {
+ let armItems = floorItems?.filter((val: any) =>
+ val.modeluuid === "3abf5d46-b59e-4e6b-9c02-a4634b64b82d"
+ );
+ // Get the first matching item
+ let armItem = armItems?.[0];
+ if (armItem) {
+ const targetMesh = scene?.getObjectByProperty("uuid", armItem.modeluuid);
+ if (targetMesh) {
+ targetMesh.visible = activeModule !== "simulation"
+ }
+ }
+ const targetBones = ikSolver?.mesh.skeleton.bones.find(
+ (b: any) => b.name === targetBone
+ );
- 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");
-
+ if (!robot?.isActive && robot?.state == "idle" && currentPhase == "init") {
+
+ setArmBotActive(robot.modelUuid, true)
+ setArmBotState(robot.modelUuid, "running")
+ setCurrentPhase("init-to-rest");
+ if (targetBones) {
+ let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
+ if (curve) {
+ setPath(curve.points.map(point => [point.x, point.y, point.z]));
+ }
+ }
+ logStatus(robot.modelUuid, "Starting from init to rest")
}
//Waiting for trigger.
- if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "moving-to-rest") {
- setCurrentPhase("rest");
+ else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && !robot.currentAction) {
+ console.log("trigger");
+ setTimeout(() => {
+ addCurrentAction(robot.modelUuid, 'action-003');
+ }, 3000);
}
- // Moving armBot from rest position to pick up point.
- if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "rest") {
-
+ else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && robot.currentAction) {
+ if (robot.currentAction) {
+ setArmBotActive(robot.modelUuid, true);
+ setArmBotState(robot.modelUuid, "running");
+ setCurrentPhase("rest-to-start");
+ const startPoint = robot.point.actions[0].process.startPoint;
+ if (startPoint) {
+ let curve = createCurveBetweenTwoPoints(restPosition, new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]));
+ if (curve) {
+ setPath(curve.points.map(point => [point.x, point.y, point.z]));
+ }
+ }
+ }
+ logStatus(robot.modelUuid, "Starting from rest to start")
}
- //Moving arm from start point to end point.
- if (armBot?.isActive && armBot?.state == "running " && currentPhase == "rest-to-start ") {
-
+ else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "picking" && robot.currentAction) {
+ setArmBotActive(robot.modelUuid, true);
+ setArmBotState(robot.modelUuid, "running");
+ setCurrentPhase("start-to-end");
+ const startPoint = robot.point.actions[0].process.startPoint;
+ const endPoint = robot.point.actions[0].process.endPoint;
+ if (startPoint && endPoint) {
+ let curve = createCurveBetweenTwoPoints(
+ new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]),
+ new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2])
+ );
+ if (curve) {
+ setPath(curve.points.map(point => [point.x, point.y, point.z]));
+ }
+ }
+ logStatus(robot.modelUuid, "Starting from start to end")
}
- //Moving arm from end point to idle.
- if (armBot?.isActive && armBot?.state == "running" && currentPhase == "end-to-start") {
-
+ else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "dropping" && robot.currentAction) {
+ setArmBotActive(robot.modelUuid, true);
+ setArmBotState(robot.modelUuid, "running");
+ setCurrentPhase("end-to-rest");
+ const endPoint = robot.point.actions[0].process.endPoint;
+ if (endPoint) {
+ let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition
+ );
+ if (curve) {
+ setPath(curve.points.map(point => [point.x, point.y, point.z]));
+ }
+ }
+ logStatus(robot.modelUuid, "Starting from end to rest")
}
-
}
- }, [currentPhase, armBot, isPlaying])
+ }, [currentPhase, robot, isPlaying, ikSolver])
+
+
+ function createCurveBetweenTwoPoints(p1: any, p2: any) {
+ const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5);
+ mid.y += 0.5;
+
+ const points = [p1, mid, p2];
+ return new THREE.CatmullRomCurve3(points);
+ }
+
const HandleCallback = () => {
- if (armBot.isActive && armBot.state == "idle" && currentPhase == "init") {
- addCurrentAction('armbot-xyz-001', 'action-001');
+ if (robot.isActive && robot.state == "running" && currentPhase == "init-to-rest") {
+ console.log("Callback triggered: rest");
+ setArmBotActive(robot.modelUuid, false)
+ setArmBotState(robot.modelUuid, "idle")
+ setCurrentPhase("rest");
+ setPath([])
}
+ else if (robot.isActive && robot.state == "running" && currentPhase == "rest-to-start") {
+ console.log("Callback triggered: pick.");
+ setArmBotActive(robot.modelUuid, false)
+ setArmBotState(robot.modelUuid, "idle")
+ setCurrentPhase("picking");
+ setPath([])
+ }
+ else if (robot.isActive && robot.state == "running" && currentPhase == "start-to-end") {
+ console.log("Callback triggered: drop.");
+ setArmBotActive(robot.modelUuid, false)
+ setArmBotState(robot.modelUuid, "idle")
+ setCurrentPhase("dropping");
+ setPath([])
+ }
+ else if (robot.isActive && robot.state == "running" && currentPhase == "end-to-rest") {
+ console.log("Callback triggered: rest, cycle completed.");
+ setArmBotActive(robot.modelUuid, false)
+ setArmBotState(robot.modelUuid, "idle")
+ setCurrentPhase("rest");
+ setPath([])
+ removeCurrentAction(robot.modelUuid)
+ }
+ }
+ const logStatus = (id: string, status: string) => {
+ console.log(id +","+ status);
}
return (
<>
-
-
+
+
>
)
diff --git a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
index 52a8610..a8d8782 100644
--- a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx
@@ -1,8 +1,87 @@
-import React from 'react'
+import React, { useEffect, useMemo, useRef, useState } from 'react'
+import * as THREE from "three";
+import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
+import { clone } from "three/examples/jsm/utils/SkeletonUtils";
+import { useFrame, useLoader, useThree } from "@react-three/fiber";
+import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
+type IKInstanceProps = {
+ modelUrl: string;
+ ikSolver: any;
+ setIkSolver: any
+ robot: any;
+ groupRef: React.RefObject;
+ processes: any;
+ setArmBotCurvePoints: any
+};
+function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processes, setArmBotCurvePoints }: IKInstanceProps) {
+ const { scene } = useThree();
+ const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
+ const draco = new DRACOLoader();
+ draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
+ loader.setDRACOLoader(draco);
+ });
+ const cloned = useMemo(() => clone(gltf?.scene), [gltf]);
+ const targetBoneName = "Target";
+ const skinnedMeshName = "link_0";
+ useEffect(() => {
+ if (!gltf) return;
+ const OOI: any = {};
+ cloned.traverse((n: any) => {
+ if (n.name === targetBoneName) OOI.Target_Bone = n;
+ if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n;
+ });
+ if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return;
+ const iks = [
+ {
+ target: 7,
+ effector: 6,
+ links: [
+ {
+ index: 5,
+ enabled: true,
+ rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
+ rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0),
+ },
+ {
+ index: 4,
+ enabled: true,
+ rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
+ rotationMax: new THREE.Vector3(0, 0, 0),
+ },
+ {
+ index: 3,
+ enabled: true,
+ rotationMin: new THREE.Vector3(0, 0, 0),
+ rotationMax: new THREE.Vector3(2, 0, 0),
+ },
+ { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) },
+ { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) },
+ ],
+ },
+ ];
+
+ const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
+ setIkSolver(solver);
+
+ const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05);
+
+ // scene.add(groupRef.current)
+
+
+ }, [gltf]);
-function IKInstance() {
return (
- <>>
+ <>
+
+
+
+ >
)
}
diff --git a/app/src/modules/simulation/roboticArm/instances/ikInstances.tsx b/app/src/modules/simulation/roboticArm/instances/ikInstances.tsx
deleted file mode 100644
index d44ddd2..0000000
--- a/app/src/modules/simulation/roboticArm/instances/ikInstances.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react'
-import IKInstance from './ikInstance/ikInstance';
-
-function IkInstances() {
- return (
- <>
-
-
-
- >
- )
-}
-
-export default IkInstances;
\ No newline at end of file
diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
index 1f963c8..1089fa5 100644
--- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx
@@ -5,17 +5,11 @@ import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
function RoboticArmInstances() {
const { armBots } = useArmBotStore();
-
return (
<>
- {
- armBots?.map((robot: any) => (
-
-
- )
- )
-
- }
+ {armBots?.map((robot: ArmBotStatus) => (
+
+ ))}
>
)
diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx
index 4295ac7..dcf01da 100644
--- a/app/src/modules/simulation/roboticArm/roboticArm.tsx
+++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx
@@ -1,21 +1,86 @@
import { useEffect } from "react";
import RoboticArmInstances from "./instances/roboticArmInstances";
import { useArmBotStore } from "../../../store/simulation/useArmBotStore";
+import { useFloorItems } from "../../../store/store";
function RoboticArm() {
- const { armBots, addArmBot, addCurrentAction } = useArmBotStore();
+ const { armBots, addArmBot, removeArmBot } = useArmBotStore();
+ const { floorItems } = useFloorItems();
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],
+ position: [91.94347308985614, 0, 6.742905194869091],
+ rotation: [0, 0, 0],
+ type: "roboticArm",
+ speed: 1.5,
+ point: {
+ uuid: "point-123",
+ position: [0, 1.5, 0],
+ rotation: [0, 0, 0],
+ actions: [
+ {
+ actionUuid: "action-003",
+ actionName: "Pick Component",
+ actionType: "pickAndPlace",
+ process: {
+ startPoint: [5.52543010919071, 1, -8.433681161200905],
+ endPoint: [10.52543010919071, 1, -12.433681161200905],
+ },
+ 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",
+ },
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ {
+ state: "idle",
+ modelUuid: "armbot-xyz-002",
+ modelName: "ArmBot-X200",
+ position: [95.94347308985614, 0, 6.742905194869091],
+ rotation: [0, 0, 0],
type: "roboticArm",
speed: 1.5,
point: {
@@ -28,8 +93,8 @@ function RoboticArm() {
actionName: "Pick Component",
actionType: "pickAndPlace",
process: {
- startPoint: [1.2, 0.3, 0.5],
- endPoint: [-0.8, 1.1, 0.7],
+ startPoint: [2.52543010919071, 0, 8.433681161200905],
+ endPoint: [95.3438373267953, 0, 9.0279187421610025],
},
triggers: [
{
@@ -80,20 +145,20 @@ function RoboticArm() {
];
useEffect(() => {
+
+ removeArmBot(armBotStatusSample[0].modelUuid);
addArmBot('123', armBotStatusSample[0]);
+ // addArmBot('123', armBotStatusSample[1]);
// addCurrentAction('armbot-xyz-001', 'action-001');
}, []);
-
useEffect(() => {
- console.log('armBots: ', armBots);
+ //
}, [armBots]);
return (
<>
-
-
>
);
}
diff --git a/app/src/store/simulation/useArmBotStore.ts b/app/src/store/simulation/useArmBotStore.ts
index d907f21..642762f 100644
--- a/app/src/store/simulation/useArmBotStore.ts
+++ b/app/src/store/simulation/useArmBotStore.ts
@@ -21,7 +21,7 @@ interface ArmBotStore {
updateEndPoint: (modelUuid: string, actionUuid: string, endPoint: [number, number, number] | null) => void;
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
-
+ setArmBotState: (modelUuid: string, newState: ArmBotStatus['state']) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
@@ -75,7 +75,6 @@ export const useArmBotStore = create()(
actionUuid: action.actionUuid,
actionName: action.actionName,
};
- armBot.isActive = true;
}
}
});
@@ -86,7 +85,6 @@ export const useArmBotStore = create()(
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
if (armBot) {
armBot.currentAction = undefined;
- armBot.isActive = false;
}
});
},
@@ -142,6 +140,15 @@ export const useArmBotStore = create()(
});
},
+ setArmBotState: (modelUuid, newState) => {
+ set((state) => {
+ const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
+ if (armBot) {
+ armBot.state = newState;
+ }
+ });
+ },
+
incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => {
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts
index ce28916..874a74c 100644
--- a/app/src/store/simulation/useVehicleStore.ts
+++ b/app/src/store/simulation/useVehicleStore.ts
@@ -1,3 +1,4 @@
+
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
From 2424fa2e154f406f44dc70796b1092b664231764 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B
Date: Fri, 25 Apr 2025 19:41:05 +0530
Subject: [PATCH 13/13] fix: Remove unused material property from vehicle
action definition
---
app/src/modules/simulation/vehicle/vehicles.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx
index 3bb16d9..f0b4d17 100644
--- a/app/src/modules/simulation/vehicle/vehicles.tsx
+++ b/app/src/modules/simulation/vehicle/vehicles.tsx
@@ -69,7 +69,6 @@ function Vehicles() {
actionUuid: "action-456",
actionName: "Deliver to Zone A",
actionType: "travel",
- material: "crate",
unLoadDuration: 10,
loadCapacity: 2,
pickUpPoint: { x: 90, y: 0, z: 28 },