Skip to content

Commit 2dc2dfe

Browse files
authored
Allow TeleopSubcomponent to re-tare and change F/T threshold (#140)
* re-tare F/T sensor on teleop (un)mount and refresh * Allow increasing F/T threshold from InfoModal * Improve layout
1 parent cde96aa commit 2dc2dfe

File tree

4 files changed

+141
-34
lines changed

4 files changed

+141
-34
lines changed

feedingwebapp/src/Pages/Constants.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ ROS_ACTIONS_NAMES[MEAL_STATE.R_StowingArm] = {
8787
messageType: 'ada_feeding_msgs/action/MoveTo'
8888
}
8989
export { ROS_ACTIONS_NAMES }
90-
export const START_CARTESIAN_CONTROLLER_ACTION_NAME = 'ActivateCartesianController'
91-
export const START_CARTESIAN_CONTROLLER_ACTION_TYPE = 'ada_feeding_msgs/action/Trigger'
92-
export const START_JOINT_CONTROLLER_ACTION_NAME = 'ActivateJointController'
93-
export const START_JOINT_CONTROLLER_ACTION_TYPE = 'ada_feeding_msgs/action/Trigger'
90+
export const ACTIVATE_CONTROLLER_ACTION_NAME = 'ActivateController'
91+
export const ACTIVATE_CONTROLLER_ACTION_TYPE = 'ada_feeding_msgs/action/ActivateController'
92+
export const CARTESIAN_CONTROLLER_NAME = 'jaco_arm_cartesian_controller'
93+
export const JOINT_CONTROLLER_NAME = 'jaco_arm_servo_controller'
9494
export const RECOMPUTE_WORKSPACE_WALLS_ACTION_NAME = 'recompute_workspace_walls'
9595
export const RECOMPUTE_WORKSPACE_WALLS_ACTION_TYPE = 'ada_feeding_msgs/action/Trigger'
9696

@@ -139,6 +139,11 @@ export const RESTING_PARAM_JOINTS_1 = 'AcquireFood.tree_kwargs.resting_joint_pos
139139
// TODO: We may need to remove the orientation constraint from the below action.
140140
export const RESTING_PARAM_JOINTS_2 = 'MoveToRestingPosition.tree_kwargs.goal_configuration'
141141

142+
// Parameters for modifying the force threshold
143+
export const FORCE_THRESHOLD_PARAM = 'wrench_threshold.fMag'
144+
export const DEFAULT_FORCE_THRESHOLD = 1.0 // N
145+
export const INCREASED_FORCE_THRESHOLD = 75.0 // N
146+
142147
// Robot link names
143148
export const ROBOT_BASE_LINK = 'j2n6s200_link_base'
144149
export const ROBOT_END_EFFECTOR = 'forkTip'

feedingwebapp/src/Pages/Header/InfoModal.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ function InfoModal(props) {
9494
<ToastContainer style={{ fontSize: textFontSize }} containerId={MODAL_CONTAINER_ID} enableMultiContainer={true} />
9595
<View
9696
style={{
97-
flex: 2,
97+
flex: 3,
9898
flexDirection: otherDirection,
9999
justifyContent: 'center',
100100
alignItems: 'center',
@@ -112,7 +112,7 @@ function InfoModal(props) {
112112
</View>
113113
<View
114114
style={{
115-
flex: 9,
115+
flex: 18,
116116
flexDirection: 'row',
117117
justifyContent: 'center',
118118
alignItems: 'center',
@@ -124,7 +124,7 @@ function InfoModal(props) {
124124
{mode === VIDEO_MODE ? (
125125
<VideoFeed topic={CAMERA_FEED_TOPIC} updateRateHz={10} webrtcURL={props.webrtcURL} />
126126
) : mode === TELEOP_MODE ? (
127-
<TeleopSubcomponent />
127+
<TeleopSubcomponent allowIncreasingForceThreshold={true} />
128128
) : mode === SYSTEM_STATUS_MODE ? (
129129
<div>System Status</div>
130130
) : (

feedingwebapp/src/Pages/Header/TeleopSubcomponent.jsx

Lines changed: 123 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,33 @@ import PropTypes from 'prop-types'
77
import { View } from 'react-native'
88

99
// Local Imports
10-
import { useROS, createROSTopic, createROSMessage, createROSActionClient, callROSAction, destroyActionClient } from '../../ros/ros_helpers'
10+
import {
11+
useROS,
12+
createROSTopic,
13+
createROSMessage,
14+
createROSActionClient,
15+
callROSAction,
16+
destroyActionClient,
17+
createROSService,
18+
createROSServiceRequest,
19+
getParameterFromValue
20+
} from '../../ros/ros_helpers'
1121
import '../Home/Home.css'
1222
import {
23+
CARTESIAN_CONTROLLER_NAME,
24+
JOINT_CONTROLLER_NAME,
1325
ROBOT_BASE_LINK,
1426
ROBOT_JOINTS,
1527
SERVO_CARTESIAN_TOPIC,
1628
SERVO_CARTESIAN_TOPIC_MSG,
1729
SERVO_JOINT_TOPIC,
1830
SERVO_JOINT_TOPIC_MSG,
19-
START_CARTESIAN_CONTROLLER_ACTION_NAME,
20-
START_CARTESIAN_CONTROLLER_ACTION_TYPE,
21-
START_JOINT_CONTROLLER_ACTION_NAME,
22-
START_JOINT_CONTROLLER_ACTION_TYPE
31+
ACTIVATE_CONTROLLER_ACTION_NAME,
32+
ACTIVATE_CONTROLLER_ACTION_TYPE,
33+
SET_PARAMETERS_SERVICE_NAME,
34+
INCREASED_FORCE_THRESHOLD,
35+
DEFAULT_FORCE_THRESHOLD,
36+
FORCE_THRESHOLD_PARAM
2337
} from '../Constants'
2438
import { useGlobalState } from '../GlobalState'
2539
import HoldButton from '../../buttons/HoldButton'
@@ -122,11 +136,17 @@ const TeleopSubcomponent = (props) => {
122136
/**
123137
* Create the ROS Action Client to start the teleop controllers.
124138
*/
125-
let startCartesianControllerAction = useMemo(() => {
126-
return createROSActionClient(ros.current, START_CARTESIAN_CONTROLLER_ACTION_NAME, START_CARTESIAN_CONTROLLER_ACTION_TYPE)
127-
}, [])
128-
let startJointControllerAction = useMemo(() => {
129-
return createROSActionClient(ros.current, START_JOINT_CONTROLLER_ACTION_NAME, START_JOINT_CONTROLLER_ACTION_TYPE)
139+
let activateControllerActionGoal = useMemo(
140+
() =>
141+
createROSMessage({
142+
controller_to_activate: teleopMode === JOINT_MODE ? JOINT_CONTROLLER_NAME : CARTESIAN_CONTROLLER_NAME,
143+
re_tare: true
144+
}),
145+
[teleopMode]
146+
)
147+
148+
let activateControllerAction = useMemo(() => {
149+
return createROSActionClient(ros.current, ACTIVATE_CONTROLLER_ACTION_NAME, ACTIVATE_CONTROLLER_ACTION_TYPE)
130150
}, [])
131151

132152
/**
@@ -144,9 +164,9 @@ const TeleopSubcomponent = (props) => {
144164
*/
145165
useEffect(() => {
146166
console.log('Starting controller', refreshCount)
147-
let action = teleopMode === JOINT_MODE ? startJointControllerAction : startCartesianControllerAction
148-
callROSAction(action, createROSMessage({}), null, null)
149-
}, [refreshCount, startCartesianControllerAction, startJointControllerAction, teleopMode])
167+
let action = activateControllerAction
168+
callROSAction(action, activateControllerActionGoal, null, null)
169+
}, [refreshCount, activateControllerAction, activateControllerActionGoal])
150170

151171
/**
152172
* When the component is unmounted, stop servo.
@@ -155,11 +175,10 @@ const TeleopSubcomponent = (props) => {
155175
let unmountCallback = props.unmountCallback
156176
return () => {
157177
console.log('Unmounting teleop subcomponent.')
158-
destroyActionClient(startCartesianControllerAction)
159-
destroyActionClient(startJointControllerAction)
178+
destroyActionClient(activateControllerAction)
160179
unmountCallback.current()
161180
}
162-
}, [startCartesianControllerAction, startJointControllerAction, props.unmountCallback])
181+
}, [activateControllerAction, props.unmountCallback])
163182

164183
/**
165184
* Callback function to publish constant cartesian cartesian velocity commands.
@@ -534,6 +553,38 @@ const TeleopSubcomponent = (props) => {
534553
},
535554
[teleopMode, setTeleopMode, textFontSize, sizeSuffix]
536555
)
556+
557+
/**
558+
* Service and callback to increase the force threshold. Additionally, before
559+
* unmounting, the force threshold should be reset.
560+
*/
561+
const [forceThresholdIsIncreased, setForceThresholdIsIncreased] = useState(false)
562+
let changeForceThresholdService = useMemo(() => {
563+
let activeController = teleopMode === JOINT_MODE ? JOINT_CONTROLLER_NAME : CARTESIAN_CONTROLLER_NAME
564+
return createROSService(ros.current, activeController + '/set_parameters_atomically', SET_PARAMETERS_SERVICE_NAME)
565+
}, [ros, teleopMode])
566+
const setForceThreshold = useCallback(
567+
(threshold) => {
568+
let service = changeForceThresholdService
569+
let request = createROSServiceRequest({
570+
parameters: [{ name: FORCE_THRESHOLD_PARAM, value: getParameterFromValue(threshold, 3) }]
571+
})
572+
console.log('Calling setForceThreshold with request', request, 'for service', service.name)
573+
service.callService(request, (response) => {
574+
console.log('For setForceThreshold request', request, 'received response', response)
575+
setForceThresholdIsIncreased(threshold > DEFAULT_FORCE_THRESHOLD)
576+
})
577+
},
578+
[changeForceThresholdService, setForceThresholdIsIncreased]
579+
)
580+
useEffect(() => {
581+
return () => {
582+
if (props.allowIncreasingForceThreshold) {
583+
setForceThreshold(DEFAULT_FORCE_THRESHOLD)
584+
}
585+
}
586+
}, [props.allowIncreasingForceThreshold, setForceThreshold])
587+
537588
// Render the component
538589
return (
539590
<View
@@ -562,7 +613,7 @@ const TeleopSubcomponent = (props) => {
562613
</View>
563614
<View
564615
style={{
565-
flex: 9,
616+
flex: 14,
566617
justifyContent: 'center',
567618
alignItems: 'center',
568619
width: '100%',
@@ -572,7 +623,7 @@ const TeleopSubcomponent = (props) => {
572623
{/* Allow users to tune to speed of the current teleop mode */}
573624
<View
574625
style={{
575-
flex: 1,
626+
flex: props.allowIncreasingForceThreshold ? 1 : 2,
576627
flexDirection: 'row',
577628
justifyContent: 'center',
578629
alignItems: 'center',
@@ -628,10 +679,58 @@ const TeleopSubcomponent = (props) => {
628679
}}
629680
/>
630681
</View>
682+
{/* If the props specify, show a button to increase the force threshold. */}
683+
{props.allowIncreasingForceThreshold ? (
684+
<View
685+
style={{
686+
flex: 1,
687+
flexDirection: 'row',
688+
justifyContent: 'center',
689+
alignItems: 'center',
690+
width: '100%'
691+
}}
692+
>
693+
{forceThresholdIsIncreased ? (
694+
<Button
695+
variant='warning'
696+
className='mx-2 mb-2 btn-huge'
697+
size='lg'
698+
style={{
699+
fontSize: (textFontSize * 1.0).toString() + sizeSuffix,
700+
paddingTop: 0,
701+
paddingBottom: 0,
702+
margin: '0 !important',
703+
width: '100%'
704+
}}
705+
onClick={() => setForceThreshold(DEFAULT_FORCE_THRESHOLD)}
706+
>
707+
&#x26E8; Restore Force Threshold
708+
</Button>
709+
) : (
710+
<Button
711+
variant='danger'
712+
className='mx-2 mb-2 btn-huge'
713+
size='lg'
714+
style={{
715+
fontSize: (textFontSize * 1.0).toString() + sizeSuffix,
716+
paddingTop: 0,
717+
paddingBottom: 0,
718+
margin: '0 !important',
719+
width: '100%'
720+
}}
721+
onClick={() => setForceThreshold(INCREASED_FORCE_THRESHOLD)}
722+
>
723+
&#9888; Increase Force Threshold
724+
</Button>
725+
)}
726+
</View>
727+
) : (
728+
<></>
729+
)}
631730
{/* Render the controls for the mode */}
632731
<View
633732
style={{
634-
flex: 5,
733+
flex: 8,
635734
flexDirection: 'column',
636735
justifyContent: 'center',
637736
alignItems: 'center',
@@ -652,10 +751,13 @@ TeleopSubcomponent.propTypes = {
652751
// A reference to a function to be called if StopServo is succesfully run.
653752
unmountCallback: PropTypes.object,
654753
// A function to be called when one of the teleop buttons are released
655-
teleopButtonOnReleaseCallback: PropTypes.func
754+
teleopButtonOnReleaseCallback: PropTypes.func,
755+
// Whether to allow the user to increase the force threshold
756+
allowIncreasingForceThreshold: PropTypes.bool
656757
}
657758
TeleopSubcomponent.defaultProps = {
658759
unmountCallback: { current: () => {} },
659-
teleopButtonOnReleaseCallback: () => {}
760+
teleopButtonOnReleaseCallback: () => {},
761+
allowIncreasingForceThreshold: false
660762
}
661763
export default TeleopSubcomponent

feedingwebapp/src/ros/ros_helpers.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,12 @@ export function getParameterFromValue(value, typeOverride = null) {
226226
if (typeOverride === 1 || typeof value === 'boolean') {
227227
parameter.bool_value = value
228228
parameter.type = 1
229-
} else if (typeOverride === 2 || Number.isInteger(value)) {
230-
parameter.integer_value = value
231-
parameter.type = 2
232229
} else if (typeOverride === 3 || typeof value === 'number') {
233230
parameter.double_value = value
234231
parameter.type = 3
232+
} else if (typeOverride === 2 || Number.isInteger(value)) {
233+
parameter.integer_value = value
234+
parameter.type = 2
235235
} else if (typeOverride === 4 || typeof value === 'string') {
236236
parameter.string_value = value
237237
parameter.type = 4
@@ -241,12 +241,12 @@ export function getParameterFromValue(value, typeOverride = null) {
241241
} else if (typeOverride === 6 || (Array.isArray(value) && value.length > 0 && typeof value[0] === 'boolean')) {
242242
parameter.bool_array_value = value
243243
parameter.type = 6
244-
} else if (typeOverride === 7 || (Array.isArray(value) && value.length > 0 && Number.isInteger(value[0]))) {
245-
parameter.integer_array_value = value
246-
parameter.type = 7
247244
} else if (typeOverride === 8 || (Array.isArray(value) && value.length > 0 && typeof value[0] === 'number')) {
248245
parameter.double_array_value = value
249246
parameter.type = 8
247+
} else if (typeOverride === 7 || (Array.isArray(value) && value.length > 0 && Number.isInteger(value[0]))) {
248+
parameter.integer_array_value = value
249+
parameter.type = 7
250250
} else if (typeOverride === 9 || (Array.isArray(value) && value.length > 0 && typeof value[0] === 'string')) {
251251
parameter.string_array_value = value
252252
parameter.type = 9

0 commit comments

Comments
 (0)