Waiting for a signal from another component in a different component

Hi,

How do I wait for a signal (say “triggerSignal”) from a component (say “fromComponent”) in a different component using the condition statement. The question seems very straightforward but somehow I cannot get it to work.

def OnRun():
  app = getApplication()
  fromComponent = app.findComponent("fromComponent")
  trigger = fromComponent.findBehaviour("triggerSignal")
  condition(lambda: trigger.Value == False)
  ..<Remaining Code Here>

Is there a better way of doing this?

Thanks

1 Like

I had similar issues. I think its because you need to connect the signal in the properties to the pythons script. So signal in component(a) is connect to python script in component(a) but not to the python script in component(b).
I am using a robot so I found it far easier to connect the signals to the robot and control it from there.
If you dont have a robot then I guess you would need to create an output signal in component(a) and connect to an input signal on component(b). So output (a) trigger input (b) and the python script looks at the input (b).
I havent tried that as I just found it so much easier to do everything through the robot inputs and outputs in my case.

Thanks, that works :slight_smile:

The script won’t get notified if the signal value is changed. Try this:

  • Your triggerSignal has a Connections property, which is a list of behaviors that are notified when there is a change in the signal's value.
  • With that, a Python Script is a behavior, so add the script as a connection.
  • Yes, the GUI recognizes behaviors in the scope of component, but using API you can add other behaviors to the Connections list. See if that works.

It is not very intuitive that you need to connect the signal to the script in order to get the trigger events. This is there to improve the performance so that only the desired signals will generate events. I usually use this simple code to make sure that the signal is creating events.

def OnSignal(signal):
  pass
  print signal.Name, signal.Value

There’s also a slight difference with condition and triggerCondition.

Condition will test the condition when the python execution reaches that line. If the condition is false it will continue waiting next trigger and will test it again on every trigger.

triggerCondition won’t test the condition when the line is reached in the python execution, it will test it first time on the next trigger.

Let’s say if you have a sensor on a conveyor and the part has already arrived on the sensor before your python code reaches the condition line. If you are using triggerCondition it won’t pass the line, it will wait a next trigger which might not ever come because the sensor is already blocked. condition would pass it because it would do the ‘test’ when the line is reached and it would notice that, oh, there’s a part already, let’s move on.

#1
triggerCondition(lambda: mySensorsignal.Value)
#2
condition(lambda: mySensorsignal.Value)

 

I have the same problem as original poster. I dont understand how to add other behaviours to the Connections list in this case. Is there a method for it?

In order to listen a signal within another component you have to add the listening script to the connections of the signal behavior (in the component to be listened).

In the following example, “Transition” signal of “ShapeFeeder” is listened from the component containing the script.

The crucial part is:

monitoredSignal.Connections = monitoredSignal.Connections + [this]

 

Example:

from vcScript import *
app = getApplication()
comp = getComponent()

monitoredSignal = None

def OnStart():
  global monitoredSignal
  
  this = comp.findBehaviour("PythonScript")
  
  monitoredComp = app.findComponent("ShapeFeeder") 
  monitoredSignal = monitoredComp.findBehaviour("TransitionSignal")
  
  print monitoredSignal
  print monitoredSignal.Connections
  
  if this not in monitoredSignal.Connections:
    monitoredSignal.Connections = monitoredSignal.Connections + [this]
  
  print monitoredSignal.Connections

def OnRun():
  n = 0  
  while True:
    triggerCondition(lambda: getTrigger() == monitoredSignal and getTrigger().Value == True)
    n += 1
    print n, "New component created!"

After running the sim, you should see the additional PythonScript added to the Transition signal Connections which is invoked when ever the signal is triggered.

Hope this helps!

2 Likes

Thank you very much. The Connections property is what I was looking for.

This post saved my day!!! I am thankful!

Writing behaviors to other component’s signal.Connections is throwing error, but working ok.

Adding other behaviors to the Connections list using API is not prevented, and this approach works ok. However, sometimes this might be a bit unstable, for example components objects can be lost when layout has been changed or reopened, etc. That’s why you might see the warning printed in the Output window:

Warning: Assigning value of incorrect type for property ‘Connections’ in script ‘Human (Anna)::ResourceScript’. Property type is ‘List<Ref >’.

To avoid this problem, safer approach would be to register to signal.OnValueChange event.

Remember to use evaluateCondition() to re-evaluate the condition when waiting on that line.

Here is an example:

from vcScript import *
app = getApplication()
comp = getComponent()

monitoredSignal = None
triggerer = None

def OnStart():
  global monitoredSignal
  monitoredComp = app.findComponent("Shape Feeder") 
  monitoredSignal = monitoredComp.findBehaviour("TransitionSignal")
  monitoredSignal.OnValueChange = on_transition_signal


def on_transition_signal(signal):
  global triggerer
  triggerer = signal
  evaluateCondition()


def OnRun():
  global triggerer
  n = 0  
  while True:
    triggerCondition(lambda: triggerer == monitoredSignal and triggerer.Value == True)
    triggerer = None 
    n += 1
    print n, "New component created!"