From 0fccb97c846f2ddaef3b9c0c5beb4756d8281148 Mon Sep 17 00:00:00 2001 From: Amal Nanavati Date: Sat, 31 Aug 2024 11:25:33 -0700 Subject: [PATCH 1/3] Allow users to adjust speed in the Bite Transfer settings --- feedingwebapp/src/Pages/Constants.js | 4 + feedingwebapp/src/Pages/GlobalState.jsx | 6 +- .../src/Pages/Settings/BiteTransfer.jsx | 115 ++++++++++++++++-- feedingwebapp/src/Pages/Settings/Main.jsx | 4 +- feedingwebapp/src/Pages/Settings/Settings.jsx | 2 +- 5 files changed, 114 insertions(+), 17 deletions(-) diff --git a/feedingwebapp/src/Pages/Constants.js b/feedingwebapp/src/Pages/Constants.js index 0bf1cd4..0ac1b99 100644 --- a/feedingwebapp/src/Pages/Constants.js +++ b/feedingwebapp/src/Pages/Constants.js @@ -125,6 +125,10 @@ export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParametersAtom // The names of parameters users can change in the settings menu export const DISTANCE_TO_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.plan_distance_from_mouth' +export const MOVE_TO_MOUTH_SPEED_PARAM = 'MoveToMouth.tree_kwargs.max_linear_speed' +export const MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.linear_speed_near_mouth' +export const MOVE_FROM_MOUTH_SPEED_PARAM = 'MoveFromMouth.tree_kwargs.max_linear_speed_to_staging_configuration' +export const MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveFromMouth.tree_kwargs.linear_speed_near_mouth' export const ABOVE_PLATE_PARAM_JOINTS = 'MoveAbovePlate.tree_kwargs.joint_positions' export const STAGING_PARAM_JOINTS = 'MoveToStagingConfiguration.tree_kwargs.goal_configuration' export const STAGING_PARAM_POSITION = 'MoveFromMouth.tree_kwargs.staging_configuration_position' diff --git a/feedingwebapp/src/Pages/GlobalState.jsx b/feedingwebapp/src/Pages/GlobalState.jsx index 45308a7..5d6e211 100644 --- a/feedingwebapp/src/Pages/GlobalState.jsx +++ b/feedingwebapp/src/Pages/GlobalState.jsx @@ -76,8 +76,8 @@ export { NON_MOVING_STATES } /** * SETTINGS_STATE controls which settings page to display. * - MAIN: The main page, with options to navigate to the other pages. - * - DISTANCE_TO_MOUTH: Allow the user to customize how close the robot gets - * to their mouth. + * - BITE_TRANSFER: Allow the user to customize how close the robot gets + * to their mouth and the speed of approach/departure. * - ABOVE_PLATE: Allow the user to customize how high the fixed above plate * arm configuration. * - RESTING_CONFIGURATION: Allow the user to customize the fixed resting @@ -89,7 +89,7 @@ export { NON_MOVING_STATES } */ export const SETTINGS_STATE = { MAIN: 'MAIN', - DISTANCE_TO_MOUTH: 'DISTANCE_TO_MOUTH', + BITE_TRANSFER: 'BITE_TRANSFER', ABOVE_PLATE: 'ABOVE_PLATE', RESTING_CONFIGURATION: 'RESTING_CONFIGURATION', STAGING_CONFIGURATION: 'STAGING_CONFIGURATION', diff --git a/feedingwebapp/src/Pages/Settings/BiteTransfer.jsx b/feedingwebapp/src/Pages/Settings/BiteTransfer.jsx index e0c3d24..bcfba22 100644 --- a/feedingwebapp/src/Pages/Settings/BiteTransfer.jsx +++ b/feedingwebapp/src/Pages/Settings/BiteTransfer.jsx @@ -7,7 +7,14 @@ import Button from 'react-bootstrap/Button' import { View } from 'react-native' // Local imports -import { getRobotMotionText, DISTANCE_TO_MOUTH_PARAM } from '../Constants' +import { + getRobotMotionText, + DISTANCE_TO_MOUTH_PARAM, + MOVE_TO_MOUTH_SPEED_PARAM, + MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM, + MOVE_FROM_MOUTH_SPEED_PARAM, + MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM +} from '../Constants' import { useGlobalState, MEAL_STATE, SETTINGS_STATE } from '../GlobalState' import RobotMotion from '../Home/MealStates/RobotMotion' import DetectingFaceSubcomponent from '../Home/MealStates/DetectingFaceSubcomponent' @@ -28,8 +35,17 @@ const BiteTransfer = (props) => { // Create relevant local state variables // Configure the parameters for SettingsPageParent - const paramNames = useMemo(() => [DISTANCE_TO_MOUTH_PARAM], []) - const [currentDistanceToMouth, setCurrentDistanceToMouth] = useState([null]) + const paramNames = useMemo( + () => [ + DISTANCE_TO_MOUTH_PARAM, + MOVE_TO_MOUTH_SPEED_PARAM, + MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM, + MOVE_FROM_MOUTH_SPEED_PARAM, + MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM + ], + [] + ) + const [currentParams, setCurrentParams] = useState([null, null, null, null, null]) const [localCurrAndNextMealState, setLocalCurrAndNextMealState] = useState( globalMealState === MEAL_STATE.U_BiteDone || globalMealState === MEAL_STATE.R_DetectingFace || settingsPageAtMouth ? [MEAL_STATE.R_MovingFromMouth, null] @@ -53,6 +69,8 @@ const BiteTransfer = (props) => { // Get min and max distance to mouth const minDistanceToMouth = 1 // cm const maxDistanceToMouth = 10 // cm + const minLinearSpeed = 2 // cm/s + const maxLinearSpeed = 15 // cm/s // When we set local meal state, also update bite transfer page at face const setLocalCurrMealStateWrapper = useCallback( @@ -166,16 +184,57 @@ const BiteTransfer = (props) => { if (value > maxDistanceToMouth) { value = maxDistanceToMouth } - let fullDistanceToMouth = [value / 100.0, currentDistanceToMouth[0][1], currentDistanceToMouth[0][2]] - setCurrentDistanceToMouth([fullDistanceToMouth]) + let distance_m = value / 100.0 + setCurrentParams((currentParams) => [ + [distance_m, currentParams[0][1], currentParams[0][2]], + currentParams[1], + currentParams[2], + currentParams[3], + currentParams[4] + ]) + }, + [minDistanceToMouth, maxDistanceToMouth] + ) + + // Callback for when the user changes the speed to the mouth + const onSpeedChange = useCallback( + (_ev, data, index) => { + let value = data.value !== null ? data.value : parseFloat(data.displayValue) + if (value < minLinearSpeed) { + value = minLinearSpeed + } + if (value > maxLinearSpeed) { + value = maxLinearSpeed + } + let speed_mps = value / 100.0 + setCurrentParams((currentParams) => [ + currentParams[0], + index === 1 ? speed_mps : currentParams[1], + index === 2 ? speed_mps : currentParams[2], + index === 3 ? speed_mps : currentParams[3], + index === 4 ? speed_mps : currentParams[4] + ]) }, - [currentDistanceToMouth, minDistanceToMouth, maxDistanceToMouth] + [minLinearSpeed, maxLinearSpeed] ) // Callback to render the main contents of the page const distanceToMouthId = useId() + const moveToMouthSpeedId = useId() + const moveToMouthSpeedNearMouthId = useId() + const moveFromMouthSpeedId = useId() + const moveFromMouthSpeedNearMouthId = useId() + const speedParameterIdsAndDescriptions = useMemo( + () => [ + [moveToMouthSpeedId, 'Approach Speed (cm/s)'], + [moveToMouthSpeedNearMouthId, 'Approach Speed Near Mouth (cm/s)'], + [moveFromMouthSpeedId, 'Retreat Speed (cm/s)'], + [moveFromMouthSpeedNearMouthId, 'Retreat Speed Near Mouth (cm/s)'] + ], + [moveToMouthSpeedId, moveToMouthSpeedNearMouthId, moveFromMouthSpeedId, moveFromMouthSpeedNearMouthId] + ) const renderBiteTransferSettings = useCallback(() => { - if (currentDistanceToMouth[0] === null) { + if (currentParams.some((param) => param === null)) { return ( <> { Distance To Mouth (cm) { size: 'large' }} /> + {speedParameterIdsAndDescriptions.map(([id, description], index) => ( + <> + + onSpeedChange(_ev, data, index + 1)} + appearance='filled-lighter' + style={{ + fontSize: textFontSize, + width: '90%', + color: 'black' + }} + incrementButton={{ + 'aria-label': 'Increase value by 1.0', + 'aria-roledescription': 'spinner', + size: 'large' + }} + /> + + ))} { }, [ dimension, textFontSize, - currentDistanceToMouth, + currentParams, onDistanceToMouthChange, + onSpeedChange, distanceToMouthId, + speedParameterIdsAndDescriptions, moveToMouthButtonClicked, moveAwayFromMouthButtonClicked ]) @@ -368,8 +461,8 @@ const BiteTransfer = (props) => { modalOnHide={() => setLocalCurrMealStateWrapper(null)} modalChildren={renderModalBody()} paramNames={paramNames} - localParamValues={currentDistanceToMouth} - setLocalParamValues={setCurrentDistanceToMouth} + localParamValues={currentParams} + setLocalParamValues={setCurrentParams} > {renderBiteTransferSettings()} diff --git a/feedingwebapp/src/Pages/Settings/Main.jsx b/feedingwebapp/src/Pages/Settings/Main.jsx index 87cbbc9..09c1022 100644 --- a/feedingwebapp/src/Pages/Settings/Main.jsx +++ b/feedingwebapp/src/Pages/Settings/Main.jsx @@ -163,9 +163,9 @@ const Main = () => { // Configure the different options in the settings menu let settingsConfig = [ { - title: 'Distance to Mouth', + title: 'Motion to/from Mouth', icon: moveToMouthConfigurationImage, - onClick: () => onClickSettingsPage(SETTINGS_STATE.DISTANCE_TO_MOUTH) + onClick: () => onClickSettingsPage(SETTINGS_STATE.BITE_TRANSFER) }, { title: 'Above Plate', diff --git a/feedingwebapp/src/Pages/Settings/Settings.jsx b/feedingwebapp/src/Pages/Settings/Settings.jsx index 3bdec42..b325b71 100644 --- a/feedingwebapp/src/Pages/Settings/Settings.jsx +++ b/feedingwebapp/src/Pages/Settings/Settings.jsx @@ -42,7 +42,7 @@ const Settings = (props) => { switch (settingsState) { case SETTINGS_STATE.MAIN: return
- case SETTINGS_STATE.DISTANCE_TO_MOUTH: + case SETTINGS_STATE.BITE_TRANSFER: return case SETTINGS_STATE.ABOVE_PLATE: return ( From 72c8389e93293febf9f940b3865dd4d7f892a822 Mon Sep 17 00:00:00 2001 From: Amal Nanavati Date: Sat, 31 Aug 2024 18:35:24 -0700 Subject: [PATCH 2/3] Allow users to customize planning scene from settings --- feedingwebapp/src/Pages/Constants.js | 5 +- feedingwebapp/src/Pages/GlobalState.jsx | 3 +- feedingwebapp/src/Pages/Settings/Main.jsx | 5 + .../src/Pages/Settings/PlanningScene.jsx | 125 ++++++++++++++++++ feedingwebapp/src/Pages/Settings/Settings.jsx | 3 + 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 feedingwebapp/src/Pages/Settings/PlanningScene.jsx diff --git a/feedingwebapp/src/Pages/Constants.js b/feedingwebapp/src/Pages/Constants.js index 0ac1b99..36268dd 100644 --- a/feedingwebapp/src/Pages/Constants.js +++ b/feedingwebapp/src/Pages/Constants.js @@ -122,6 +122,8 @@ export const GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_param export const GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters' export const SET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/set_parameters_atomically' export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParametersAtomically' +export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_parameters' +export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters' // The names of parameters users can change in the settings menu export const DISTANCE_TO_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.plan_distance_from_mouth' @@ -129,11 +131,12 @@ export const MOVE_TO_MOUTH_SPEED_PARAM = 'MoveToMouth.tree_kwargs.max_linear_spe export const MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.linear_speed_near_mouth' export const MOVE_FROM_MOUTH_SPEED_PARAM = 'MoveFromMouth.tree_kwargs.max_linear_speed_to_staging_configuration' export const MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveFromMouth.tree_kwargs.linear_speed_near_mouth' +export const PLANNING_SCENE_PARAM = 'planning_scene_namespace_to_use' export const ABOVE_PLATE_PARAM_JOINTS = 'MoveAbovePlate.tree_kwargs.joint_positions' export const STAGING_PARAM_JOINTS = 'MoveToStagingConfiguration.tree_kwargs.goal_configuration' export const STAGING_PARAM_POSITION = 'MoveFromMouth.tree_kwargs.staging_configuration_position' export const STAGING_PARAM_ORIENTATION = 'MoveFromMouth.tree_kwargs.staging_configuration_quat_xyzw' -// TODO: Eventually, we should break AcquireFood into two actionss to avoid these +// TODO: Eventually, we should break AcquireFood into two actions to avoid these // two different resting parameters. export const RESTING_PARAM_JOINTS_1 = 'AcquireFood.tree_kwargs.resting_joint_positions' // TODO: We may need to remove the orientation constraint from the below action. diff --git a/feedingwebapp/src/Pages/GlobalState.jsx b/feedingwebapp/src/Pages/GlobalState.jsx index 5d6e211..c530b38 100644 --- a/feedingwebapp/src/Pages/GlobalState.jsx +++ b/feedingwebapp/src/Pages/GlobalState.jsx @@ -93,7 +93,8 @@ export const SETTINGS_STATE = { ABOVE_PLATE: 'ABOVE_PLATE', RESTING_CONFIGURATION: 'RESTING_CONFIGURATION', STAGING_CONFIGURATION: 'STAGING_CONFIGURATION', - STOW_CONFIGURATION: 'STOW_CONFIGURATION' + STOW_CONFIGURATION: 'STOW_CONFIGURATION', + PLANNING_SCENE: 'PLANNING_SCENE' } // The name of the default parameter namespace diff --git a/feedingwebapp/src/Pages/Settings/Main.jsx b/feedingwebapp/src/Pages/Settings/Main.jsx index 09c1022..1b91470 100644 --- a/feedingwebapp/src/Pages/Settings/Main.jsx +++ b/feedingwebapp/src/Pages/Settings/Main.jsx @@ -186,6 +186,11 @@ const Main = () => { title: 'Stow Position', icon: moveToStowConfigurationImage, onClick: () => onClickSettingsPage(SETTINGS_STATE.STOW_CONFIGURATION) + }, + { + title: 'Planning Scene', + icon: null, + onClick: () => onClickSettingsPage(SETTINGS_STATE.PLANNING_SCENE) } ] diff --git a/feedingwebapp/src/Pages/Settings/PlanningScene.jsx b/feedingwebapp/src/Pages/Settings/PlanningScene.jsx new file mode 100644 index 0000000..069a90d --- /dev/null +++ b/feedingwebapp/src/Pages/Settings/PlanningScene.jsx @@ -0,0 +1,125 @@ +// React imports +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useMediaQuery } from 'react-responsive' +import ButtonGroup from 'react-bootstrap/ButtonGroup' +import Dropdown from 'react-bootstrap/Dropdown' +import DropdownButton from 'react-bootstrap/DropdownButton' +import { View } from 'react-native' + +// Local imports +import { PLANNING_SCENE_PARAM, PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME, PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE } from '../Constants' +import { useGlobalState, SETTINGS_STATE } from '../GlobalState' +import { useROS, createROSService, createROSServiceRequest, getValueFromParameter } from '../../ros/ros_helpers' +import SettingsPageParent from './SettingsPageParent' + +/** + * The PlanningScene component allows users to change the planning scene that a particular + * settings namespace is configured with + */ +const PlanningScene = () => { + // Get relevant global state variables + const setSettingsState = useGlobalState((state) => state.setSettingsState) + + // Flag to check if the current orientation is portrait + const isPortrait = useMediaQuery({ query: '(orientation: portrait)' }) + // Indicator of how to arrange screen elements based on orientation + let dimension = isPortrait ? 'column' : 'row' + // Rendering variables + let textFontSize = '3.5vh' + + // Configure the parameters for SettingsPageParent + const paramNames = useMemo(() => [PLANNING_SCENE_PARAM], []) + const [currentParams, setCurrentParams] = useState([null]) + + /** + * Connect to ROS, if not already connected. Put this in useRef to avoid + * re-connecting upon re-renders. + */ + const ros = useRef(useROS().ros) + + // Get the options for the planning scene + let getParametersService = useRef( + createROSService(ros.current, PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME, PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE) + ) + const [planningSceneNamespaces, setPlanningSceneNamespaces] = useState([]) + useEffect(() => { + let service = getParametersService.current + let request = createROSServiceRequest({ + names: ['namespaces'] + }) + service.callService(request, (response) => { + if (response.values.length > 0 && response.values[0].type === 9) { + setPlanningSceneNamespaces(getValueFromParameter(response.values[0])) + } else { + console.error('PlanningScene: Error getting planning scene namespaces') + } + }) + }, [getParametersService, setPlanningSceneNamespaces]) + + // Render the settings for the planning scene + const renderPlanningSceneSettings = useCallback(() => { + if (currentParams.some((param) => param === null)) { + return ( + <> + +
Loading...
+
+ + ) + } else { + return ( + + + {planningSceneNamespaces.map((namespace) => ( + setCurrentParams([namespace])} active={namespace === currentParams[0]}> + {namespace} + + ))} + + + ) + } + }, [currentParams, dimension, planningSceneNamespaces, setCurrentParams, textFontSize]) + + return ( + setSettingsState(SETTINGS_STATE.MAIN)} + modalShow={false} + modalOnHide={null} + modalChildren={null} + paramNames={paramNames} + localParamValues={currentParams} + setLocalParamValues={setCurrentParams} + > + {renderPlanningSceneSettings()} + + ) +} + +export default PlanningScene diff --git a/feedingwebapp/src/Pages/Settings/Settings.jsx b/feedingwebapp/src/Pages/Settings/Settings.jsx index b325b71..dcf30b1 100644 --- a/feedingwebapp/src/Pages/Settings/Settings.jsx +++ b/feedingwebapp/src/Pages/Settings/Settings.jsx @@ -22,6 +22,7 @@ import { STAGING_PARAM_POSITION, STOW_PARAM_JOINTS } from '../Constants' +import PlanningScene from './PlanningScene' /** * The Settings components displays the appropriate settings page based on the @@ -138,6 +139,8 @@ const Settings = (props) => { webrtcURL={props.webrtcURL} /> ) + case SETTINGS_STATE.PLANNING_SCENE: + return default: console.log('Invalid settings state', settingsState) return
From 9fbeac594f7f553bb885d3e16bb8712b38d4cf03 Mon Sep 17 00:00:00 2001 From: Amal Nanavati Date: Sat, 31 Aug 2024 20:25:36 -0700 Subject: [PATCH 3/3] Fixes from testing --- .../public/robot_state_imgs/table.svg | 13 +++++++++++ feedingwebapp/src/Pages/Constants.js | 3 ++- feedingwebapp/src/Pages/Settings/Main.jsx | 5 +++-- .../src/Pages/Settings/PlanningScene.jsx | 22 ++++++++++++------- 4 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 feedingwebapp/public/robot_state_imgs/table.svg diff --git a/feedingwebapp/public/robot_state_imgs/table.svg b/feedingwebapp/public/robot_state_imgs/table.svg new file mode 100644 index 0000000..c9818f4 --- /dev/null +++ b/feedingwebapp/public/robot_state_imgs/table.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/feedingwebapp/src/Pages/Constants.js b/feedingwebapp/src/Pages/Constants.js index 36268dd..88cc6ba 100644 --- a/feedingwebapp/src/Pages/Constants.js +++ b/feedingwebapp/src/Pages/Constants.js @@ -29,6 +29,7 @@ MOVING_STATE_ICON_DICT[MEAL_STATE.R_MovingFromMouth] = '/robot_state_imgs/move_t MOVING_STATE_ICON_DICT[MEAL_STATE.R_MovingToMouth] = '/robot_state_imgs/move_to_mouth_position.svg' MOVING_STATE_ICON_DICT[MEAL_STATE.R_StowingArm] = '/robot_state_imgs/stowing_arm_position.svg' export { MOVING_STATE_ICON_DICT } +export const TABLE_ICON = '/robot_state_imgs/table.svg' // The names of the ROS topic(s) export const CAMERA_FEED_TOPIC = '/local/camera/color/image_raw/compressed' @@ -122,7 +123,7 @@ export const GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_param export const GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters' export const SET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/set_parameters_atomically' export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParametersAtomically' -export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_parameters' +export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME = 'ada_planning_scene/get_parameters' export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters' // The names of parameters users can change in the settings menu diff --git a/feedingwebapp/src/Pages/Settings/Main.jsx b/feedingwebapp/src/Pages/Settings/Main.jsx index 1b91470..a524163 100644 --- a/feedingwebapp/src/Pages/Settings/Main.jsx +++ b/feedingwebapp/src/Pages/Settings/Main.jsx @@ -20,7 +20,8 @@ import { MOVING_STATE_ICON_DICT, REGULAR_CONTAINER_ID, SET_PARAMETERS_SERVICE_NAME, - SET_PARAMETERS_SERVICE_TYPE + SET_PARAMETERS_SERVICE_TYPE, + TABLE_ICON } from '../Constants' /** @@ -189,7 +190,7 @@ const Main = () => { }, { title: 'Planning Scene', - icon: null, + icon: TABLE_ICON, onClick: () => onClickSettingsPage(SETTINGS_STATE.PLANNING_SCENE) } ] diff --git a/feedingwebapp/src/Pages/Settings/PlanningScene.jsx b/feedingwebapp/src/Pages/Settings/PlanningScene.jsx index 069a90d..5e458e7 100644 --- a/feedingwebapp/src/Pages/Settings/PlanningScene.jsx +++ b/feedingwebapp/src/Pages/Settings/PlanningScene.jsx @@ -1,6 +1,5 @@ // React imports import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { useMediaQuery } from 'react-responsive' import ButtonGroup from 'react-bootstrap/ButtonGroup' import Dropdown from 'react-bootstrap/Dropdown' import DropdownButton from 'react-bootstrap/DropdownButton' @@ -20,10 +19,6 @@ const PlanningScene = () => { // Get relevant global state variables const setSettingsState = useGlobalState((state) => state.setSettingsState) - // Flag to check if the current orientation is portrait - const isPortrait = useMediaQuery({ query: '(orientation: portrait)' }) - // Indicator of how to arrange screen elements based on orientation - let dimension = isPortrait ? 'column' : 'row' // Rendering variables let textFontSize = '3.5vh' @@ -42,12 +37,14 @@ const PlanningScene = () => { createROSService(ros.current, PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME, PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE) ) const [planningSceneNamespaces, setPlanningSceneNamespaces] = useState([]) - useEffect(() => { + const getPlanningSceneNamespaces = useCallback(() => { let service = getParametersService.current let request = createROSServiceRequest({ names: ['namespaces'] }) + console.log('PlanningScene: Requesting planning scene namespaces', service, request) service.callService(request, (response) => { + console.log('PlanningScene: Received planning scene namespaces', request, response) if (response.values.length > 0 && response.values[0].type === 9) { setPlanningSceneNamespaces(getValueFromParameter(response.values[0])) } else { @@ -55,6 +52,9 @@ const PlanningScene = () => { } }) }, [getParametersService, setPlanningSceneNamespaces]) + useEffect(() => { + getPlanningSceneNamespaces() + }, [getPlanningSceneNamespaces]) // Render the settings for the planning scene const renderPlanningSceneSettings = useCallback(() => { @@ -79,13 +79,14 @@ const PlanningScene = () => { +
Select Planning Scene:
{ variant='secondary' title={currentParams[0]} size='lg' + onClick={() => { + if (planningSceneNamespaces.length === 0) { + getPlanningSceneNamespaces() + } + }} > {planningSceneNamespaces.map((namespace) => ( setCurrentParams([namespace])} active={namespace === currentParams[0]}> @@ -104,7 +110,7 @@ const PlanningScene = () => {
) } - }, [currentParams, dimension, planningSceneNamespaces, setCurrentParams, textFontSize]) + }, [currentParams, planningSceneNamespaces, getPlanningSceneNamespaces, setCurrentParams, textFontSize]) return (