Skip to content

Commit

Permalink
Temporary fix for video latency (#111)
Browse files Browse the repository at this point in the history
* Revert default sim image to match with depth

* Lower publication rate to prevent lag on VideoFeed

* Aesthetic changes on DetectingFood

* Change updateHz in app to 3Hz
  • Loading branch information
amalnanavati committed Jan 10, 2024
1 parent b40a684 commit ec73b0e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<remap from="~/camera_info" to="/camera/color/camera_info"/>
<remap from="~/aligned_depth/camera_info" to="/camera/aligned_depth_to_color/camera_info"/>
<param name="fps" value="30"/>
<param name="rgb_path" value="$(find-pkg-share feeding_web_app_ros2_test)/../data/2022_11_01_ada_picks_up_carrots_camera_compressed_ft_tf.mp4"/>
<param name="rgb_path" value="$(find-pkg-share feeding_web_app_ros2_test)/../data/above_plate_1_rgb.jpg"/>
<param name="depth_path" value="$(find-pkg-share feeding_web_app_ros2_test)/../data/above_plate_1_depth.png"/>
</node>
</group>
Expand Down
4 changes: 2 additions & 2 deletions feedingwebapp/src/Pages/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ NON_MOVING_STATES.add(MEAL_STATE.U_PostMeal)
export { NON_MOVING_STATES }

// The names of the ROS topic(s)
export const CAMERA_FEED_TOPIC = '/local/camera/color/image_raw/compressed'
export const CAMERA_FEED_TOPIC = '/local/camera/color/image_raw/compressed/low_hz'
export const FACE_DETECTION_TOPIC = '/face_detection'
export const FACE_DETECTION_TOPIC_MSG = 'ada_feeding_msgs/FaceDetection'
export const FACE_DETECTION_IMG_TOPIC = '/face_detection_img/compressed'
export const FACE_DETECTION_IMG_TOPIC = '/face_detection_img/compressed/low_hz'

// States from which, if they fail, it is NOT okay for the user to retry the
// same action.
Expand Down
4 changes: 2 additions & 2 deletions feedingwebapp/src/Pages/Home/MealStates/DetectingFace.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ const DetectingFace = () => {
// Font size for text
let textFontSize = 3
let buttonWidth = 30
let buttonHeight = 20
let buttonHeight = 18
let iconWidth = 28
let iconHeight = 18
let iconHeight = 16
let sizeSuffix = isPortrait ? 'vh' : 'vw'
// The min and max distance from the camera to the face for the face to be
// conidered valid. NOTE: This must match the values in the MoveToMouth tree.
Expand Down
68 changes: 41 additions & 27 deletions feedingwebapp/src/Pages/Home/VideoFeed.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,30 +85,39 @@ const VideoFeed = (props) => {
* re-connecting upon re-renders.
*/
const ros = useRef(useROS().ros)
// Store the latest image timestamp in a ref to avoid re-generating cameraCallback
const latestImageTimestamp = useRef(null)
// Store the latest image message in a ref to avoid re-generating cameraCallback
const latestImageMessage = useRef(null)

/**
* Subscribe to the image topic.
*/
const cameraCallback = useCallback(
(message) => {
// console.log('Got camera message', message)
if (!latestImageTimestamp.current || props.updateRateHz <= 0) {
setLatestRenderedImg(message)
} else {
let currTime = message.header.stamp.sec + message.header.stamp.nanosec * 1e-9
if (currTime - latestImageTimestamp.current >= 1.0 / props.updateRateHz) {
setLatestRenderedImg(message)
latestImageTimestamp.current = currTime
}
}
latestImageMessage.current = message
},
[latestImageTimestamp, setLatestRenderedImg, props.updateRateHz]
[latestImageMessage]
)

/**
* Create a timer to re-render the latest image every props.updateRateHz
*/
const [updateHzCurrentDate, setUpdateHzCurrentDate] = useState(new Date())
useEffect(() => {
setTimeout(() => {
setUpdateHzCurrentDate(new Date())
setLatestRenderedImg(latestImageMessage.current)
}, 1000 / props.updateRateHz)
}, [updateHzCurrentDate, setUpdateHzCurrentDate, props.updateRateHz, setLatestRenderedImg, latestImageMessage])
/**
* Create a timer to re-render the latest image every props.updateRateHz
*/
const [resubscribeRateCurrentDate, setResubscribeRateCurrentDate] = useState(new Date())
useEffect(() => {
console.log('subscribing to img topic')
let topic = subscribeToROSTopic(ros.current, props.topic, 'sensor_msgs/CompressedImage', cameraCallback)
setTimeout(() => {
setResubscribeRateCurrentDate(new Date())
}, 1000 / props.resubscribeRateHz)
const cleanup = () => {
console.log('unsubscribing from img topic')
unsubscribeFromROSTopic(topic, cameraCallback)
Expand All @@ -123,7 +132,7 @@ const VideoFeed = (props) => {
window.removeEventListener('beforeunload', cleanup)
cleanup()
}
}, [cameraCallback, props.topic])
}, [cameraCallback, props.topic, props.resubscribeRateHz, resubscribeRateCurrentDate, setResubscribeRateCurrentDate])

// Callback to resize the image based on the parent width and height
const resizeImage = useCallback(() => {
Expand Down Expand Up @@ -192,18 +201,20 @@ const VideoFeed = (props) => {

// Render the component
return (
<img
src={`data:image/jpeg;base64,${latestRenderedImg ? latestRenderedImg.data : ''}`}
alt='Live video feed from the robot'
style={{
width: imgWidth,
height: imgHeight,
display: 'block',
alignItems: 'center',
justifyContent: 'center'
}}
onClick={props.pointClicked ? imageClicked : null}
/>
<>
<img
src={`data:image/jpeg;base64,${latestRenderedImg ? latestRenderedImg.data : ''}`}
alt='Live video feed from the robot'
style={{
width: imgWidth,
height: imgHeight,
display: 'block',
alignItems: 'center',
justifyContent: 'center'
}}
onClick={props.pointClicked ? imageClicked : null}
/>
</>
)
}
VideoFeed.propTypes = {
Expand All @@ -218,6 +229,8 @@ VideoFeed.propTypes = {
topic: PropTypes.string.isRequired,
// The rate at which to update the video feed, in Hz
updateRateHz: PropTypes.number.isRequired,
// The rate at which to resubscribe to the image topic
resubscribeRateHz: PropTypes.number.isRequired,
/**
* An optional callback function for when the user clicks on the video feed.
* This function should take in two parameters, `x` and `y`, which are the
Expand All @@ -228,7 +241,8 @@ VideoFeed.propTypes = {
}
VideoFeed.defaultProps = {
topic: CAMERA_FEED_TOPIC,
updateRateHz: 10
updateRateHz: 3,
resubscribeRateHz: 0.1
}

export default VideoFeed

0 comments on commit ec73b0e

Please sign in to comment.