Skip to content

Allow users to change auto-continue from Settings Menu #147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 1, 2024
Merged
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
9 changes: 9 additions & 0 deletions feedingwebapp/public/robot_state_imgs/forward.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions feedingwebapp/src/Pages/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
5 changes: 3 additions & 2 deletions feedingwebapp/src/Pages/GlobalState.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
137 changes: 137 additions & 0 deletions feedingwebapp/src/Pages/Settings/AutoContinue.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: '100%'
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
width: '100%'
}}
>
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: textFontSize }}>
<input
name='biteAcquisitionCheckAutoContinue'
type='checkbox'
checked={biteAcquisitionCheckAutoContinue}
onChange={(e) => {
setBiteAcquisitionCheckAutoContinue(e.target.checked)
}}
style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }}
/>
Auto-continue after acquisition
</p>
</View>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
width: '100%'
}}
>
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: textFontSize }}>
<input
name='faceDetectionAutoContinue'
type='checkbox'
checked={faceDetectionAutoContinue}
onChange={(e) => {
setFaceDetectionAutoContinue(e.target.checked)
}}
style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }}
/>
Auto-continue after face detection
</p>
</View>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
width: '100%'
}}
>
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: textFontSize }}>
<input
name='biteDoneAutoContinue'
type='checkbox'
checked={biteDoneAutoContinue}
onChange={(e) => {
setBiteDoneAutoContinue(e.target.checked)
}}
style={{ transform: 'scale(2.0)', verticalAlign: 'middle', marginRight: '15px' }}
/>
Auto-continue after transfer
</p>
</View>
</View>
)
}, [
textFontSize,
biteAcquisitionCheckAutoContinue,
setBiteAcquisitionCheckAutoContinue,
faceDetectionAutoContinue,
setFaceDetectionAutoContinue,
biteDoneAutoContinue,
setBiteDoneAutoContinue
])

return (
<SettingsPageParent
title='Auto-Continue &#9881;'
doneCallback={() => setSettingsState(SETTINGS_STATE.MAIN)}
modalShow={false}
modalOnHide={null}
modalChildren={null}
paramNames={paramNames}
localParamValues={currentParams}
setLocalParamValues={setCurrentParams}
>
{renderAutoContinueSettings()}
</SettingsPageParent>
)
}

export default AutoContinue
10 changes: 8 additions & 2 deletions feedingwebapp/src/Pages/Settings/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
REGULAR_CONTAINER_ID,
SET_PARAMETERS_SERVICE_NAME,
SET_PARAMETERS_SERVICE_TYPE,
TABLE_ICON
TABLE_ICON,
FORWARD_ICON
} from '../Constants'

/**
Expand Down Expand Up @@ -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)
}
]

Expand Down Expand Up @@ -271,7 +277,7 @@ const Main = () => {
display: 'flex'
}}
alt={config.title}
className='center'
className='settingsImage'
/>
<p
style={{
Expand Down
3 changes: 3 additions & 0 deletions feedingwebapp/src/Pages/Settings/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
STOW_PARAM_JOINTS
} from '../Constants'
import PlanningScene from './PlanningScene'
import AutoContinue from './AutoContinue'

/**
* The Settings components displays the appropriate settings page based on the
Expand Down Expand Up @@ -141,6 +142,8 @@ const Settings = (props) => {
)
case SETTINGS_STATE.PLANNING_SCENE:
return <PlanningScene />
case SETTINGS_STATE.AUTO_CONTINUE:
return <AutoContinue />
default:
console.log('Invalid settings state', settingsState)
return <Main />
Expand Down
79 changes: 46 additions & 33 deletions feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -240,42 +249,46 @@ const SettingsPageParent = (props) => {
height: '100%'
}}
>
<View
style={{
flex: 4,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
zIndex: 1
}}
>
<p style={{ textAlign: 'center', fontSize: textFontSize.toString() + sizeSuffix, margin: 0 }} className='txt-huge'>
{props.title}
</p>
<SplitButton
variant='secondary'
className='mx-2 mb-2 btn-huge'
size='lg'
{props.paramNames.length === 0 ? (
<></>
) : (
<View
style={{
fontSize: textFontSize.toString() + sizeSuffix,
marginLeft: '1rem'
flex: 4,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
zIndex: 1
}}
title={settingsPresets.current}
>
<Dropdown.Item key={DEFAULT_NAMESPACE} onClick={() => resetToPreset(DEFAULT_NAMESPACE)}>
Reset parameter to {DEFAULT_NAMESPACE}
</Dropdown.Item>
{settingsPresets.customNames
.filter((preset) => preset !== settingsPresets.current)
.map((preset) => (
<Dropdown.Item key={preset} onClick={() => resetToPreset(preset)}>
Reset parameter to {preset}
</Dropdown.Item>
))}
</SplitButton>
</View>
<p style={{ textAlign: 'center', fontSize: textFontSize.toString() + sizeSuffix, margin: 0 }} className='txt-huge'>
{props.title}
</p>
<SplitButton
variant='secondary'
className='mx-2 mb-2 btn-huge'
size='lg'
style={{
fontSize: textFontSize.toString() + sizeSuffix,
marginLeft: '1rem'
}}
title={settingsPresets.current}
>
<Dropdown.Item key={DEFAULT_NAMESPACE} onClick={() => resetToPreset(DEFAULT_NAMESPACE)}>
Reset parameter to {DEFAULT_NAMESPACE}
</Dropdown.Item>
{settingsPresets.customNames
.filter((preset) => preset !== settingsPresets.current)
.map((preset) => (
<Dropdown.Item key={preset} onClick={() => resetToPreset(preset)}>
Reset parameter to {preset}
</Dropdown.Item>
))}
</SplitButton>
</View>
)}
<View
style={{
flex: 32,
Expand Down
Loading