RobotStudio event

Event Handler Problem VSTA

Options
Hi,
I'm running a simple C# program for modifying objects within RobotStudio 5.12 I and want to call a method regularly within VSTA using the System.Timers.Timer Class. I have setup the a private timer, set the interval, enabled the timer and set it to call and ElapsedEventHandler every time the ElapsedEventArg occurs (currently set to 1 second intervals). I can call methods within the VSTA Macro public partial class, and can run some methods within the ElapsedEventHandler, but when I want to do something such as setting a station signal from within the ElapsedEventHandler, nothing happens. What I am doing wrong here? If I set the station signals from another method or macro, it works fine.

///// SAMPLE CODE /////

//Create the timer 
private Timer myTimer;

//Setup Timer and ElapsedEventHandler and output enabled status to Output Window.
public void Macro_StartTimer()
{
    myTimer = new Timer();
    myTimer.Interval = 1000;
    myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
    myTimer.Enabled = true;

    Logger.AddMessage(new LogMessage("myTimer Enabled: " + myTimer.Enabled.ToString()));
}

// Send a message to Output Window everytime timer elapses.
// Change signal of digital station signal "Digital1"
void myTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    Logger.AddMessage(new LogMessage("myTimer elapsed at " + e.SignalTime.TimeOfDay.ToString()));

    Station station = Project.ActiveProject as Station;
    if (station.VirtualSignals["Digital1"].Equals(0))
    {
        station.VirtualSignals["Digital1"] = 1;
    }
    else
    {
        if (station.VirtualSignals["Digital1"].Equals(1))
        {
            station.VirtualSignals["Digital1"] = 0;
        }
    }                        

    throw new Exception("The method or operation is not implemented.");
}

// Stop the timer
public void Macro_StopTimer()
{
    myTimer.Enabled = false;
    Logger.AddMessage(new LogMessage("myTimer Enabled: " + myTimer.Enabled.ToString()));
}

///// END SAMPLE CODE /////

Thanks,
Matt.

Comments

  • Here is the output from when running the above for a few seconds. Note that the station signal "Digital1" does not change at all, even though the identical code within another Macro will change the station signals.


    myTimer Enabled: True                                    18/02/2010 5:12:26 PM General
    myTimer elapsed at 17:12:27.9531250           18/02/2010 5:12:27 PM General
    myTimer elapsed at 17:12:28.9531250           18/02/2010 5:12:28 PM General
    myTimer elapsed at 17:12:29.9531250           18/02/2010 5:12:29 PM General
    myTimer elapsed at 17:12:30.9531250           18/02/2010 5:12:30 PM General
    myTimer Enabled: False                         18/02/2010 5:12:31 PM General



  • carlosmtz2000
    Options

    Hi ... are you running the above code?

    There is an line with an exception. Could you remove and try without it?

     

     
    Carlos Martinez
    ABB
  • Hi Carlos,
    the code is from within a Robotstudio VSTA Sample Add-In. It is missing the assembly references and class code.

    I have attached the VSTA Add-In project files. Basically you can use this with any station as long as you have a digital station signal "Digital1", as this is what I am trying to modify.

    webwiz/2995/RobotStudioSample3.zip

    This project uses the System.Timers Timer. I have also tried using the System.Windows.Forms Timer. This enables modification of the "Digital1" virtual signal, but it encounters a windows jit- error (Just-In-Time Debugging) which halts the RobotStudio simulation.

    I am not really too sure where to go from here.

    Thanks,
    Matt.
  • carlosmtz2000
    Options
    Could you try this code instead. Let's see the result in the ouput window ...
     


    void myTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
    try
    {
    Logger.AddMessage(new LogMessage("myTimer elapsed at " + e.SignalTime.TimeOfDay.ToString()));
    Station station = Project.ActiveProject as Station;
    if (station == null)
    {
    Logger.AddMessage(new LogMessage("No Active Project"));
    }
    else
    {
    if (station.VirtualSignals["Digital1"].Equals(0))
    {
    station.VirtualSignals[
    "Digital1"] = 1;
    }
    else
    {
    if (station.VirtualSignals["Digital1"].Equals(1))
    {
    station.VirtualSignals[
    "Digital1"] = 0;
    }
    }
    }
    }
    catch (Exception e1)
    {
    Logger.AddMessage(new LogMessage(string.Format("Exception: {0}", e1.ToString())));
    }
    //throw new Exception("The method or operation is not implemented.");
    }
    Carlos Martinez
    ABB
  • Hi Carlos,
    same as before. Event handler is called when the Timer elapses, and no change to "Digital1". Here is the Exception e1 that was thrown:


    Exception: Microsoft.VisualStudio.Tools.Applications.Contract.AddInException: System.Reflection.TargetInvocationException, mscorlib
    System.ArgumentNullException, mscorlib

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentNullException: Value cannot be null.
    Parameter name: spSimRoot
       at ABB.Robotics.RobotStudio.Stations.VirtualSignalCollection.get_Item(String name)
       --- End of inner exception stack trace ---
       at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
       at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
       at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
       at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
       at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
       at Microsoft.VisualStudio.Tools.Applications.RemotePropertyInfoAdapter.System.AddIn.Contract.Automation.IRemotePropertyInfoContract.GetValue(IRemoteObjectContract target, BindingFlags bindingFlags, IRemoteArgumentArrayContract index, Int32 lcid)

    Server stack trace: 
       at Microsoft.VisualStudio.Tools.Applications.RemotePropertyInfoAdapter.System.AddIn.Contract.Automation.IRemotePropertyInfoContract.GetValue(IRemoteObjectContract target, BindingFlags bindingFlags, IRemoteArgumentArrayContract index, Int32 lcid)
       at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
       at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
       at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)

    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at System.AddIn.Contract.Automation.IRemotePropertyInfoContract.GetValue(IRemoteObjectContract obj, BindingFlags bindingFlags, IRemoteArgumentArrayContract index, Int32 localeId)
       at Microsoft.VisualStudio.Tools.Applications.ExceptionFilterHelper.GetValue(IExceptionManagerContract mgr, IExceptionNotificationObjectContract exceptionNotificationObjectContract, IRemotePropertyInfoContract propertyInfoContract, IRemoteObjectContract remoteObjectContract, BindingFlags bindingAttr, IRemoteArgumentArrayContract parameters, Int32 lcid)
       at Microsoft.VisualStudio.Tools.Applications.RemotePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
       at System.Reflection.PropertyInfo.GetValue(Object obj, Object[] index)
       at ABB.Robotics.RobotStudio.Stations.VirtualSignalCollection.get_Item(String name)
       at RobotStudioSample1.ThisApplication.myTimer_Elapsed(Object sender, ElapsedEventArgs e) 19/02/2010 2:48:20 AM General

  • Hi Carlos,
    I modified your code above to use a System.Windows.Forms.Timer(). Using the try, catch statements has eliminated the Just-In-Time debugging error that was previously encountered. I shall try to avoid amateur mistakes like this in future. 

    Thanks alot,
    Matt.
  • carlosmtz2000
    Options

    It seems that the signal could not be found.  Can you debug the application and check that the VirtualSignals collection has this signal?

    Could you share a Pack&Go file?
    Carlos Martinez
    ABB
  • Hi Carlos,
    here is the Pack & Go File. I have also included zip file of the Macro Add-Ins in case if it is not included.



    I have added in a little bit of code to debug the station signals present, by showing which ones are present and seeing if I can toggle their values from a separate macro Macro_CheckSignals(). I have included both methods for the timers, using the System.Timers and System.Windows.Forms.Timers classes respectively. This is interesting to see that the System.Timers does not work for some reason.

    Thanks,
    Matt.

  • carlosmtz2000
    Options
    Hi again,
     

    I opoen the RS station and link the last version of c# code. I only modified method StopTime2 since it was refefering to myTimer instead of myTimer2.

     

    Both methods (1 & 2) changes the signal for me.

     

    Could you give a try with my station?  Not sure where the difference could be.

     


    Carlos Martinez
    ABB
  • Hi Carlos,
    sorry about the mistake in the code. I previously had just copied, pasted and commented out the original methods using System.Timers and modified the copied version to use System.Windows.Forms.Timers. I then proceeded to clean up the code so that you could see the difference between each, but must've missed that one reference. 

    Anywho, on my computer (relatively new Dell M4400 running XP Pro SP3), System.Timers does not work for outputting anything useful to the station, whereas System.Windows.Forms.timers does. I had a look around the MSDN forums and it was suggested on other threads that there can be some threading problems with System.Timers.Timer.

    For now, I have implemented what I need using the System.Windows.Forms.Timer and it works as advertised.

    I have a station with two robots and four conveyor mechanisms (not IRC5Conveyors) and need to add parts/convey/transfer with robot1/convey/palletize with robot2. I have been using the timer to check conveyor transfer positions to detach parts from Conveyor1 and attach to Conveyor2 if required. I have found that there has been little to no gain in the simulation from calling these methods using a C# project based on the timer (note: independent of process timer - does not need synchronization) vs. calling the methods from rapid using a macro and timed interrupt. It is quite jerky and slow as I have to monitor transfer positions regularly even though I am only using 25% CPU. I have modified the RS Timeslice simulation speed and timestep and still have a jerky simulation.

    Any ideas on what is possible?

    Thanks alot for your time, I really appreciate it.
    Regards,
    Matt.
  • Hi Matt,

    You are correct about the (potential) threading issue. The callback from System.Timers.Timer is executed on a worker thread, and the RS API is (mostly) not thread safe; all calls should be made from the main GUI thread.

    In the case of VSTA there is also a whole lot of marshaling going on between your code and the API, I'm not sure how that is affected by threading issues.

    Unless you need macro support, I wouldn't recommend VSTA for add-in development. A standard add-in has superior performance and supports the entire RS API.

    regards,
    Johannes

    Johannes Weiman
    Software Engineer
    ABB Robotics
  • carlosmtz2000
    Options

    Have you tried to use events manager?

    Nto tried before, but for simulation purposes, what about having an virtual IO from the IRC5 which triggers this?
    Carlos Martinez
    ABB