Program signals triggering parallel movement

Hey experts,

I am trying to connect the VC sim with PLC for virtual commissioning so I have to programm in VC some movements triggered by the PLC. The problem is that these signals could trigger at any time so they should be able of moving whenever they are triggered. There wouldn’t be any problem if I could do a script per movement but since this consumes computer resources and I’m already using physics (which consumes a lot), I’m trying other ways.

Therefore, I am struggling with programming a script in which I can trigger signals in parallel. For what I’ve been trying, this is the closest I have gotten, but since I use suspendRun() it stops and then accelerates to continue. The movements should be triggered by boolean signals and in each state(True or False), the link should move to the target position.

I’d really appreciate some tips on how to program this. Thanks a lot.

from vcScript import * 

app = getApplication() 
sim = app.Simulation 
comp = getComponent() 

sensorSignal=comp.findBehaviour('BooleanSignal')
signal_1=comp.findBehaviour('Q_A_1A')  
signal_2=comp.findBehaviour('Q_A_1B')
`...............................`
    signal_12=comp.findBehaviour('Q_D_1A')
servo = comp.findBehaviour("Servo Controller")
list=[sensorSignal,signal_1,.............,signal_12]

def OnSignal(signal):
  suspendRun()
  global go
  go=True
  resumeRun()

def OnRun():
  global go
  while sim.IsRunning == True:
      triggerCondition ( lambda:go==True)
      for i in range(0,len(list)):
        if list[i].Value:
          servo.setJointTarget(i,30)
        elif list[i].Value==False:
          servo.setJointTarget(i,0)
      servo.move()

The servo controller behavior doesn’t seem to provide asynchronous motion API so this approach of using a single script to drive more than one controller at a time is a dead end.

You could try using a Process Modeling process per servo instead. Still you won’t be able to interrupt an ongoing motion.

The process would look like this:
image

These PM processes are relatively light weight. You can have at least hundreds of them.
And yes, you will need to have a Process Executor behavior per servo as well, since each only executes a single process at a time.

Hey @TSy,

Thanks for answering. The approach I tried is with ONE single controller (“Servo Controller”) connected to many links, instead of different servo controllers. With more than one, the links move one after another instead of all of them at a time. With my approach, whenever there’s a trigger, I check every signal connected if it’s true or False and I consequently set a target position to each of the links connected to the controller. At the end of the cycle I send the movement command (servo.move()). That works fine, the links I trigger move all at once. The problem is with motion interruptions, same as your approach if I’m not mistaken. To deal with it, I checked the emergency stop thread (Emergency Stop - #20 by hero) and tried to continue the approach they commented, but I reached a dead end.

You sure there isn’t any way to interrupt that movement? Many of my links are moving with a signal and when their encoder reaches a value, another signal should stop the movement (interrupt motion). Therefore, I have to try to find a way to simulate that.

Thank you once again.

Okey, with the following code, I managed to interrupt the motion with suspendRun()/resumeRun() and execute another motion immediately. The only problem is that because the suspendRun() it stops instantly and then starts accelerating again from 0 instead of continuing without any stop, which would be the real thing. Any ideas?
Thank you in advance. The code is the following:

from vcScript import * 
app = getApplication()
sim = app.Simulation 
comp = getComponent()


sensorSignal=comp.findBehaviour('BooleanSignal')
signal_1=comp.findBehaviour('Q_A_1A')  
signal_2=comp.findBehaviour('Q_A_1B')
   ....................
signal_12=comp.findBehaviour('Q_D_1A')

servo = comp.findBehaviour("Servo Controller")

list=[sensorSignal,signal_1,........,signal_12]

def OnSignal(signal):
  suspendRun()
  global go
  for i in range(0,len(lista)):
    if lista[i].Value:
      servo.setJointTarget(i,90)
    elif lista[i].Value==False:
      servo.setJointTarget(i,0)
  go=True
  resumeRun()

def OnRun():
  global go
  go=False
  while sim.IsRunning == True:
      goes.Value=go
      condition ( lambda:go==True)
      go= False
      servo.move()

Not being able to interrupt a motion is a fundamental limitation of the servo and robot controller behaviors, which is better to just accept in my opinion. All existing “solutions” to this are really just hacks which may happen to work, but were never intended to.

If you want interruptable motion, you’ll need to code your own motion interpolation which just sets the joint values directly at some interval without using any servo controller behavior.

Hey @TSy,

I see…What you say makes sense. However, I’m afraid I don’t know how to code motion interpolation and this approach arises some questions. Is it more or less easy to code the interpolation? Does it drain the performance more than a servo controller? Do you have an example of interpolation or where to look to find further information on the matter?

I appreciate your time,