Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions frontend/src/api_helper/TreeWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,99 @@ const listDockerWorlds = async () => {
}
};

const listDockerRobots = async () => {
const apiUrl = "/bt_studio/list_docker_robots/";
try {
const response = await axios.get(apiUrl);
return response.data.robots;
} catch (e: unknown) {
const error = e as ApiError;
throw Error(error.response?.data.message);
}
};

const createCombinedUniverse = async (
projectId: string,
universeName: string,
worldId: string,
robotId: string,
startPose: number[] | null = null
) => {
if (!projectId) throw new Error("The project name is not set");
if (!universeName) throw new Error("The universe name is not set");
if (!worldId) throw new Error("The world is not set");

const apiUrl = "/bt_studio/create_combined_universe/";
try {
const response = await axios.post(
apiUrl,
{
project_id: projectId,
universe_name: universeName,
world_id: worldId,
robot_id: robotId,
start_pose: startPose,
},
axiosExtra()
);
return response.data;
} catch (e: unknown) {
const error = e as ApiError;
throw Error(error.response?.data.message);
}
};

const getCombinedUniverseData = async (worldId: string, robotId: string) => {
const apiUrl = `/bt_studio/get_combined_universe_data/?world_id=${encodeURIComponent(
worldId
)}&robot_id=${encodeURIComponent(robotId || "None")}`;
try {
const response = await axios.get(apiUrl);
return {
world: response.data.universe.world,
robot: response.data.universe.robot,
tools: response.data.universe.tools,
tools_config: response.data.universe.tools_config,
};
} catch (e: unknown) {
const error = e as ApiError;
throw Error(error.response?.data.message);
}
};

const captureRobotPose = async () => {
const apiUrl = "/bt_studio/capture_robot_pose/";
try {
const response = await axios.get(apiUrl);
return response.data.pose;
} catch (e: unknown) {
const error = e as ApiError;
throw Error(error.response?.data.message);
}
};

const saveCurrentPose = async (projectId: string, universeName: string) => {
if (!projectId) throw new Error("Project name is not set");
if (!universeName) throw new Error("Universe name is not set");

const apiUrl = "/bt_studio/save_current_pose/";
try {
const response = await axios.post(
apiUrl,
{
project_id: projectId,
universe_name: universeName,
},
axiosExtra()
);
return response.data.pose;
} catch (e: unknown) {
const error = e as ApiError;
throw Error(error.response?.data.message);
}
};


////////////////////////////// App management //////////////////////////////////

const generateLocalApp = async (project: string, btOrder: string) => {
Expand Down Expand Up @@ -998,7 +1091,13 @@ export {
getWorldConfig,
getWorldFile,
listDockerWorlds,
listDockerRobots,
createCombinedUniverse,
getCombinedUniverseData,
captureRobotPose,
saveCurrentPose,
listProjects,

listWorlds,
renameFile,
renameFolder,
Expand Down
72 changes: 72 additions & 0 deletions frontend/src/components/Buttons/SavePose.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useState } from "react";
import { StyledHeaderButton } from "BtStyles/Header/HeaderMenu.styles";
import { useError } from "jderobot-ide-interface";
import { CommsManager, states } from "jderobot-commsmanager";
import { useBtTheme } from "BtContexts/BtThemeContext";
import { LoadingIcon } from "BtIcons";
import PinDropIcon from "@mui/icons-material/PinDropRounded";
import { saveCurrentPose } from "BtApi/TreeWrapper";

interface SavePoseButtonProps {
project: string;
}

const SavePoseButton = ({ project }: SavePoseButtonProps) => {
const theme = useBtTheme();
const { warning, error, info } = useError() as any;
const [loading, setLoading] = useState<boolean>(false);

const onSavePose = async () => {
const manager = CommsManager.getInstance();
const state = manager.getState();
const activeUniverse = manager.getUniverse();

if (!activeUniverse || activeUniverse === "") {
warning("No active universe loaded. Please select and launch a combined universe first.");
return;
}

if (
state === states.CONNECTED ||
state === states.IDLE ||
state === states.WORLD_READY
) {
warning("Simulation is not running. Please launch the simulation first.");
return;
}

setLoading(true);
try {
const pose = await saveCurrentPose(project, activeUniverse);
const poseStr = `[x:${pose[0]}, y:${pose[1]}, z:${pose[2]}, yaw:${pose[5]}]`;
if (info) {
info(`Successfully saved robot's current pose ${poseStr} as the starting pose for universe '${activeUniverse}'!`);
} else {
alert(`Successfully saved robot's current pose ${poseStr} as the starting pose for universe '${activeUniverse}'!`);
}
} catch (e: any) {
error(e.response?.data?.message || e.message || "Failed to save the current robot pose. Make sure the robot is active in the simulator.");
}
setLoading(false);
};

return (
<StyledHeaderButton
bgColor={theme.palette.bg}
hoverColor={theme.palette.primary}
roundness={theme.roundness}
id="save-robot-pose"
onClick={onSavePose}
title="Save robot current position as starting pose"
disabled={loading}
>
{loading ? (
<LoadingIcon htmlColor={theme.palette.text} id="loading-spin" />
) : (
<PinDropIcon sx={{ color: theme.palette.text }} />
)}
</StyledHeaderButton>
);
};

export default SavePoseButton;
2 changes: 2 additions & 0 deletions frontend/src/components/Buttons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export { default as ThemeButton } from "./Theme";
export { default as SettingsButton } from "./Settings";
export { default as DocumentationButton } from "./Documentation";
export { default as ExportButton } from "./Export";
export { default as SavePoseButton } from "./SavePose";

2 changes: 1 addition & 1 deletion frontend/src/components/CreateProject/CreateProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const Menu = ({ projId }: { projId?: string }) => {
}
setLoading(true);
try {
await createProject(name);
await createProject(name, projId);
navigate("..");
console.log("Project created successfully");
} catch (e: unknown) {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/HeaderMenu/HeaderMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
TerminateWorldButton,
ThemeButton,
ExportButton,
SavePoseButton,
} from "../Buttons";
import {
StyledHeaderButtonContainer,
Expand Down Expand Up @@ -92,6 +93,7 @@ const HeaderMenu = ({
<ThemeButton />
<ExportButton project={project} />
<DownloadButton project={project} />
<SavePoseButton project={project} />
<LayoutButton setLayout={setLayout} />
{/* <SettingsButton project={project} /> */}
<ExecutionControl
Expand Down
Loading
Loading