Skip to content
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

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

Merged
merged 3 commits into from
Sep 1, 2024
Merged
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
@@ -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'
5 changes: 3 additions & 2 deletions feedingwebapp/src/Pages/GlobalState.jsx
Original file line number Diff line number Diff line change
@@ -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,
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
@@ -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'
/>
<p
style={{
3 changes: 3 additions & 0 deletions feedingwebapp/src/Pages/Settings/Settings.jsx
Original file line number Diff line number Diff line change
@@ -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
@@ -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 />
79 changes: 46 additions & 33 deletions feedingwebapp/src/Pages/Settings/SettingsPageParent.jsx
Original file line number Diff line number Diff line change
@@ -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%'
}}
>
<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,