Decrease response time of "Command: Until" within "MoveL"

I need the robot to perform MoveL until a certain condition is met. The MoveL speed is slow, 7 mm/second.
Screenshot 2023-09-30 at 2.18.50 PM
I am finding that the response time from the moment the until condition is trigger, to the moment the robot actually stops the MoveL, is too slow, several hundreds milliseconds.

For example:

  1. Move until a Modbus TCP cyclic digital input goes high. On the installation node, I see an effective average frequency of ~32 Hz for this command (targeting 50 Hz). This is plenty good for my application. But the MoveL : Until node responds much slower than I expected.

  2. To remove Modbus TCP from the equation, I tried using a digital input as the MoveL : Until stop condition. I used an expression to check when a certain digital input goes high. The issue remains: it takes a variable amount of time, on average too high, for the robot to stop moving after I trigger the digital I/O.

How can I decrease the response time of the “Command: Until” within a MoveZ node?
Are there alternative program structures that are faster (an outer loop to check the condition with short MoveZ-distance nodes inside? Use URScript directly instead of program nodes?)

I need the robot to “immediately” stop when I trigger a certain condition via Modbus TCP or via Digital I/O. By “immediately” I mean a response time of ideally < 100ms, the lower the better. But many hundreds of ms is too much, in this application it means that the robot collides and goes in a protective stop.

Do I need to use the RTDE for this? Eventually I need to build this type of cycle in a URCap.

Hi…

if you create a program with a moveL with a until condition, I choose a digital in for convenience, and save the program and then inspect the actual script code being run, you get.

   global move_thread_flag_4=0
    thread move_thread_4():
      enter_critical
      move_thread_flag_4 = 1
      movel(Waypoint_1_p, a=1.2, v=0.25)
      move_thread_flag_4 = 2
      exit_critical
    end
    move_thread_flag_4 = 0
    move_thread_han_4 = run move_thread_4()
    while (True):
      if (get_standard_digital_in(0) == True):
        kill move_thread_han_4
        stopl(3.0)
        $ 5 "Until (io)"
        break
      end
      sleep(1.0E-10)
      if (move_thread_flag_4 > 1):
        join move_thread_han_4
        break
      end
      sync()
    end

I suspect its the stopl(3) call thats messing your program up, try increasing this to get higher stop accelerations.

so I suggest trying to write you own version of this code, to get the result you want.

removing the sleep command might also help, by decreasing the loop time.

Best Regards CG1

PS: some of this might also because of your safety settings, as this limits the amount of force and therefore the robots ability to break. Please also ensures that your COG and Payload are on point, because if they are not the robot might over or under compensate resulting in unpredictable behavior.

I would not advise raising the deceleration. Stopl(3) is a deceleration of 3000mm/s^2, which is already higher than what UR themselves advise (which is kinda funny actually).
If you do decide to edit the deceleration speed, it can simply be done within the Direction command. You don’t have to do it in the script file. :slight_smile:

I do not know of a solution to this issue, though. I suspect the MODBUS communication might be at fault. Maybe you can make a test by wiring the input directly to the robot I/O and check for the difference (if we’re talking a physical input).

Yeah efn is properly right about the deceleration…

it might be woth a try to use the angle based deceleration ‘stopl(aRot=255)’ instead, dont know if it would help but it might.

maybe try calling the stopl command before killing the thread, it might be that it takes a long time to kill the thread that results in the delay you see, but this might also simply result in an control error as the robot would be controled from 2 places at once.

maybe somthing like

def  servoMove(pose , vel, resolution):
       cnt = 1                                                        
       start_pose = get_actual_tcp_pose();
       dist = point_dist(start_pose, pose)                                          
       time_out = (dist/resolution)/vel                                                                  
       while  cnt <= resolution:                                                                 
          procentage = cnt/resolution												
          middle_pose = interpolate_pose(start_pose, pose,  procentage)
          servoj(get_inverse_kin(middle_pose), t=time_out, lookahead_time=0.2, gain=100)              
          cnt = cnt + 1                                                                     
          sync() 
          if (get_standard_digital_in(0) == True):
             break
          end
       end
       stopl(3.)                                                                     
    end

would work better if its the kill time thats the trouble…

@cg1 The acceleration value doesn’t seem to matter because my speed is already so slow (7 mm/s at 1 m/s^2 means 7milliseconds to stop).
The UR Script generated by my robot is actually a little different than what you posted: there is no thread join and there is no sleep (syncs instead). The move_thread_flag_5 flag is ignored outside the thread.
The thread is a run-once, not a loop (although I suspect the call to movel is blocking as it tries to move 1m).

  $ 2 "Robot Program"
  $ 3 "Set START= True "
  modbus_set_output_signal("START",   True  )
  $ 4 "MoveL"
  $ 5 "Direction: Tool Z+"
  global move_thread_flag_5=0
  thread move_thread_5():
    enter_critical
    move_thread_flag_5 = 1
    local towardsPos=calculate_point_to_move_towards(get_forward_kin(), [0.0,0.0,1.0], 1000.0)
    movel(towardsPos, a=0.01, v=0.007)
    move_thread_flag_5 = 2
    exit_critical
  end
  move_thread_flag_5 = 0
  move_thread_han_5 = run move_thread_5()
  while (True):
    if (modbus_get_signal_status("STOP") == 1):
      kill move_thread_han_5
      stopl(1.2)
      $ 6 "Until (expression)"
      break
    end
    sync()
  end

@efn

I suspect the MODBUS communication might be at fault. Maybe you can make a test by wiring the input directly to the robot I/O and check for the difference (if we’re talking a physical input).

I already tested with a digital I/O (physical I/O), same issue (before updating Polyscope see below)

@cg1

maybe try calling the stopl command before killing the thread, it might be that it takes a long time to kill the thread that results in the delay you see, but this might also simply result in an control error as the robot would be controled from 2 places at once.

This results in a control error as you said.

In any case, I was running Polyscope 5.12, I updated to 5.14.3 (latest as of 10/2/23) and it seems much more responsive now… perhaps it’s due to the script generated being structured better vs older versions like what @cg1 posted. I did not check what the generated script looked like on 5.12.

Good to hear an update fixed it. :slight_smile: Maybe it was an underlying bug somewhere.