Skip to content

Commit c4fd19d

Browse files
authored
Extend Settings to allow customizing planning scene and bite transfer speed (#146)
* Allow users to adjust speed in the Bite Transfer settings * Allow users to customize planning scene from settings * Fixes from testing
1 parent 98ca809 commit c4fd19d

File tree

7 files changed

+275
-20
lines changed

7 files changed

+275
-20
lines changed
Loading

feedingwebapp/src/Pages/Constants.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ MOVING_STATE_ICON_DICT[MEAL_STATE.R_MovingFromMouth] = '/robot_state_imgs/move_t
2929
MOVING_STATE_ICON_DICT[MEAL_STATE.R_MovingToMouth] = '/robot_state_imgs/move_to_mouth_position.svg'
3030
MOVING_STATE_ICON_DICT[MEAL_STATE.R_StowingArm] = '/robot_state_imgs/stowing_arm_position.svg'
3131
export { MOVING_STATE_ICON_DICT }
32+
export const TABLE_ICON = '/robot_state_imgs/table.svg'
3233

3334
// The names of the ROS topic(s)
3435
export const CAMERA_FEED_TOPIC = '/local/camera/color/image_raw/compressed'
@@ -122,14 +123,21 @@ export const GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_param
122123
export const GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters'
123124
export const SET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/set_parameters_atomically'
124125
export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParametersAtomically'
126+
export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_NAME = 'ada_planning_scene/get_parameters'
127+
export const PLANNING_SCENE_GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters'
125128

126129
// The names of parameters users can change in the settings menu
127130
export const DISTANCE_TO_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.plan_distance_from_mouth'
131+
export const MOVE_TO_MOUTH_SPEED_PARAM = 'MoveToMouth.tree_kwargs.max_linear_speed'
132+
export const MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.linear_speed_near_mouth'
133+
export const MOVE_FROM_MOUTH_SPEED_PARAM = 'MoveFromMouth.tree_kwargs.max_linear_speed_to_staging_configuration'
134+
export const MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM = 'MoveFromMouth.tree_kwargs.linear_speed_near_mouth'
135+
export const PLANNING_SCENE_PARAM = 'planning_scene_namespace_to_use'
128136
export const ABOVE_PLATE_PARAM_JOINTS = 'MoveAbovePlate.tree_kwargs.joint_positions'
129137
export const STAGING_PARAM_JOINTS = 'MoveToStagingConfiguration.tree_kwargs.goal_configuration'
130138
export const STAGING_PARAM_POSITION = 'MoveFromMouth.tree_kwargs.staging_configuration_position'
131139
export const STAGING_PARAM_ORIENTATION = 'MoveFromMouth.tree_kwargs.staging_configuration_quat_xyzw'
132-
// TODO: Eventually, we should break AcquireFood into two actionss to avoid these
140+
// TODO: Eventually, we should break AcquireFood into two actions to avoid these
133141
// two different resting parameters.
134142
export const RESTING_PARAM_JOINTS_1 = 'AcquireFood.tree_kwargs.resting_joint_positions'
135143
// TODO: We may need to remove the orientation constraint from the below action.

feedingwebapp/src/Pages/GlobalState.jsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ export { NON_MOVING_STATES }
7676
/**
7777
* SETTINGS_STATE controls which settings page to display.
7878
* - MAIN: The main page, with options to navigate to the other pages.
79-
* - DISTANCE_TO_MOUTH: Allow the user to customize how close the robot gets
80-
* to their mouth.
79+
* - BITE_TRANSFER: Allow the user to customize how close the robot gets
80+
* to their mouth and the speed of approach/departure.
8181
* - ABOVE_PLATE: Allow the user to customize how high the fixed above plate
8282
* arm configuration.
8383
* - RESTING_CONFIGURATION: Allow the user to customize the fixed resting
@@ -89,11 +89,12 @@ export { NON_MOVING_STATES }
8989
*/
9090
export const SETTINGS_STATE = {
9191
MAIN: 'MAIN',
92-
DISTANCE_TO_MOUTH: 'DISTANCE_TO_MOUTH',
92+
BITE_TRANSFER: 'BITE_TRANSFER',
9393
ABOVE_PLATE: 'ABOVE_PLATE',
9494
RESTING_CONFIGURATION: 'RESTING_CONFIGURATION',
9595
STAGING_CONFIGURATION: 'STAGING_CONFIGURATION',
96-
STOW_CONFIGURATION: 'STOW_CONFIGURATION'
96+
STOW_CONFIGURATION: 'STOW_CONFIGURATION',
97+
PLANNING_SCENE: 'PLANNING_SCENE'
9798
}
9899

99100
// The name of the default parameter namespace

feedingwebapp/src/Pages/Settings/BiteTransfer.jsx

+104-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import Button from 'react-bootstrap/Button'
77
import { View } from 'react-native'
88

99
// Local imports
10-
import { getRobotMotionText, DISTANCE_TO_MOUTH_PARAM } from '../Constants'
10+
import {
11+
getRobotMotionText,
12+
DISTANCE_TO_MOUTH_PARAM,
13+
MOVE_TO_MOUTH_SPEED_PARAM,
14+
MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM,
15+
MOVE_FROM_MOUTH_SPEED_PARAM,
16+
MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM
17+
} from '../Constants'
1118
import { useGlobalState, MEAL_STATE, SETTINGS_STATE } from '../GlobalState'
1219
import RobotMotion from '../Home/MealStates/RobotMotion'
1320
import DetectingFaceSubcomponent from '../Home/MealStates/DetectingFaceSubcomponent'
@@ -28,8 +35,17 @@ const BiteTransfer = (props) => {
2835

2936
// Create relevant local state variables
3037
// Configure the parameters for SettingsPageParent
31-
const paramNames = useMemo(() => [DISTANCE_TO_MOUTH_PARAM], [])
32-
const [currentDistanceToMouth, setCurrentDistanceToMouth] = useState([null])
38+
const paramNames = useMemo(
39+
() => [
40+
DISTANCE_TO_MOUTH_PARAM,
41+
MOVE_TO_MOUTH_SPEED_PARAM,
42+
MOVE_TO_MOUTH_SPEED_NEAR_MOUTH_PARAM,
43+
MOVE_FROM_MOUTH_SPEED_PARAM,
44+
MOVE_FROM_MOUTH_SPEED_NEAR_MOUTH_PARAM
45+
],
46+
[]
47+
)
48+
const [currentParams, setCurrentParams] = useState([null, null, null, null, null])
3349
const [localCurrAndNextMealState, setLocalCurrAndNextMealState] = useState(
3450
globalMealState === MEAL_STATE.U_BiteDone || globalMealState === MEAL_STATE.R_DetectingFace || settingsPageAtMouth
3551
? [MEAL_STATE.R_MovingFromMouth, null]
@@ -53,6 +69,8 @@ const BiteTransfer = (props) => {
5369
// Get min and max distance to mouth
5470
const minDistanceToMouth = 1 // cm
5571
const maxDistanceToMouth = 10 // cm
72+
const minLinearSpeed = 2 // cm/s
73+
const maxLinearSpeed = 15 // cm/s
5674

5775
// When we set local meal state, also update bite transfer page at face
5876
const setLocalCurrMealStateWrapper = useCallback(
@@ -166,16 +184,57 @@ const BiteTransfer = (props) => {
166184
if (value > maxDistanceToMouth) {
167185
value = maxDistanceToMouth
168186
}
169-
let fullDistanceToMouth = [value / 100.0, currentDistanceToMouth[0][1], currentDistanceToMouth[0][2]]
170-
setCurrentDistanceToMouth([fullDistanceToMouth])
187+
let distance_m = value / 100.0
188+
setCurrentParams((currentParams) => [
189+
[distance_m, currentParams[0][1], currentParams[0][2]],
190+
currentParams[1],
191+
currentParams[2],
192+
currentParams[3],
193+
currentParams[4]
194+
])
195+
},
196+
[minDistanceToMouth, maxDistanceToMouth]
197+
)
198+
199+
// Callback for when the user changes the speed to the mouth
200+
const onSpeedChange = useCallback(
201+
(_ev, data, index) => {
202+
let value = data.value !== null ? data.value : parseFloat(data.displayValue)
203+
if (value < minLinearSpeed) {
204+
value = minLinearSpeed
205+
}
206+
if (value > maxLinearSpeed) {
207+
value = maxLinearSpeed
208+
}
209+
let speed_mps = value / 100.0
210+
setCurrentParams((currentParams) => [
211+
currentParams[0],
212+
index === 1 ? speed_mps : currentParams[1],
213+
index === 2 ? speed_mps : currentParams[2],
214+
index === 3 ? speed_mps : currentParams[3],
215+
index === 4 ? speed_mps : currentParams[4]
216+
])
171217
},
172-
[currentDistanceToMouth, minDistanceToMouth, maxDistanceToMouth]
218+
[minLinearSpeed, maxLinearSpeed]
173219
)
174220

175221
// Callback to render the main contents of the page
176222
const distanceToMouthId = useId()
223+
const moveToMouthSpeedId = useId()
224+
const moveToMouthSpeedNearMouthId = useId()
225+
const moveFromMouthSpeedId = useId()
226+
const moveFromMouthSpeedNearMouthId = useId()
227+
const speedParameterIdsAndDescriptions = useMemo(
228+
() => [
229+
[moveToMouthSpeedId, 'Approach Speed (cm/s)'],
230+
[moveToMouthSpeedNearMouthId, 'Approach Speed Near Mouth (cm/s)'],
231+
[moveFromMouthSpeedId, 'Retreat Speed (cm/s)'],
232+
[moveFromMouthSpeedNearMouthId, 'Retreat Speed Near Mouth (cm/s)']
233+
],
234+
[moveToMouthSpeedId, moveToMouthSpeedNearMouthId, moveFromMouthSpeedId, moveFromMouthSpeedNearMouthId]
235+
)
177236
const renderBiteTransferSettings = useCallback(() => {
178-
if (currentDistanceToMouth[0] === null) {
237+
if (currentParams.some((param) => param === null)) {
179238
return (
180239
<>
181240
<View
@@ -225,7 +284,7 @@ const BiteTransfer = (props) => {
225284
Distance To Mouth (cm)
226285
</Label>
227286
<SpinButton
228-
value={currentDistanceToMouth[0][0] * 100}
287+
value={currentParams[0][0] * 100}
229288
id={distanceToMouthId}
230289
step={0.5}
231290
onChange={onDistanceToMouthChange}
@@ -241,6 +300,38 @@ const BiteTransfer = (props) => {
241300
size: 'large'
242301
}}
243302
/>
303+
{speedParameterIdsAndDescriptions.map(([id, description], index) => (
304+
<>
305+
<Label
306+
htmlFor={id}
307+
style={{
308+
fontSize: textFontSize,
309+
width: '90%',
310+
color: 'black',
311+
textAlign: 'center'
312+
}}
313+
>
314+
{description}
315+
</Label>
316+
<SpinButton
317+
value={currentParams[index + 1] * 100}
318+
id={id}
319+
step={1.0}
320+
onChange={(_ev, data) => onSpeedChange(_ev, data, index + 1)}
321+
appearance='filled-lighter'
322+
style={{
323+
fontSize: textFontSize,
324+
width: '90%',
325+
color: 'black'
326+
}}
327+
incrementButton={{
328+
'aria-label': 'Increase value by 1.0',
329+
'aria-roledescription': 'spinner',
330+
size: 'large'
331+
}}
332+
/>
333+
</>
334+
))}
244335
</View>
245336
<View
246337
style={{
@@ -321,9 +412,11 @@ const BiteTransfer = (props) => {
321412
}, [
322413
dimension,
323414
textFontSize,
324-
currentDistanceToMouth,
415+
currentParams,
325416
onDistanceToMouthChange,
417+
onSpeedChange,
326418
distanceToMouthId,
419+
speedParameterIdsAndDescriptions,
327420
moveToMouthButtonClicked,
328421
moveAwayFromMouthButtonClicked
329422
])
@@ -368,8 +461,8 @@ const BiteTransfer = (props) => {
368461
modalOnHide={() => setLocalCurrMealStateWrapper(null)}
369462
modalChildren={renderModalBody()}
370463
paramNames={paramNames}
371-
localParamValues={currentDistanceToMouth}
372-
setLocalParamValues={setCurrentDistanceToMouth}
464+
localParamValues={currentParams}
465+
setLocalParamValues={setCurrentParams}
373466
>
374467
{renderBiteTransferSettings()}
375468
</SettingsPageParent>

feedingwebapp/src/Pages/Settings/Main.jsx

+9-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
MOVING_STATE_ICON_DICT,
2121
REGULAR_CONTAINER_ID,
2222
SET_PARAMETERS_SERVICE_NAME,
23-
SET_PARAMETERS_SERVICE_TYPE
23+
SET_PARAMETERS_SERVICE_TYPE,
24+
TABLE_ICON
2425
} from '../Constants'
2526

2627
/**
@@ -163,9 +164,9 @@ const Main = () => {
163164
// Configure the different options in the settings menu
164165
let settingsConfig = [
165166
{
166-
title: 'Distance to Mouth',
167+
title: 'Motion to/from Mouth',
167168
icon: moveToMouthConfigurationImage,
168-
onClick: () => onClickSettingsPage(SETTINGS_STATE.DISTANCE_TO_MOUTH)
169+
onClick: () => onClickSettingsPage(SETTINGS_STATE.BITE_TRANSFER)
169170
},
170171
{
171172
title: 'Above Plate',
@@ -186,6 +187,11 @@ const Main = () => {
186187
title: 'Stow Position',
187188
icon: moveToStowConfigurationImage,
188189
onClick: () => onClickSettingsPage(SETTINGS_STATE.STOW_CONFIGURATION)
190+
},
191+
{
192+
title: 'Planning Scene',
193+
icon: TABLE_ICON,
194+
onClick: () => onClickSettingsPage(SETTINGS_STATE.PLANNING_SCENE)
189195
}
190196
]
191197

0 commit comments

Comments
 (0)