1. Home
    1. Dashboard
    2. Search
  2. Forum
    1. Unresolved Threads
    2. Members
      1. Recent Activities
      2. Users Online
      3. Team Members
      4. Search Members
      5. Trophys
  3. Articles
  4. Blog
  5. Videos
  6. Jobs
  7. Shop
    1. Orders
  • Login or register
  • Search
This Thread
  • Everywhere
  • This Thread
  • This Forum
  • Articles
  • Pages
  • Forum
  • Blog Articles
  • Products
  • More Options
  1. Robotforum - Support and discussion community for industrial robots and cobots
  2. Forum
  3. Industrial Robot Support and Discussion Center
  4. KUKA Robot Forum
Your browser does not support videos RoboDK Software for simulation and programming
Visit our Mainsponsor
IRBCAM
Robotics Channel
Robotics Training
Advertise in robotics
Sponsored Ads

Setting a variable only after the motion primitive has finished without losing the advance pointer

  • Mathias314
  • June 10, 2025 at 3:06 PM
  • Thread is Resolved
  • Mathias314
    Posts
    12
    • June 10, 2025 at 3:06 PM
    • New
    • #1

    Hello everyone,

    I am using the KUKA ready2educate cell with the following setup:

    Controller: KRC4 compact - 8.3.36
    Robot: KR3R540 C4SR

    I want to write the command id of amotion primitive into a variable after the primitive ptp/lin/circ execution is finished. Does anyone know a way to implement this without losing the advance pointer?

    Code
    ...
     loop
          if get_command(current_command) then   
             CURRENT_COMMAND_ID = current_command.id
             switch current_command.type
                case 1
                   check_error(do_grip(current_command.grip_data))
                   check_error(do_move(current_command.step, current_command.move_data, current_command.id))
                   ;LAST_FINISHED_MOVE_ID = current_command.id
                case 2
                   check_error(do_move(current_command.step, current_command.move_data, current_command.id))
                   ;msgnotify("Motion primitive with command ID %1 done","Motion EKI",current_command.id)
                   ;LAST_FINISHED_MOVE_ID = current_command.id
                case 3
                   check_error(do_grip(current_command.grip_data))
             endswitch
          else
             CURRENT_COMMAND_ID = 0
          endif
       endloop 
       close_interface()
    end
    
    
    
    deffct int do_move(step :in, move_data :in, cmd_id :in)
       decl int step
       decl move_type move_data
       decl int cmd_id
       decl int error_code
       error_code = 0
       
       ...
       
       switch (move_data.mode)
          case 1
             set_joint_vel(move_data.velocity)
             set_joint_acc(move_data.acceleration)
             set_blending(move_data.blending)
             INTERRUPT ON 19   ; enable interrupt to stop movement
             ptp move_data.joint c_ptp C_DIS
             INTERRUPT OFF 19
             LAST_FINISHED_MOVE_ID = cmd_id  ; save id of last finished motion primitive
          case 2
             set_joint_vel(move_data.velocity)
             set_joint_acc(move_data.acceleration)
             set_blending(move_data.blending)
             INTERRUPT ON 19
             ptp move_data.cartesian c_ptp C_DIS
             INTERRUPT OFF 19
             LAST_FINISHED_MOVE_ID = cmd_id
          case 3
             set_cart_vel(move_data.velocity)
             set_cart_acc(move_data.acceleration)
             set_blending(move_data.blending)
             INTERRUPT ON 19
             lin move_data.cartesian C_DIS
             INTERRUPT OFF 19
             LAST_FINISHED_MOVE_ID = cmd_id
    
          case 6
             set_cart_vel(move_data.velocity)
             set_cart_acc(move_data.acceleration)
             set_blending(move_data.blending)
             INTERRUPT ON 19
             circ move_data.cartesian_aux, move_data.cartesian C_DIS
             INTERRUPT OFF 19
             LAST_FINISHED_MOVE_ID = cmd_id
       endswitch
       return error_code
    endfct
    Display More

    I would appreciate any hints or suggestions on this.

    Thanks in advance!

  • Online
    SkyeFire
    Reactions Received
    1,051
    Trophies
    12
    Posts
    9,424
    • June 10, 2025 at 4:00 PM
    • New
    • #2

    There are multiple places in that code where the ARP may get broken, depending on whether CURRENT_COMMAND_ID, LAST_MOVE_COMPLETED, etc are variables or Outputs.

    Generally the simplest way to set Outputs without breaking the ARP is to use TRIGGER commands.

  • Mathias314
    Posts
    12
    • June 10, 2025 at 4:53 PM
    • New
    • #3

    Thanks for the hint. CURRENT_COMMAND_ID and LAST_FINISHED_MOVE_ID are Variables that are send as feedback via eki.

    Do you have a code snipped or a source on how to use the TRIGGER commands to set LAST_FINISHED_MOVE_ID after the move is completed?

    Thanks in advance!

    Edited once, last by Mathias314 (June 10, 2025 at 5:41 PM).

  • Fubini
    Reactions Received
    278
    Trophies
    9
    Posts
    1,886
    • June 10, 2025 at 5:01 PM
    • New
    • #4

    Can easily be found by looking into system integrators manual or searching in this forum with keyword trigger.

  • Online
    SkyeFire
    Reactions Received
    1,051
    Trophies
    12
    Posts
    9,424
    • June 10, 2025 at 5:40 PM
    • New
    • #5
    Quote from Mathias314

    Thanks for the hint. CURRENT_COMMAND_ID, LAST_FINISHED_MOVE_ID and are Variables that are send as feedback via eki

    How are you doing the EKI operations? Those break the ARP as well, unless you're handling your EKI in Interrupts or the SPS.

    TRIGGERs with approximated motions have a complex set of options. Simplest TRIGGER is usually something like:

    Code
    TRIGGER WHEN DISTANCE=0 DELAY=100 DO $OUT[3]=TRUE 
    TRIGGER WHEN DISTANCE=0 DELAY=101 DO vtcom_setup(1,2) PRIO=-1
    PTP XP1 C_PTP

    Setting an output, or calling a subroutine. TRIGGERs are always "attached" to the next motion command, regardless of the logic between the TRIGGER and that motion. So it's possible to "stack" multiple TRIGGERS on one motion, up to a limit (7? 10?).

    DISTANCE=0 "attaches" the TRIGGER to the start of the motion. DISTANCE=1 attaches to the "end" of the motion, or (if the motion is Continuous), to the "closest approach" -- basically, where the approximated arc passes closest to the programmed point. This is where the path planner switches between the current motion and the next motion.

    DELAY=xx is a delay in milliseconds. It can also be negative, to fire the TRIGGER in advance of the physical location. Note: if the DELAY puts the TRIGGER more than 50% of the distance between two points, the TRIGGER fires at the 50% mark.

    PRIO=-1 is a way of letting the system choose a Priority level automatically. -1 is the best choice, usually.

    TRIGGERs are special types of INTERRUPT, and use the same resources, so the limit on the maximum number of "armed" INTERRUPTs or TRIGGERs is the sum of both. They also use the same Priority levels, which is another reason to use PRIO=-1 for TRIGGERs.

  • Mathias314
    Posts
    12
    • June 10, 2025 at 7:19 PM
    • New
    • #6

    Thank you very much for your help:)

    With this approach, however, another problem arises: the trigger function can only accept global or constant variables.

    I receive motion primitives via EKI (in an interrupt). I execute these in a switch-case statement. I want to send feedback via EKI (also in an interrupt) indicating which primitive (ID) has been completed. To do this, I need to read the ID of the primitive at runtime and then set it once the primitive has been processed.
    If I understand correctly, I cannot pass the variable in this way in the trigger function.

    This was my approche:

    Code
    deffct int do_move(step :in, move_data :in, cmd_id :in)
       decl int step
       decl move_type move_data
       decl int cmd_id
       decl int error_code
       error_code = 0
       
      ...
      
       switch (move_data.mode)
          case 1
             set_joint_vel(move_data.velocity)
             set_joint_acc(move_data.acceleration)
             set_blending(move_data.blending)
             TRIGGER WHEN DISTANCE=1 DELAY=100 DO set_cmd_id_done(cmd_id) PRIO=-1
             INTERRUPT ON 19   ; enable interrupt to stop movement
             ptp move_data.joint c_ptp C_DIS
             INTERRUPT OFF 19
             
           ...
           
       endswitch
       
       return error_code
    endfct
    Display More
    Code
    def set_cmd_id_done(cmd_id :in)
       decl int cmd_id
       msgnotify("Command with ID %1 done","Motion EKI",cmd_id)
       LAST_FINISHED_MOVE_ID = cmd_id
    end

    Is there a solution or workaround for this?

    Edited once, last by Mathias314 (June 10, 2025 at 7:24 PM).

  • Online
    SkyeFire
    Reactions Received
    1,051
    Trophies
    12
    Posts
    9,424
    • June 10, 2025 at 8:48 PM
    • New
    • #7
    Quote from Mathias314

    With this approach, however, another problem arises: the trigger function can only accept global or constant variables.

    Wait... I don't recall that being a TRIGGER limitation (then again, I'm old). As long as the variable is both DECL'd and Initialized before the TRIGGER fires, any type of variable should be okay. What kind of error did you get when you tried this?

    I take it CMD_ID was the variable that caused the issue? That looks like it should be fine, as it's a received argument, so there shouldn't be any time where the TRIGGER fires with that variable in an unitialized state.

    If the DECL location of the variable really is a problem for the TRIGGER, then it should be easy to fix this simply by adding a static variable (DECL it in the module's .DAT file with DECL INT myIntVar=0), and then copy CMD_ID to it at the top of the SWITCH.

    Oh... wait. Maybe it's the DELAY value. I can't see the entirety of DO_MOVE, but the way it's contructed suggests that the DELAY could push the actual firing of the TRIGGER out to a time when the program pointer has already returned from DO_MOVE. KRL has a single-line execution time down in the several-nanosecond range on modern KSS versions, for non-blocking commands. That could cause a bad interaction, with the memory space allocated for CMD_ID having already been deallocated. Copying CMD_ID to a static .DAT variable would probably still fix it, but you can test this theory by simply changing the DELAY value to 0 or even -100 and re-testing.

  • Mathias314
    Posts
    12
    • June 11, 2025 at 12:17 PM
    • New
    • #8

    I received the error: "Use of runtime data not permitted." ("Verwendung von Laufzeitdaten nicht zulässig")

    I tested the implementation with a delay of 0 and -100, and I still got the same error.

    Introducing an additional variable that is declared in the .dat file worked.

    Code
    deffct int do_move(step :in, move_data :in, cmd_id :in)
       decl int step
       decl move_type move_data
       decl int cmd_id
       decl int error_code
       error_code = 0
       
       temp_cmd_id = cmd_id
       
       
    ...
       
       switch (move_data.mode)
          case 1
             set_joint_vel(move_data.velocity)
             set_joint_acc(move_data.acceleration)
             set_blending(move_data.blending)
             TRIGGER WHEN DISTANCE=1 DELAY=0 DO set_cmd_id_done(temp_cmd_id) PRIO=-1 ; save id of last finished motion primitive
             INTERRUPT ON 19   ; enable interrupt to stop movement
             ptp move_data.joint c_ptp C_DIS
             INTERRUPT OFF 19
             
          ...
          
       endswitch
       
       return error_code
    endfct
    Display More

    Thanks for your help. Its great having people like you in the internet:)


    But I don’t quite understand why this approach works, and why the temp_cmd_id variable declared in the .dat file isn’t overwritten with future values, like I experienced with the previous issue?

  • Online
    SkyeFire
    Reactions Received
    1,051
    Trophies
    12
    Posts
    9,424
    • June 11, 2025 at 5:05 PM
    • New
    • #9
    Quote from Mathias314

    I received the error: "Use of runtime data not permitted." ("Verwendung von Laufzeitdaten nicht zulässig")

    Huh! I'll be dipped. I honestly can't recall ever running into that, but I'd have to deep-dive my archives to see if I ever had a similar TRIGGER setup.

    Quote from Mathias314

    But I don’t quite understand why this approach works, and why the temp_cmd_id variable declared in the .dat file isn’t overwritten with future values, like I experienced with the previous issue?

    That's a good question -- when I made that suggestion, I wasn't thinking about how do_move() is being called from a loop.

    Unfortunately, I don't have a good answer. If you're seeing continuous motion between points with this program, the ARP is obviously not being broken. But that seems like it should be having "future" values overwrite the .DAT variable.

    It may be that KSS handling of sequential calls is invisibly handling this for us, but that's just a guess.

  • Online
    panic mode
    Reactions Received
    1,280
    Trophies
    11
    Posts
    13,079
    • June 11, 2025 at 5:19 PM
    • New
    • #10

    you cannot pass runtime variables as parameters to ISR. also they must be initialized before advance run pointer reaches the interrupt or trigger instruction.

    usual workaround is to move declaration of such variables to a DAT file

    1) read pinned topic: READ FIRST...

    2) if you have an issue with robot, post question in the correct forum section... do NOT contact me directly

    3) read 1 and 2

Advertising from our partners

IRBCAM
Robotics Channel
Robotics Training
Advertise in robotics
Advertise in Robotics
Advertise in Robotics

Job Postings

  • Anyware Robotics is hiring!

    yzhou377 February 23, 2025 at 4:54 AM
  • How to see your Job Posting (search or recruit) here in Robot-Forum.com

    Werner Hampel November 18, 2021 at 3:44 PM
Your browser does not support videos RoboDK Software for simulation and programming

Tag Cloud

  • abb
  • Backup
  • calibration
  • Communication
  • CRX
  • DCS
  • dx100
  • dx200
  • error
  • Ethernet
  • Ethernet IP
  • external axis
  • Fanuc
  • help
  • hmi
  • I/O
  • irc5
  • IRVIsion
  • karel
  • kawasaki
  • KRC2
  • KRC4
  • KRC 4
  • KRL
  • KUKA
  • motoman
  • Offset
  • PLC
  • PROFINET
  • Program
  • Programming
  • RAPID
  • robodk
  • roboguide
  • robot
  • robotstudio
  • RSI
  • safety
  • Siemens
  • simulation
  • SPEED
  • staubli
  • tcp
  • TCP/IP
  • teach pendant
  • vision
  • Welding
  • workvisual
  • yaskawa
  • YRC1000

Thread Tag Cloud

  • abb
  • Backup
  • calibration
  • Communication
  • CRX
  • DCS
  • dx100
  • dx200
  • error
  • Ethernet
  • Ethernet IP
  • external axis
  • Fanuc
  • help
  • hmi
  • I/O
  • irc5
  • IRVIsion
  • karel
  • kawasaki
  • KRC2
  • KRC4
  • KRC 4
  • KRL
  • KUKA
  • motoman
  • Offset
  • PLC
  • PROFINET
  • Program
  • Programming
  • RAPID
  • robodk
  • roboguide
  • robot
  • robotstudio
  • RSI
  • safety
  • Siemens
  • simulation
  • SPEED
  • staubli
  • tcp
  • TCP/IP
  • teach pendant
  • vision
  • Welding
  • workvisual
  • yaskawa
  • YRC1000
  1. Privacy Policy
  2. Legal Notice
Powered by WoltLab Suite™
As a registered Member:
* You will see no Google advertising
* You can translate posts into your local language
* You can ask questions or help the community with your knowledge
* You can thank the authors for their help
* You can receive notifications of replies or new topics on request
* We do not sell your data - we promise

JOIN OUR GREAT ROBOTICS COMMUNITY.
Don’t have an account yet? Register yourself now and be a part of our community!
Register Yourself Lost Password
Robotforum - Support and discussion community for industrial robots and cobots in the WSC-Connect App on Google Play
Robotforum - Support and discussion community for industrial robots and cobots in the WSC-Connect App on the App Store
Download