@@ -28,6 +28,22 @@ namespace ZO.ROS.Controllers {
2828 [ RequireComponent ( typeof ( ZOROSJointStatesPublisher ) ) ]
2929 public class ZOArmController : ZOROSUnityGameObjectBase , ZOROSControllerInterface {
3030
31+
32+
33+ /// <summary>
34+ /// The error allowed between target joint positions and actual joint positions.
35+ /// </summary>
36+ public float _allowedJointPositionError = 0.01f ;
37+
38+
39+ /// <summary>
40+ /// The error allowed between target joint positions and actual joint positions.
41+ /// </summary>
42+ /// <value>float</value>
43+ public float AllowedJointPositionError {
44+ get => _allowedJointPositionError ;
45+ set => _allowedJointPositionError = value ;
46+ }
3147 /// <summary>
3248 /// Arm controller action server as used by MoveIt
3349 /// </summary>
@@ -177,6 +193,8 @@ protected override void ZOFixedUpdateHzSynchronized() {
177193
178194 if ( this . ControllerState == ControllerStateEnum . Running ) {
179195
196+
197+
180198 // see if we have any goals and update the controller state message
181199 if ( GoalStatus == ActionStatusEnum . ACTIVE ) {
182200
@@ -193,8 +211,18 @@ protected override void ZOFixedUpdateHzSynchronized() {
193211
194212 double [ ] interpolatedJointPositions = GetJointPositionsAtTimeSeconds ( Goal . goal . trajectory . points , _currentGoalTime ) ;
195213 if ( interpolatedJointPositions != null ) {
196-
197214
215+ // check if we are beyond the last time
216+ bool atTheEnd = false ;
217+ double lastTime = Goal . goal . trajectory . points . Last < JointTrajectoryPointMessage > ( ) . time_from_start . Seconds ;
218+ if ( _currentGoalTime >= lastTime ) {
219+ // Debug.Log("INFO: at end of joint trajectory.");
220+ atTheEnd = true ;
221+ }
222+
223+
224+ // Update the joint status and actual position
225+ bool isLessThenAllowedJointPositionError = true ;
198226 for ( int i = 0 ; i < Goal . goal . trajectory . joint_names . Length ; i ++ ) {
199227 _trajectoryControllerStateMessage . joint_names [ i ] = Goal . goal . trajectory . joint_names [ i ] ;
200228 ZOJointInterface joint = GetJointByName ( Goal . goal . trajectory . joint_names [ i ] ) ;
@@ -211,16 +239,37 @@ protected override void ZOFixedUpdateHzSynchronized() {
211239 ActionMessage . action_feedback . feedback . error . positions [ i ] = joint . Position - _trajectoryControllerStateMessage . desired . positions [ i ] ;
212240 // _trajectoryControllerStateMessage.error.velocities[i] = joint.Velocity - _trajectoryControllerStateMessage.desired.velocities[i];
213241
242+ // actually drive the joint position
214243 joint . Position = ( float ) _trajectoryControllerStateMessage . desired . positions [ i ] ;
215244
245+ // check if we are within error bounds
246+ if ( Mathf . Abs ( ( float ) _trajectoryControllerStateMessage . error . positions [ i ] ) > AllowedJointPositionError ) {
247+ isLessThenAllowedJointPositionError = false ;
248+ }
249+
216250 }
217251
252+ // if we are at the end and within error bounds then update the goal state
253+ if ( atTheEnd && isLessThenAllowedJointPositionError ) {
254+ Debug . Log ( "INFO: Finished arm control movement" ) ;
255+
256+ // at the end of the points for this goal so finish it
257+ ActionMessage . action_result . status = new GoalStatusMessage ( Goal . goal_id , ( byte ) ActionStatusEnum . SUCCEEDED , "finished arm control" ) ;
258+ ActionMessage . action_result . result = new FollowJointTrajectoryResult ( FollowJointTrajectoryResult . SUCCESSFUL ) ;
259+ ActionMessage . Update ( ) ;
260+ ActionServer . SetSucceeded ( ActionMessage . action_result , "Finished arm control movement" ) ;
261+ }
262+
263+
218264 } else {
219- // at the end of the points for this goal so finish it
220- ActionMessage . action_result . status = new GoalStatusMessage ( Goal . goal_id , ( byte ) ActionStatusEnum . SUCCEEDED , "finished arm control" ) ;
221- ActionMessage . action_result . result = new FollowJointTrajectoryResult ( FollowJointTrajectoryResult . SUCCESSFUL ) ;
222- ActionMessage . Update ( ) ;
223- ActionServer . SetSucceeded ( ActionMessage . action_result , "Finished arm control movement" ) ;
265+ // Debug.LogWarning("WARNING Should no be here!!!");
266+ // // FIXME: this is probably actually an error condition and not success.
267+ // // at the end of the points for this goal so finish it
268+ // ActionMessage.action_result.status = new GoalStatusMessage(Goal.goal_id, (byte)ActionStatusEnum.SUCCEEDED, "finished arm control");
269+ // ActionMessage.action_result.result = new FollowJointTrajectoryResult(FollowJointTrajectoryResult.SUCCESSFUL);
270+ // ActionMessage.Update();
271+ // ActionServer.SetSucceeded(ActionMessage.action_result, "Finished arm control movement");
272+
224273
225274 }
226275
@@ -304,25 +353,40 @@ protected override void ZOOnGUI() {
304353
305354 #region Utils
306355
356+
357+ /// <summary>
358+ /// Gets the interpolated joints position at time. Remember a joint position is the joint angle in radians.
359+ /// </summary>
360+ /// <param name="points">`JointTrajectoryPointMessage` points method.</param>
361+ /// <param name="timeSeconds">Time in seconds to get the joints position.</param>
362+ /// <returns>An array of joint positions (angles) in radians.</returns>
307363 protected double [ ] GetJointPositionsAtTimeSeconds ( JointTrajectoryPointMessage [ ] points , float timeSeconds ) {
308364
309365 if ( points . Length > 1 ) {
366+
367+ // check if we are beyond the last time
368+ double lastTime = points . Last < JointTrajectoryPointMessage > ( ) . time_from_start . Seconds ;
369+ if ( timeSeconds >= lastTime ) {
370+ // Debug.Log("INFO: at end of joint trajectory.");
371+ return points . Last < JointTrajectoryPointMessage > ( ) . positions ;
372+ }
373+
310374 for ( int i = 1 ; i < points . Length ; i ++ ) {
311375 // search for bracket
312376 double aTime = points [ i - 1 ] . time_from_start . Seconds ;
313- double bTime = points [ i ] . time_from_start . Seconds ;
314- if ( timeSeconds > aTime && timeSeconds <= bTime ) {
315-
377+ double bTime = points [ i ] . time_from_start . Seconds ;
378+ if ( timeSeconds >= aTime && timeSeconds < bTime ) {
379+
316380 double timeBetweenPoints = bTime - aTime ;
317381 if ( timeBetweenPoints > 0 ) {
318382 double timeFromA = timeSeconds - aTime ;
319383 double t = timeFromA / timeBetweenPoints ;
320384 int numPositions = points [ i ] . positions . Length ;
321385 double [ ] interpolatedJointPositions = new double [ numPositions ] ;
322386 for ( int p = 0 ; p < numPositions ; p ++ ) {
323- double aJointPosition = points [ i - 1 ] . positions [ p ] ;
387+ double aJointPosition = points [ i - 1 ] . positions [ p ] ;
324388 double bJointPosition = points [ i ] . positions [ p ] ;
325- interpolatedJointPositions [ p ] = Mathf . LerpAngle ( ( float ) aJointPosition * Mathf . Rad2Deg , ( float ) bJointPosition * Mathf . Deg2Rad , ( float ) t ) * Mathf . Deg2Rad ;
389+ interpolatedJointPositions [ p ] = Mathf . Lerp ( ( float ) aJointPosition , ( float ) bJointPosition , ( float ) t ) ;
326390 }
327391
328392 return interpolatedJointPositions ;
0 commit comments