diff --git a/feedingwebapp/package-lock.json b/feedingwebapp/package-lock.json index a44f5970..47fec088 100644 --- a/feedingwebapp/package-lock.json +++ b/feedingwebapp/package-lock.json @@ -16,6 +16,7 @@ "axios": "^1.6.5", "body-parser": "^1.20.2", "bootstrap": "^5.1.3", + "caniuse-lite": "^1.0.30001579", "cors": "^2.8.5", "express": "^4.18.2", "mdb-react-ui-kit": "^3.0.0", @@ -7520,9 +7521,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001487", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz", - "integrity": "sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA==", + "version": "1.0.30001579", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", + "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", "funding": [ { "type": "opencollective", diff --git a/feedingwebapp/package.json b/feedingwebapp/package.json index 93b1d99d..a10f3dce 100644 --- a/feedingwebapp/package.json +++ b/feedingwebapp/package.json @@ -11,6 +11,7 @@ "axios": "^1.6.5", "body-parser": "^1.20.2", "bootstrap": "^5.1.3", + "caniuse-lite": "^1.0.30001579", "cors": "^2.8.5", "express": "^4.18.2", "mdb-react-ui-kit": "^3.0.0", diff --git a/feedingwebapp/src/Pages/Constants.js b/feedingwebapp/src/Pages/Constants.js index ab82a840..3e237a49 100644 --- a/feedingwebapp/src/Pages/Constants.js +++ b/feedingwebapp/src/Pages/Constants.js @@ -109,6 +109,8 @@ ROS_SERVICE_NAMES[MEAL_STATE.R_DetectingFace] = { export { ROS_SERVICE_NAMES } 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_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' diff --git a/feedingwebapp/src/Pages/GlobalState.jsx b/feedingwebapp/src/Pages/GlobalState.jsx index 0d0e7391..702990d2 100644 --- a/feedingwebapp/src/Pages/GlobalState.jsx +++ b/feedingwebapp/src/Pages/GlobalState.jsx @@ -121,6 +121,8 @@ export const useGlobalState = create( // message received from the face detection node where a // face was detected and within the distance bounds of the camera. moveToMouthActionGoal: null, + // Last RobotMotion action response + lastMotionActionResponse: null, // Whether or not the currently-executing robot motion was paused by the user paused: false, // Flag to indicate robot motion trough teleoperation interface @@ -171,6 +173,10 @@ export const useGlobalState = create( set(() => ({ biteAcquisitionActionGoal: biteAcquisitionActionGoal })), + setLastMotionActionResponse: (lastMotionActionResponse) => + set(() => ({ + lastMotionActionResponse: lastMotionActionResponse + })), setMoveToMouthActionGoal: (moveToMouthActionGoal) => set(() => ({ moveToMouthActionGoal: moveToMouthActionGoal diff --git a/feedingwebapp/src/Pages/Home/MealStates/BiteAcquisitionCheck.jsx b/feedingwebapp/src/Pages/Home/MealStates/BiteAcquisitionCheck.jsx index a6083ea1..de7eb9ad 100644 --- a/feedingwebapp/src/Pages/Home/MealStates/BiteAcquisitionCheck.jsx +++ b/feedingwebapp/src/Pages/Home/MealStates/BiteAcquisitionCheck.jsx @@ -1,13 +1,16 @@ // React Imports -import React, { useCallback } from 'react' +import React, { useCallback, useRef } from 'react' import Button from 'react-bootstrap/Button' import { useMediaQuery } from 'react-responsive' +import { toast } from 'react-toastify' import { View } from 'react-native' // Local Imports import '../Home.css' import { useGlobalState, MEAL_STATE } from '../../GlobalState' import { MOVING_STATE_ICON_DICT } from '../../Constants' +import { useROS, createROSService, createROSServiceRequest } from '../../../ros/ros_helpers' +import { ACQUISITION_REPORT_SERVICE_NAME, ACQUISITION_REPORT_SERVICE_TYPE } from '../../Constants' /** * The BiteAcquisitionCheck component appears after the robot has attempted to @@ -31,14 +34,37 @@ const BiteAcquisitionCheck = () => { let iconWidth = isPortrait ? '28vh' : '28vw' let iconHeight = isPortrait ? '18vh' : '18vw' + // Configure AcquisitionReport service + const lastMotionActionResponse = useGlobalState((state) => state.lastMotionActionResponse) + /** + * Connect to ROS, if not already connected. Put this in useRef to avoid + * re-connecting upon re-renders. + */ + const ros = useRef(useROS().ros) + /** + * Create the ROS Service Client for reporting success/failure + */ + let acquisitionReportService = useRef(createROSService(ros.current, ACQUISITION_REPORT_SERVICE_NAME, ACQUISITION_REPORT_SERVICE_TYPE)) + /** * Callback function for when the user indicates that the bite acquisition * succeeded. */ const acquisitionSuccess = useCallback(() => { console.log('acquisitionSuccess') + toast.info('Reporting Food Acquisition Success!') + // Create a service request + let request = createROSServiceRequest({ + loss: 0.0, + action_index: lastMotionActionResponse.action_index, + posthoc: lastMotionActionResponse.posthoc, + id: lastMotionActionResponse.selection_id + }) + // Call the service + let service = acquisitionReportService.current + service.callService(request, (response) => console.log('Got acquisition report response', response)) setMealState(MEAL_STATE.R_MovingToStagingConfiguration) - }, [setMealState]) + }, [lastMotionActionResponse, setMealState]) /** * Callback function for when the user indicates that the bite acquisition @@ -46,8 +72,19 @@ const BiteAcquisitionCheck = () => { */ const acquisitionFailure = useCallback(() => { console.log('acquisitionFailure') + toast.info('Reporting Food Acquisition Failure.') + // Create a service request + let request = createROSServiceRequest({ + loss: 1.0, + action_index: lastMotionActionResponse.action_index, + posthoc: lastMotionActionResponse.posthoc, + id: lastMotionActionResponse.selection_id + }) + // Call the service + let service = acquisitionReportService.current + service.callService(request, (response) => console.log('Got acquisition report response', response)) setMealState(MEAL_STATE.R_MovingAbovePlate) - }, [setMealState]) + }, [lastMotionActionResponse, setMealState]) /** * Get the ready for bite text to render. diff --git a/feedingwebapp/src/Pages/Home/MealStates/RobotMotion.jsx b/feedingwebapp/src/Pages/Home/MealStates/RobotMotion.jsx index 07dd3809..607f0dd8 100644 --- a/feedingwebapp/src/Pages/Home/MealStates/RobotMotion.jsx +++ b/feedingwebapp/src/Pages/Home/MealStates/RobotMotion.jsx @@ -63,6 +63,9 @@ const RobotMotion = (props) => { const paused = useGlobalState((state) => state.paused) const setPaused = useGlobalState((state) => state.setPaused) + // Setter for last motion action response + const setLastMotionActionResponse = useGlobalState((state) => state.setLastMotionActionResponse) + /** * Connect to ROS, if not already connected. Put this in useRef to avoid * re-connecting upon re-renders. @@ -143,6 +146,7 @@ const RobotMotion = (props) => { setActionStatus({ actionStatus: ROS_ACTION_STATUS_SUCCEED }) + setLastMotionActionResponse(response.values) robotMotionDone() } else { if ( @@ -163,7 +167,7 @@ const RobotMotion = (props) => { } } }, - [setActionStatus, setPaused, robotMotionDone] + [setLastMotionActionResponse, setActionStatus, setPaused, robotMotionDone] ) /**