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 (