diff --git a/feedingwebapp/public/robot_state_imgs/forward.svg b/feedingwebapp/public/robot_state_imgs/forward.svg new file mode 100644 index 0000000..a028f7b --- /dev/null +++ b/feedingwebapp/public/robot_state_imgs/forward.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/feedingwebapp/src/Pages/Constants.js b/feedingwebapp/src/Pages/Constants.js index 88cc6ba..5a22897 100644 --- a/feedingwebapp/src/Pages/Constants.js +++ b/feedingwebapp/src/Pages/Constants.js @@ -30,6 +30,7 @@ MOVING_STATE_ICON_DICT[MEAL_STATE.R_MovingToMouth] = '/robot_state_imgs/move_to_ 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' +export const FORWARD_ICON = '/robot_state_imgs/forward.svg' // The names of the ROS topic(s) export const CAMERA_FEED_TOPIC = '/local/camera/color/image_raw/compressed' diff --git a/feedingwebapp/src/Pages/GlobalState.jsx b/feedingwebapp/src/Pages/GlobalState.jsx index c530b38..0a3e03e 100644 --- a/feedingwebapp/src/Pages/GlobalState.jsx +++ b/feedingwebapp/src/Pages/GlobalState.jsx @@ -94,7 +94,8 @@ export const SETTINGS_STATE = { RESTING_CONFIGURATION: 'RESTING_CONFIGURATION', STAGING_CONFIGURATION: 'STAGING_CONFIGURATION', STOW_CONFIGURATION: 'STOW_CONFIGURATION', - PLANNING_SCENE: 'PLANNING_SCENE' + PLANNING_SCENE: 'PLANNING_SCENE', + AUTO_CONTINUE: 'AUTO_CONTINUE' } // The name of the default parameter namespace @@ -140,7 +141,7 @@ export const useGlobalState = create( teleopAngularSpeed: 0.15, // rad/s teleopJointSpeed: 0.2, // rad/s // Flag to indicate whether to auto-continue after face detection - faceDetectionAutoContinue: true, + faceDetectionAutoContinue: false, // Flag to indicate whether to auto-continue in bite done after food-on-fork detection biteDoneAutoContinue: false, biteDoneAutoContinueSecs: 3.0, diff --git a/feedingwebapp/src/Pages/Settings/AutoContinue.jsx b/feedingwebapp/src/Pages/Settings/AutoContinue.jsx new file mode 100644 index 0000000..6e58258 --- /dev/null +++ b/feedingwebapp/src/Pages/Settings/AutoContinue.jsx @@ -0,0 +1,137 @@ +// React imports +import React, { useCallback, useMemo, useState } from 'react' +import { View } from 'react-native' + +// Local imports +import { useGlobalState, SETTINGS_STATE } from '../GlobalState' +import SettingsPageParent from './SettingsPageParent' + +/** + * The AutoContinue component allows users to change the auto-continue settings + * from the Settings menu. + */ +const AutoContinue = () => { + // Get relevant global state variables + const setSettingsState = useGlobalState((state) => state.setSettingsState) + const biteAcquisitionCheckAutoContinue = useGlobalState((state) => state.biteAcquisitionCheckAutoContinue) + const setBiteAcquisitionCheckAutoContinue = useGlobalState((state) => state.setBiteAcquisitionCheckAutoContinue) + const faceDetectionAutoContinue = useGlobalState((state) => state.faceDetectionAutoContinue) + const setFaceDetectionAutoContinue = useGlobalState((state) => state.setFaceDetectionAutoContinue) + const biteDoneAutoContinue = useGlobalState((state) => state.biteDoneAutoContinue) + const setBiteDoneAutoContinue = useGlobalState((state) => state.setBiteDoneAutoContinue) + + // Rendering variables + let textFontSize = '3.5vh' + + // Configure the parameters for SettingsPageParent + const paramNames = useMemo(() => [], []) + const [currentParams, setCurrentParams] = useState([]) + + // Render the settings for the planning scene + const renderAutoContinueSettings = useCallback(() => { + return ( + + +

+ { + setBiteAcquisitionCheckAutoContinue(e.target.checked) + }} + style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }} + /> + Auto-continue after acquisition +

+
+ +

+ { + setFaceDetectionAutoContinue(e.target.checked) + }} + style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }} + /> + Auto-continue after face detection +

+
+ +

+ { + setBiteDoneAutoContinue(e.target.checked) + }} + style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }} + /> + Auto-continue after transfer +

+
+
+ ) + }, [ + textFontSize, + biteAcquisitionCheckAutoContinue, + setBiteAcquisitionCheckAutoContinue, + faceDetectionAutoContinue, + setFaceDetectionAutoContinue, + biteDoneAutoContinue, + setBiteDoneAutoContinue + ]) + + return ( + setSettingsState(SETTINGS_STATE.MAIN)} + modalShow={false} + modalOnHide={null} + modalChildren={null} + paramNames={paramNames} + localParamValues={currentParams} + setLocalParamValues={setCurrentParams} + > + {renderAutoContinueSettings()} + + ) +} + +export default AutoContinue diff --git a/feedingwebapp/src/Pages/Settings/Main.jsx b/feedingwebapp/src/Pages/Settings/Main.jsx index a524163..1a515ae 100644 --- a/feedingwebapp/src/Pages/Settings/Main.jsx +++ b/feedingwebapp/src/Pages/Settings/Main.jsx @@ -21,7 +21,8 @@ import { REGULAR_CONTAINER_ID, SET_PARAMETERS_SERVICE_NAME, SET_PARAMETERS_SERVICE_TYPE, - TABLE_ICON + TABLE_ICON, + FORWARD_ICON } from '../Constants' /** @@ -192,6 +193,11 @@ const Main = () => { title: 'Planning Scene', icon: TABLE_ICON, onClick: () => onClickSettingsPage(SETTINGS_STATE.PLANNING_SCENE) + }, + { + title: 'Auto-Continue', + icon: FORWARD_ICON, + onClick: () => onClickSettingsPage(SETTINGS_STATE.AUTO_CONTINUE) } ] @@ -271,7 +277,7 @@ const Main = () => { display: 'flex' }} alt={config.title} - className='center' + className='settingsImage' />

{ ) case SETTINGS_STATE.PLANNING_SCENE: return + case SETTINGS_STATE.AUTO_CONTINUE: + return default: console.log('Invalid settings state', settingsState) return

diff --git a/feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx b/feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx index e062c5d..7a217d1 100644 --- a/feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx +++ b/feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx @@ -76,6 +76,11 @@ const SettingsPageParent = (props) => { */ const setLocalParametersToGlobalValues = useCallback( (preset) => { + if (props.paramNames.length === 0) { + console.log('Skipping setLocalParametersToGlobalValues because there are no parameters to get.') + return + } + let service = getParametersService.current let setLocalParamValues = props.setLocalParamValues @@ -134,6 +139,10 @@ const SettingsPageParent = (props) => { * Save the current parameter values to the current namespace. */ const setGlobalParameter = useCallback(() => { + if (props.paramNames.length === 0) { + console.log('Skipping setGlobalParameter because there are no parameters to set.') + return + } if (props.localParamValues.every((element) => element === null)) { console.log('Skipping setGlobalParameter because all values are null.') return @@ -240,42 +249,46 @@ const SettingsPageParent = (props) => { height: '100%' }} > - -

- {props.title} -

- + ) : ( + - resetToPreset(DEFAULT_NAMESPACE)}> - Reset parameter to {DEFAULT_NAMESPACE} - - {settingsPresets.customNames - .filter((preset) => preset !== settingsPresets.current) - .map((preset) => ( - resetToPreset(preset)}> - Reset parameter to {preset} - - ))} - -
+

+ {props.title} +

+ + resetToPreset(DEFAULT_NAMESPACE)}> + Reset parameter to {DEFAULT_NAMESPACE} + + {settingsPresets.customNames + .filter((preset) => preset !== settingsPresets.current) + .map((preset) => ( + resetToPreset(preset)}> + Reset parameter to {preset} + + ))} + + + )}