Skip to content

Controls to Navigate Between Meal States #30

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

Merged
merged 31 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
639e007
add icons
Raidakarim Apr 26, 2023
6f71caa
add distinct pause modals
Raidakarim Apr 26, 2023
a776f74
new colors
Raidakarim Apr 30, 2023
585681e
Merge branch 'main' of https://github.com/personalrobotics/feeding_we…
Raidakarim Apr 30, 2023
2ae352f
use pause modals from const dictionary
Raidakarim Apr 30, 2023
c333187
make one dictionary
Raidakarim Apr 30, 2023
67f7092
small fixes
Raidakarim Apr 30, 2023
bb20469
squash and merge
Raidakarim Apr 30, 2023
e8d3394
Merge branch 'raidak/meal_state_controls' of https://github.com/perso…
Raidakarim Apr 30, 2023
639ebe8
squash
Raidakarim Apr 30, 2023
37ef23e
Merge branch 'raidak/meal_state_controls' of https://github.com/perso…
Raidakarim Apr 30, 2023
11e4097
updated changes for PR comments
Raidakarim May 1, 2023
aa732a1
transparent icons
Raidakarim May 2, 2023
b8fa4bb
pause button fixes
Raidakarim May 3, 2023
12edfc0
pause modal fixes
Raidakarim May 3, 2023
011535d
resize icons and text edits
Raidakarim May 3, 2023
f46859a
fix text
Raidakarim May 3, 2023
547f44d
button size, color, and text fix
Raidakarim May 4, 2023
71af04d
updated icons
Raidakarim May 5, 2023
e2feeba
add new changes
Raidakarim May 5, 2023
334b067
add footer logic
Raidakarim May 8, 2023
b1c61e6
fix comments
Raidakarim May 8, 2023
fcb898b
delete jquery
Raidakarim May 8, 2023
089ef56
fix comments
Raidakarim May 8, 2023
40235af
add todos for the PR
Raidakarim May 8, 2023
b60c462
Merge branch 'main' into raidak/meal_state_controls
Raidakarim May 9, 2023
a1c651f
response to PR comments
Raidakarim May 9, 2023
44c5e41
fix comment font size
Raidakarim May 9, 2023
bf18eb6
fix staging position icon
Raidakarim May 9, 2023
0a34011
resize staging icon
Raidakarim May 9, 2023
70f5d24
add icon acknowledgements
Raidakarim May 9, 2023
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
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions feedingwebapp/src/Pages/Constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
import { MEAL_STATE } from './GlobalState'
// The RealSense's default video stream is 640x480
export const REALSENSE_WIDTH = 640
export const REALSENSE_HEIGHT = 480
/**
* A dictionary containing information for the meal states where the robot moves.
* The meal states are used as keys.
* Each key is paired with a value of an array that has 3 elements in it.
* First 2 array elements contain the text used in pause modal for previous and next meal state of current meal state.
* The 3rd array element contains the previous meal state of current meal state.
*/
export const pause_modal_state_info_dict = {
R_MovingAbovePlate: ['stowing the arm', 'moving above plate', MEAL_STATE.R_StowingArm],
R_BiteAcquisition: ['moving above plate', 'acquiring bite', MEAL_STATE.R_MovingAbovePlate],
R_MovingToStagingLocation: ['moving above plate', 'moving to ready position', MEAL_STATE.R_MovingAbovePlate],
R_MovingToMouth: ['moving to ready position', 'moving to mouth', MEAL_STATE.R_MovingToStagingLocation],
R_StowingArm: ['moving above plate', 'stowing the arm', MEAL_STATE.R_MovingAbovePlate]
}
9 changes: 7 additions & 2 deletions feedingwebapp/src/Pages/Footer/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ const Footer = () => {
<MDBFooter bgColor='dark' className='text-center text-lg-left fixed-bottom'>
<div className='text-center p-3' style={{ backgroundColor: 'rgba(0, 0, 0, 0.2)' }}>
{
<Button className='bg-warning rounded btn-hugeE' style={{ fontSize: '50px' }} size='lg' onClick={() => setPause(true)}>
⏸️ Pause
<Button
className='bg-warning rounded btn-hugeE'
style={{ fontSize: '25px', fontWeight: 'bold' }}
size='lg'
onClick={() => setPause(true)}
>
Pause (⏸️) or Cancel (🗑️)
</Button>
}
</div>
Expand Down
38 changes: 35 additions & 3 deletions feedingwebapp/src/Pages/Footer/PauseModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,37 @@ import Modal from 'react-bootstrap/Modal'
// PropTypes is used to validate that the used props are in fact passed to this
// Component
import PropTypes from 'prop-types'
// local imports
import { pause_modal_state_info_dict } from '../Constants'
import { useGlobalState } from '../GlobalState'

/**
* The PauseModal gives the user the option to resume the robot when they are
* ready.
*/
function PauseModal(props) {
const ref = useRef(null)
// check which meal state we are currently at
var meal_state = useGlobalState((state) => state.mealState)
// function to set a meal state
var setMealState = useGlobalState((state) => state.setMealState)
var return_text = '◀️ Return by '
var proceed_text = '▶️ Continue with '
// access current meal state info from dictionary in constants.js
var state_info_list = pause_modal_state_info_dict[meal_state]
var prev_text_from_dict = state_info_list[0]
var next_text_from_dict = state_info_list[1]
var prev_state_from_dict = state_info_list[2]
return_text = return_text + prev_text_from_dict
proceed_text = proceed_text + next_text_from_dict

/**
* Function to return to previous meal state from the current
* meal state, if user selects "Return to....." option in the pause modal.
*/
function returnButtonCallback() {
setMealState(prev_state_from_dict)
}
return (
<>
{/**
Expand All @@ -39,15 +63,23 @@ function PauseModal(props) {
</Modal.Header>
<Modal.Body style={{ paddingLeft: '10px', overflow: 'hidden' }}>
<p className='transitionMessage' style={{ marginBottom: '10px', marginTop: '0px', fontSize: '24px' }}>
Resume the feeding session when you are ready.
Resume the feeding session.
</p>
<Button
className='bg-warning rounded btn-hugeE'
style={{ fontSize: '50px', marginLeft: '8%' }}
style={{ fontSize: '35px', marginLeft: '8%', fontWeight: 'bold', marginBottom: '8%' }}
size='lg'
onClick={returnButtonCallback}
>
{return_text}
</Button>
<Button
className='bg-warning rounded btn-hugeE'
style={{ fontSize: '35px', marginLeft: '8%', fontWeight: 'bold', marginBottom: '8%' }}
size='lg'
onClick={props.resumeClicked}
>
▶️ Resume
{proceed_text}
</Button>
</Modal.Body>
</Modal>
Expand Down
14 changes: 0 additions & 14 deletions feedingwebapp/src/Pages/Home/MealStates/BiteAcquisition.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@ const BiteAcquisition = (props) => {
const setMealState = useGlobalState((state) => state.setMealState)
const desiredFoodItem = useGlobalState((state) => state.desiredFoodItem)

/**
* Callback function for if the user decides to cancel the bite.
*/
function cancelBite() {
console.log('cancelBite')
setMealState(MEAL_STATE.R_MovingAbovePlate)
}

/**
* Callback function for when the bite acquisition is done.
*/
Expand All @@ -42,12 +34,6 @@ const BiteAcquisition = (props) => {
// Render the component
return (
<>
{/* Give the user the option to cancel this bite */}
<div style={{ display: 'inline-block' }}>
<Button className='cancelButton' style={{ fontSize: '24px', marginTop: '0px' }} onClick={cancelBite}>
🗑 Cancel Bite
</Button>
</div>
{/* TODO: Consider vertically centering this element */}
<Row className='justify-content-center mx-auto my-2 w-75'>
<div>
Expand Down
47 changes: 27 additions & 20 deletions feedingwebapp/src/Pages/Home/MealStates/BiteDone.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,54 @@ const BiteDone = () => {
const setMealState = useGlobalState((state) => state.setMealState)

/**
* Callback function for when the user is done with their bite.
* Callback function for when the user wants to move above plate.
*/
function doneWithBite() {
console.log('readyForBite')
function moveAbovePlate() {
setMealState(MEAL_STATE.R_MovingAbovePlate)
}

/**
* Callback function for if the user decides to cancel the bite.
* Callback function for if the user decides to move to staging position.
*
* TODO: Think more carefully about what cancelBite at this stage should do!
* Maybe replace with a more descriptive button (e.g., "return to staging.")
*/
function cancelBite() {
console.log('cancelBite')
function moveToStagingPosition() {
setMealState(MEAL_STATE.R_MovingToStagingLocation)
}

// Render the component
return (
<div style={{ display: 'block', width: '100%', height: '115vh', overflowX: 'hidden', overflowY: 'auto' }} className='outer'>
{/* Give the user the option to cancel this bite */}
<div style={{ display: 'inline' }}>
<Button className='cancelButton' style={{ fontSize: '24px' }} onClick={cancelBite}>
🗑 Cancel Bite
{/* Ask the user whether they want to move to above plate position */}
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: '148%', fontWeight: 'bold' }}>
Bite finished? Move above plate.
</p>
{/* Icon to move above plate */}
<Row className='justify-content-center mx-auto my-2 w-75'>
<Button
variant='info'
className='mx-2 mb-2 btn-huge'
size='lg'
onClick={moveAbovePlate}
style={{ width: '200px', height: '130px' }}
>
<img src='/robot_state_imgs/move_above_plate_position.svg' alt='move_above_plate_image' className='center' />
</Button>
</div>
</Row>

{/* Ask the user whether they're ready for the bite */}
<p className='transitionMessage' style={{ marginBottom: '0px' }}>
Click the below button to indicate the completion of your bite.
{/* Ask the user whether they want to move to staging position */}
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: '120%' }}>
Take another bite? Move to &quot;ready&quot; position.
</p>
{/* Icon to move to staging position */}
<Row className='justify-content-center mx-auto my-2 w-75'>
<Button
variant='primary'
variant='warning'
className='mx-2 mb-2 btn-huge'
size='lg'
onClick={doneWithBite}
style={{ width: '75%', fontSize: '35px' }}
onClick={moveToStagingPosition}
style={{ width: '110px', height: '71.5px' }}
>
Done with Bite
<img src='/robot_state_imgs/move_to_staging_position.svg' alt='move_to_staging_image' className='center' />
</Button>
</Row>
</div>
Expand Down
46 changes: 27 additions & 19 deletions feedingwebapp/src/Pages/Home/MealStates/BiteInitiation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,52 @@ const BiteInitiation = () => {
* Callback function for when the user is ready for their bite.
*/
function readyForBite() {
console.log('readyForBite')
setMealState(MEAL_STATE.R_MovingToMouth)
}

/**
* Callback function for if the user decides to cancel the bite.
*
* TODO: Think more carefully about what cancelBite at this stage should do!
* Maybe replace with a more descriptive button (e.g., "return above plate.")
* Callback function for when the user wants to move above plate.
*/
function cancelBite() {
console.log('cancelBite')
function moveAbovePlate() {
setMealState(MEAL_STATE.R_MovingAbovePlate)
}

// Render the component
return (
<div style={{ display: 'block', width: '100%', height: '115vh', overflowX: 'hidden', overflowY: 'auto' }} className='outer'>
{/* Give the user the option to cancel this bite */}
<div style={{ display: 'inline' }}>
<Button className='cancelButton' style={{ fontSize: '24px' }} onClick={cancelBite}>
🗑 Cancel Bite
{/* Ask the user whether they want to move to mouth position */}
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: '148%', fontWeight: 'bold' }}>
Ready for bite? Move to mouth.
</p>
{/* Icon to move to mouth */}
{/* Ask the user whether they're ready for the bite */}
<Row className='justify-content-center mx-auto my-2 w-75'>
<Button
variant='success'
className='mx-2 mb-2 btn-huge'
size='lg'
onClick={readyForBite}
style={{ width: '200px', height: '130px' }}
>
<img src='/robot_state_imgs/move_to_mouth_position.svg' alt='move_to_mouth_image' className='center' />
</Button>
</div>
</Row>

{/* Ask the user whether they're ready for the bite */}
<p className='transitionMessage' style={{ marginBottom: '0px' }}>
Click the below button when you are ready for the bite.
{/* Ask the user whether they want to move to above plate position */}
<p className='transitionMessage' style={{ marginBottom: '0px', fontSize: '120%' }}>
Cancel bite and move above plate.
</p>
{/* Icon to move above plate */}
{/* Give the user the option to move robot over plate*/}
<Row className='justify-content-center mx-auto my-2 w-75'>
<Button
variant='primary'
variant='info'
className='mx-2 mb-2 btn-huge'
size='lg'
onClick={readyForBite}
style={{ width: '75%', fontSize: '35px' }}
onClick={moveAbovePlate}
style={{ width: '110px', height: '71.5px' }}
>
Ready for a Bite
<img src='/robot_state_imgs/move_above_plate_position.svg' alt='move_above_plate_image' className='center' />
</Button>
</Row>
</div>
Expand Down
24 changes: 22 additions & 2 deletions feedingwebapp/src/Pages/Home/MealStates/BiteSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import Row from 'react-bootstrap/Row'
// Local Imports
import '../Home.css'
import { useGlobalState, MEAL_STATE } from '../../GlobalState'
import { REALSENSE_WIDTH, REALSENSE_HEIGHT } from '../../Constants'
import { convertRemToPixels, scaleWidthHeightToWindow } from '../../../helpers'

// TODO: Replace the list of items with a view of the camera feed that the user
// can click on.
Expand Down Expand Up @@ -48,9 +50,27 @@ const BiteSelection = () => {
setMealState(MEAL_STATE.R_BiteAcquisition)
}

// Get the size of the robot's live video stream.
const margin = convertRemToPixels(1)
let { width, height } = scaleWidthHeightToWindow(REALSENSE_WIDTH, REALSENSE_HEIGHT, margin, margin, margin, margin)

// Render the component
return (
<>
<div style={{ overflowX: 'hidden', overflowY: 'auto' }} className='outer'>
{/**
* Display the live stream from the robot's camera.
*/}
<center>
<iframe
src={`http://localhost:8080/stream?topic=/camera/color/image_raw&default_transport=compressed&width=${Math.round(
width
)}&height=${Math.round(height)}&quality=20`}
allow='autoplay; encrypted-media'
allowFullScreen
title='video'
style={{ width: width, height: height, display: 'block', margin: '1rem' }}
/>
</center>
{/**
* In addition to selecting their desired food item, the user has two
* other options on this page:
Expand Down Expand Up @@ -99,7 +119,7 @@ const BiteSelection = () => {
</Button>
))}
</Row>
</>
</div>
)
}

Expand Down