@@ -78,6 +78,8 @@ def __init__(self, name: str, config: EEFTwistTaskConfig) -> None:
7878 self ._lock = threading .Lock ()
7979 self ._latest_twist : TwistStamped | None = None
8080 self ._last_update_time = 0.0
81+ self ._last_commanded_positions : NDArray [np .float64 ] | None = None
82+ self ._last_commanded_pose : pinocchio .SE3 | None = None
8183
8284 def claim (self ) -> ResourceClaim :
8385 return ResourceClaim (self ._joint_names , self ._config .priority , ControlMode .SERVO_POSITION )
@@ -92,10 +94,6 @@ def on_ee_twist_command(self, twist: TwistStamped, t_now: float) -> bool:
9294 logger .warning ("EEFTwistTask rejecting non-finite twist" , task = self ._name )
9395 return False
9496 with self ._lock :
95- if np .allclose (values , 0.0 ):
96- self ._clear_locked ()
97- self ._last_update_time = t_now
98- return True
9997 self ._latest_twist = twist
10098 self ._last_update_time = t_now
10199 return True
@@ -109,13 +107,25 @@ def compute(self, state: CoordinatorState) -> JointCommandOutput | None:
109107 self ._config .timeout > 0
110108 and state .t_now - self ._last_update_time > self ._config .timeout
111109 ):
112- self ._clear_locked ()
110+ self ._clear_locked (clear_target = True )
113111 return None
114112
115113 q_current = self ._get_current_joints (state )
116114 if q_current is None or not np .all (np .isfinite (q_current )):
117115 return None
118- target_pose = self ._ik .forward_kinematics (q_current )
116+ q_current = np .asarray (q_current , dtype = np .float64 )
117+ if np .allclose (twist_to_numpy (twist ), 0.0 ):
118+ if self ._last_commanded_positions is None :
119+ return None
120+ return JointCommandOutput (
121+ joint_names = self ._joint_names_list ,
122+ positions = self ._last_commanded_positions .tolist (),
123+ mode = ControlMode .SERVO_POSITION ,
124+ )
125+
126+ target_pose = self ._last_commanded_pose
127+ if target_pose is None :
128+ target_pose = self ._ik .forward_kinematics (q_current )
119129 dt = min (max (state .dt , 0.0 ), _MAX_DT )
120130 candidate = self ._integrate_twist (target_pose , twist , dt )
121131
@@ -139,9 +149,13 @@ def compute(self, state: CoordinatorState) -> JointCommandOutput | None:
139149 )
140150 return None
141151
152+ commanded_positions = np .asarray (q_solution , dtype = np .float64 ).reshape (- 1 )
153+ self ._last_commanded_positions = commanded_positions .copy ()
154+ self ._last_commanded_pose = self ._ik .forward_kinematics (commanded_positions )
155+
142156 return JointCommandOutput (
143157 joint_names = self ._joint_names_list ,
144- positions = q_solution . flatten () .tolist (),
158+ positions = commanded_positions .tolist (),
145159 mode = ControlMode .SERVO_POSITION ,
146160 )
147161
@@ -160,8 +174,11 @@ def _get_current_joints(self, state: CoordinatorState) -> NDArray[np.floating[An
160174 positions .append (pos )
161175 return np .array (positions , dtype = np .float64 )
162176
163- def _clear_locked (self ) -> None :
177+ def _clear_locked (self , * , clear_target : bool = False ) -> None :
164178 self ._latest_twist = None
179+ if clear_target :
180+ self ._last_commanded_positions = None
181+ self ._last_commanded_pose = None
165182
166183 def _integrate_twist (
167184 self , pose : pinocchio .SE3 , twist : TwistStamped , dt : float
0 commit comments