Skip to content

Commit

Permalink
Added staging configuration customization (#136)
Browse files Browse the repository at this point in the history
* Added staging configuration customization

* [WIP] fixes from in-person testing

* Added another food pic

* Remove unnecessary comment

* Remove unnecessary comments

* Update comments

* Removed unnecessary and expensive log

* Ignore build folder when formatting

* Fixes from in-person testing

* Renamed settingsPageAtFace to settingsPageAtMouth
  • Loading branch information
amalnanavati authored May 6, 2024
1 parent b5ddf35 commit b65a9ef
Show file tree
Hide file tree
Showing 16 changed files with 425 additions and 222 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion feedingwebapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint:fix": "eslint \"{,!(node_modules)/**/}*.{js,jsx}\" --fix",
"prettier:fix": "prettier \"{,!(node_modules)/**/}*.{js,jsx,css}\" --write --config ./.prettierrc",
"prettier:fix": "prettier \"{,!(node_modules)/**/}*.{js,jsx,css}\" --write --config ./.prettierrc --ignore-path ./.gitignore",
"format": "npm run prettier:fix && npm run lint:fix"
},
"eslintConfig": {
Expand Down
9 changes: 5 additions & 4 deletions feedingwebapp/src/Pages/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ export const CLEAR_OCTOMAP_SERVICE_NAME = 'clear_octomap'
export const CLEAR_OCTOMAP_SERVICE_TYPE = 'std_srvs/srv/Empty'
export const ACQUISITION_REPORT_SERVICE_NAME = 'ada_feeding_action_select/action_report'
export const ACQUISITION_REPORT_SERVICE_TYPE = 'ada_feeding_msgs/srv/AcquisitionReport'
export const GET_JOINT_STATE_SERVICE_NAME = 'get_joint_state'
export const GET_JOINT_STATE_SERVICE_TYPE = 'ada_feeding_msgs/srv/GetJointState'
export const GET_ROBOT_STATE_SERVICE_NAME = 'get_robot_state'
export const GET_ROBOT_STATE_SERVICE_TYPE = 'ada_feeding_msgs/srv/GetRobotState'
export const GET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/get_parameters'
export const GET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/GetParameters'
export const SET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/set_parameters'
export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParameters'
export const SET_PARAMETERS_SERVICE_NAME = 'ada_feeding_action_servers/set_parameters_atomically'
export const SET_PARAMETERS_SERVICE_TYPE = 'rcl_interfaces/srv/SetParametersAtomically'

// The names of parameters users can change in the settings menu
export const DISTANCE_TO_MOUTH_PARAM = 'MoveToMouth.tree_kwargs.plan_distance_from_mouth'
Expand All @@ -139,6 +139,7 @@ export const RESTING_PARAM_JOINTS_2 = 'MoveToRestingPosition.tree_kwargs.goal_co

// Robot link names
export const ROBOT_BASE_LINK = 'j2n6s200_link_base'
export const ROBOT_END_EFFECTOR = 'forkTip'
export const ROBOT_JOINTS = [
'j2n6s200_joint_1',
'j2n6s200_joint_2',
Expand Down
26 changes: 15 additions & 11 deletions feedingwebapp/src/Pages/GlobalState.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export const SETTINGS_STATE = {
MAIN: 'MAIN',
BITE_TRANSFER: 'BITE_TRANSFER',
ABOVE_PLATE: 'ABOVE_PLATE',
RESTING_CONFIGURATION: 'RESTING_CONFIGURATION'
RESTING_CONFIGURATION: 'RESTING_CONFIGURATION',
STAGING_CONFIGURATION: 'STAGING_CONFIGURATION'
}

// The name of the default parameter namespace
Expand Down Expand Up @@ -140,11 +141,11 @@ export const useGlobalState = create(
biteAcquisitionCheckAutoContinueSecs: 3.0,
biteAcquisitionCheckAutoContinueProbThreshLower: 0.25,
biteAcquisitionCheckAutoContinueProbThreshUpper: 0.75,
// Whether the settings bite transfer page is currently at the user's face
// Whether any of the settings pages is currently at the user's mouth
// or not. This is in the off-chance that the mealState is not at the user's
// face, the settings page is, and the user refreshes -- the page should
// call MoveFromMouthToStaging instead of just MoveToStaging.
biteTransferPageAtFace: false,
// mouth, the settings page is, and the user refreshes -- the page should
// call MoveFromMouth instead of just MoveToStaging.
settingsPageAtMouth: false,
// The button the user most recently clicked on the BiteDone page. In practice,
// this is the state we transition to after R_MovingFromMouth. In practice,
// it is either R_MovingAbovePlate, R_MovingToRestingPosition, or R_DetectingFace.
Expand All @@ -168,7 +169,7 @@ export const useGlobalState = create(
let retval = {
mealState: mealState,
mealStateTransitionTime: Date.now(),
biteTransferPageAtFace: false // Reset this flag when the meal state changes
settingsPageAtMouth: false // Reset this flag when the meal state changes
}
// Only update the previous state if it is not a self-transition (to
// account for cases where a MoveTo action result message is reveived twice)
Expand Down Expand Up @@ -211,9 +212,12 @@ export const useGlobalState = create(
lastMotionActionResponse: lastMotionActionResponse
})),
setMoveToMouthActionGoal: (moveToMouthActionGoal) =>
set(() => ({
moveToMouthActionGoal: moveToMouthActionGoal
})),
set(() => {
console.log('setMoveToMouthActionGoal called with', moveToMouthActionGoal)
return {
moveToMouthActionGoal: moveToMouthActionGoal
}
}),
setPaused: (paused) =>
set(() => {
let retval = { paused: paused }
Expand Down Expand Up @@ -276,9 +280,9 @@ export const useGlobalState = create(
set(() => ({
biteAcquisitionCheckAutoContinueProbThreshUpper: biteAcquisitionCheckAutoContinueProbThreshUpper
})),
setBiteTransferPageAtFace: (biteTransferPageAtFace) =>
setSettingsPageAtMouth: (settingsPageAtMouth) =>
set(() => ({
biteTransferPageAtFace: biteTransferPageAtFace
settingsPageAtMouth: settingsPageAtMouth
})),
setBiteSelectionZoom: (biteSelectionZoom) =>
set(() => ({
Expand Down
2 changes: 1 addition & 1 deletion feedingwebapp/src/Pages/Home/MealStates/BiteSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ const BiteSelection = (props) => {
// Create a service request
let request = createROSServiceRequest({ data: false })
// Call the service
service.callService(request, (response) => console.log('Got toggle face detection service response', response))
service.callService(request, (response) => console.log('Got toggle table detection service response', response))
// Destroy the action client
destroyActionClient(action)
}
Expand Down
22 changes: 7 additions & 15 deletions feedingwebapp/src/Pages/Home/MealStates/DetectingFace.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const DetectingFace = (props) => {
const prevMealState = useGlobalState((state) => state.prevMealState)
const setInNonMovingState = useGlobalState((state) => state.setInNonMovingState)
const setMealState = useGlobalState((state) => state.setMealState)
const setMoveToMouthActionGoal = useGlobalState((state) => state.setMoveToMouthActionGoal)
const faceDetectionAutoContinue = useGlobalState((state) => state.faceDetectionAutoContinue)
const setFaceDetectionAutoContinue = useGlobalState((state) => state.setFaceDetectionAutoContinue)
// Get icon image for move to mouth
Expand Down Expand Up @@ -105,20 +104,13 @@ const DetectingFace = (props) => {
/**
* Callback for when a face is detected within the correct range.
*/
const faceDetectedCallback = useCallback(
(message) => {
console.log('Face detected callback')
setMouthDetected(true)
setMoveToMouthActionGoal({
face_detection: message
})
// If auto-continue is enabled, move to the mouth position
if (autoContinueIsEnabled()) {
moveToMouthCallback()
}
},
[autoContinueIsEnabled, moveToMouthCallback, setMoveToMouthActionGoal]
)
const faceDetectedCallback = useCallback(() => {
setMouthDetected(true)
// If auto-continue is enabled, move to the mouth position
if (autoContinueIsEnabled()) {
moveToMouthCallback()
}
}, [autoContinueIsEnabled, moveToMouthCallback])

/** Get the full page view
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@ import { useMediaQuery } from 'react-responsive'
import { View } from 'react-native'

// Local Imports
import { useROS, createROSService, createROSServiceRequest, subscribeToROSTopic, unsubscribeFromROSTopic } from '../../../ros/ros_helpers'
import { useROS, subscribeToROSTopic, unsubscribeFromROSTopic } from '../../../ros/ros_helpers'
import '../Home.css'
import { MEAL_STATE } from '../../GlobalState'
import { FACE_DETECTION_IMG_TOPIC, FACE_DETECTION_TOPIC, FACE_DETECTION_TOPIC_MSG, ROS_SERVICE_NAMES } from '../../Constants'
import { FACE_DETECTION_IMG_TOPIC, FACE_DETECTION_TOPIC, FACE_DETECTION_TOPIC_MSG } from '../../Constants'
import VideoFeed from '../VideoFeed'
import { useGlobalState } from '../../GlobalState'

/**
* The DetectingFace component appears after the robot has moved to the staging
* configuration. It displays the output of face detection, and automatically
* moves on to `R_MovingToMouth` when a face is detected.
*/
const DetectingFaceSubcomponent = (props) => {
// Get the relevant global variables
const setMoveToMouthActionGoal = useGlobalState((state) => state.setMoveToMouthActionGoal)

// Keep track of whether a mouth has been detected or not
const [mouthDetected, setMouthDetected] = useState(false)
// Flag to check if the current orientation is portrait
Expand Down Expand Up @@ -51,11 +54,14 @@ const DetectingFaceSubcomponent = (props) => {
0.5
if (distance > min_face_distance && distance < max_face_distance) {
setMouthDetected(true)
setMoveToMouthActionGoal({
face_detection: message
})
faceDetectedCallback()
}
}
},
[props.faceDetectedCallback, setMouthDetected]
[props.faceDetectedCallback, setMouthDetected, setMoveToMouthActionGoal]
)
useEffect(() => {
let topic = subscribeToROSTopic(ros.current, FACE_DETECTION_TOPIC, FACE_DETECTION_TOPIC_MSG, faceDetectionCallback)
Expand All @@ -69,38 +75,6 @@ const DetectingFaceSubcomponent = (props) => {
}
}, [faceDetectionCallback])

/**
* Create the ROS Service. This is created in local state to avoid re-creating
* it upon every re-render.
*/
let { serviceName, messageType } = ROS_SERVICE_NAMES[MEAL_STATE.R_DetectingFace]
let toggleFaceDetectionService = useRef(createROSService(ros.current, serviceName, messageType))

/**
* Toggles face detection on the first time this component is rendered, but
* not upon additional re-renders. See here for more details on how `useEffect`
* achieves this goal: https://stackoverflow.com/a/69264685
*/
useEffect(() => {
// Create a service request
let request = createROSServiceRequest({ data: true })
// Call the service
let service = toggleFaceDetectionService.current
service.callService(request, (response) => console.log('Got toggle face detection service response', response))

/**
* In practice, because the values passed in in the second argument of
* useEffect will not change on re-renders, this return statement will
* only be called when the component unmounts.
*/
return () => {
// Create a service request
let request = createROSServiceRequest({ data: false })
// Call the service
service.callService(request, (response) => console.log('Got toggle face detection service response', response))
}
}, [toggleFaceDetectionService])

// Render the component
return (
<>
Expand All @@ -125,7 +99,7 @@ const DetectingFaceSubcomponent = (props) => {
height: '100%'
}}
>
<VideoFeed topic={FACE_DETECTION_IMG_TOPIC} webrtcURL={props.webrtcURL} />
<VideoFeed topic={FACE_DETECTION_IMG_TOPIC} webrtcURL={props.webrtcURL} toggleFaceDetection={true} />
</View>
</>
)
Expand Down
Loading

0 comments on commit b65a9ef

Please sign in to comment.