Waiting for multiple signals

Hi experts!

I am rather new to python programming and I’m struggling with modelling this component:
I have modelled my own belt conveyor and now I want to connect different signals to it and each signal triggers a different movement eg., moving a belt to adjust to the size of the product.

I don’t know how to program the script so that it waits until a signal is triggered and then move the respective joint (with servo.moveJoint(0,…)). I’ve already tried using onSignal (signal) or conditiontrigger (in a while loop) and if…elif inside a while loop but with no success.

For what I’ve learned so far:
-onSignal doesn’t let me use commands for movement that need time like .movejoint.
-conditiontrigger looks like it needs to be executed in the order or if not it won’t enter on the next conditiontrigger
-the if… elif option gets the program hooked.

Does someone know how to program this?

Thanks in advance.

Hi,

Use a while loop,
inside it,
if you need a positive or negative trigger (rising/falling edge) =>
triggerCondition(lambda: getTrigger() == yourSignal and yourSignal.Value)
if you do not need a trigger, but simply wait until a value is something, and the value change could have already happend =>
condition(lambda: yourSignal.Value)

In OnSignal, you are correct, you are not allowed to spend simulation time, e.g. moving a servo, unless it is immediate motions.

Hey @line_out ,

Thanks for your answer. I tried the triggerCondition method inside a while loop as follows:

    #WHILE LOOP INSIDE DEF ONRUN()
    while sim.IsRunning == True:
    #MOVEMENT OF STOPS:
    triggerCondition ( lambda:getTrigger()==sensorSignal and sensorSignal.Value)
    servo.moveJoint(0,30)
    triggerCondition ( lambda:getTrigger()==sensorSignal and sensorSignal.Value==False)
    servo.moveJoint(0,0)

    #MOVEMENT OF BELTS IN X AXIS:
    triggerCondition ( lambda:getTrigger()==PresetSignal and PresetSignal.Value) 
    servo2.moveJoint(0,-180)
    triggerCondition ( lambda:getTrigger()==PresetSignal and PresetSignal.Value==False)
    servo2.moveJoint(0,0)

As I said, when I try this method looks like I must run the script in order. If I try to trigger the “PresetSignal” before “sensorSignal” it does nothing. Any ideas on how to solve it?

Thanks again,

Aha yes, you must have them in order, you can solve it in 2 ways,

either you do something like:
triggerCondition ( lambda:getTrigger() in [sensorSignal, PresetSignal ])
if sensorSignal.Value:
doSomething
elif not sensorSignal.Value:
do something else
elif PresetSignal .Value:
do something else
etc.

or you create a queue in OnRun:
def OnSignal(signal):
if signal == sensorSignal and sensorSignal .Value:
queue.append((0,30))
elif signal == sensorSignal and not sensorSignal .Value:
queue.append((0,0))

def OnRun():
global queue
queue = []
while True:
condition(lambda: queue)
target = queue.pop(0)
servo2.moveJoint(target[0], target[1])

1 Like

Thanks @line_out !!

I tried out the first one and it worked perfectly fine although I had to change one elif since it wasn’t working at first somehow. Here’s the code:

  while sim.IsRunning == True:
  triggerCondition ( lambda:getTrigger() in [sensorSignal,PresetSignal])
  #MOVEMENT OF STOPS:
  if PresetSignal.Value:
    servo2.moveJoint(0,-180)
  elif PresetSignal.Value==False:
    servo2.moveJoint(0,0)
  #MOVEMENT OF BELTS IN X AXIS
  if sensorSignal.Value:
    servo.moveJoint(0,30)
  elif sensorSignal.Value==False:
    servo.moveJoint(0,0)

Thanks, I really appreciate your help.

1 Like

By the way, when do you recommend to use more than one python script for a component?

For virtual commissioning purposes I have many inputs/outputs per component that may happen in parallel so I was wondering if it was wise to use more than one python script.

Thanks for your help.

1 Like

Hi, remember that each script, creates like a sandbox (uses system resources), so the more is not merrier. Only have more then one, if you have things that require parallel execution that is not solvable in 1 thread so to speak.

1 Like

Hey experts!

Continuing with the thread, I have the following problem. I have to wait for many signals that can trigger a servo movement at any time. So after troubleshooting for some time, I found a way of doing so in the same script with the same servo controller, although it is quite tedious since I have to write a if…elif…condition for every single signal, and I could have up to 80 signals in one component.

  1. Could you experts tell me if there is a more eficient way of programming the component? I tried with a for loop and entering the signals into a list but it didn’t work out.
  2. Have I done well by writing everything in a single script or maybe it’s better to separate some of the signals in more components and have more scripts?

Thanks in advance. The code would be like the following:


from vcScript import *

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

sensorSignal=comp.findBehaviour('BooleanSignal')
signal_1=comp.findBehaviour('Signal1')  
...................
...................
signal_12=comp.findBehaviour('Signal12')
...........
servo = comp.findBehaviour("Servo Controller")

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

def OnRun():
  global go
  while sim.IsRunning == True:
      triggerCondition ( lambda:go==True)
      
      if sensorSignal.Value:
        servo.setJointTarget(0,30)
      elif sensorSignal.Value==False:
        servo.setJointTarget(0,0)
      if signal_1.Value:
        servo.setJointTarget(1,30)
      elif signal_1.Value==False:
        servo.setJointTarget(1,0)
      if signal_2.Value:
        servo.setJointTarget(2,30)
      elif signal_2.Value==False:
        servo.setJointTarget(2,0)
     ..................................................................
      if signal_12.Value:
        servo.setJointTarget(12,30)
      elif signal_12.Value==False:
        servo.setJointTarget(12,0)
      ............................................................
 
      servo.move()
      go=False

You could create a dictonary object with signal name as key and target as list value, then you just do loop the signals. e.g. sevoDict[signal.Name] = [jointIndex, positiveValue, negativeValue] = [0,30,0]

signals = list of all your signals

for signal in signals:
joint_target_list = sevoDict[signal.Name]
target = joint_target_list[1] if signal.Value else joint_target_list[2]
servo.setJointTarget(joint_target_list[0], target)
servo.move()

isntead of the go part, you could just do triggerCondition ( lambda: getTrigger() in signals)

with reservations for spelling mistakes :slight_smile:

1 Like