Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Launch an actor from TestStand

Solved!
Go to solution

Hi,

 

I am trying to develop an ESS test sequence (for temp and vibe) in TestStand. I have developed two actors; one which is the top level root that acts as a GUI and launches a nested actor which is used to sample/monitor daqmx analog input data and pipe it back to the top level GUI actor through abstract messaging. It is working great when I launch the actors on their own from LabVIEW (a "Launch.vi"). However, I am trying to figure out how to spawn/launch the root actor from TestStand. What happens now is I call the "Launch.vi" from TestStand and it launches the actor OK, but then just keeps going and finishes the sequence while the actor continues to run. What I would like to do is launch it while TestStand waits for the actor to complete (probably VIA operator pressing stop button or similar) and pipe back the results from the actor to TestStand.

 

The reason I'd like to use TestStand for this is that I have already created a full ambient ATP sequence which is working great. I'd like to have an ESS sequence for that portion of testing so I can continue to leverage TestStand reporting and database logging which I am currently doing. I realize I don't necessarily HAVE to use actors for this, but I'd like to if this is something that is possible and considering it is working really well on it's own. This may just be something simple, but I'm fairly new to actors and have been looking for excuses to implement them in my development and deployment.

 

Thanks for any help.

0 Kudos
Message 1 of 11
(5,630 Views)
Solution
Accepted by topic author rdp08LM

I use TestStand for exactly the same thing, ATP and Qual of components in thermal, vibe, and other environments. When dealing with actors in a sequential application like TestStand, the best course of action is build interface classes for your actors that can be used like traditional railroad track vi's.

 

For example, you can have a start DAQ vi that launches the actor and stores it's enqueuer in the private data of the interface class. You then have a vi that is "set chamber temperature". That vi sends a message to the actor and then sits and waits for the actor to report that the temperature has be achieved. In TestStand, this will block the seq until that vi receives appropriate confirmation. Add more commands as required. Then your "stop daq.vi" would "Send Normal Stop" to the actor. 

 

The method for getting data into the synchronous interface class is typically done with a proxy actor. I'll try to find a good example on the forum of the proxy...I think justACS has posted several things on it. 

Message 2 of 11
(5,613 Views)

As wrkcrw00 alluded to, you write some bridge code for your actor to get it into TestStand space.

 

You are going to write a regular LabVIEW class that is your actor's API for TestStand.  This class has methods for every message you will send to the actor from TestStand, and methods for receiving data from your actor to pass to TestStand.

 

You will also write a proxy actor.  This actor is launched by the API (probably in a Create VI), and in turn launches your actor as a nested actor.  It also creates a set of shared references to queues or DVRs that it will share with the API.

 

When you want to send data to your actor from TestStand, invoke an API method.  That method will send a message to the proxy, which will send a message to your actor.

 

When you want to send data from your actor to TestStand, send the data to the proxy using a normal (abstract) message.  The proxy will put the data on the queue or in the DVR.  TestStand can then read the data from an API method that can access the queue or DVR.

 

There are a few steps here, but it means that you can keep your actor "pure", meaning you can call it from another actor, but still interact with TestStand, which is very non-actor-like.

 

If you just want to launch the actor and wait for it to complete, you can use this with any actor:  Test Launch For Nested Actor Without Caller.  It was intended to allow automated testing of actors, but it has general applications.  Set your actor's attributes and pass it to this VI.  The VI will wait until the actor stops, and return the actor object.  You can read any data out of the actor object using accessors.  Note that it won't work if the actor sends any messages to its caller other than Last Ack.

Message 3 of 11
(5,608 Views)

justACS and wrkcrw00,

 

Thanks for the answers. I think what is involved is starting to make some sense now. I will try and start building a simple API class. If I understand properly, the class's private data would hold the actor's enqueuer and it's methods would just be invoking the actor's desired methods via its messages (using the enqueuer)? And of course, TestStand would hold the reference to the class object?

 

The one thing I'm not clear on is the proxy actor. I haven't heard of this before. Is this just a dummy actor for the purpose of launching your own actors? Is this just to expose "your actor's" enqueuer up a level? If so, does this mean that my current root actor, the GUI actor, become nested?

 

I'm curious about the Test Launch For Nested Actor Without Caller. I will look at this too. I'm wondering if this would make more sense for me where my actor application is fairly simple. I would extract my final data from a last ack override?

 

To clarify, my root actor is a simply GUI that receives abstract message data from a daqmx monitor actor. It has a helper loop that compares the data against a mask and event that pushes it to the front panel so the operators can see current status of critical points during testing. If any of the data points fail the mask, I would just want to push a fail boolean and the name of the analog line that failed up to TestStand, for example.

 

My nested actor is a daqmx monitor. It simply sends itself time delayed messages to acquire data and sends that data in an abstract message to the root actor for display and analysis. 

 

Based on this, is method one you proposed more than I need? Is method two more appropriate? You mentioned keeping the actor "pure". Is this more desirable? I have no problem doing more work for method one if it makes sense or is the most robust in the long run. This is really just a small subset of the testing compared to the normal ATP which has thousands of steps that TestStand is going through. In this subset though, TestStand would essentially be launching a glorified monitoring loop and waiting until it is sent the results (how I envision it).

 

Thanks again for your comments.

0 Kudos
Message 4 of 11
(5,596 Views)

Keeping things "pure" means not cluttering your main actor with things that it may not always use. The proxy actor is what holds the queues or DVR's or notifiers or whatever type of data transfer mechanism that you want to use to send data back to the api class. You don't need to hold those queues or DVR references in the main actor if for instance you use that main actor in an entirely actor based system (because you would just use messages). By building a proxy actor, you can receive in the proxy actor the same messages or abstract messages you use in the main application to share data and have the proxy be the process that dumps that data into queue or DVR. 

 

If you only ever use this main actor in one specific place, you don't really need a proxy. But actors make for great reuse - and designing them as such from the start is good practice. Having the proxy launch the "main" application means the proxy doesn't always have to be launched if it's an pure actor system.

0 Kudos
Message 5 of 11
(5,592 Views)

OK. The concept of keeping things "pure" makes sense now. I would like to potentially make this actor re-usable in the future either as a pure actor system or through TestStand so I have started to implement a proxy and an api class. So far I have created a "create/launch" method in the API class which will launch the proxy which in turn launches my main actors as nested. I have a few further questions though. Apologies if they are trivial:

 

1. In my simple scenario, I want to call the launch api method from TestStand (using the method I've created) and then I'd like to implement a "wait for test to complete" type of method call that is blocking in TestStand. I'm struggling to visualize how I'd implement this type of operation. My main actor that is launched by the proxy will pop up as a GUI for the operator who will manually start a monitor loop (with start button) at temperature and manually stop it when the temp cycle is done. When done, I want to pass the result back to TestStand (which is waiting at this point). Any advice or existing examples that would help me visualize how to do this? Or maybe there is a better approach.

 

2. As I've started to build my proxy, I create a DVR reference with the result datatype I'd like to send to the API class within "Pre Launch Init". I'm guessing I should be storing this DVR in the private data of the proxy actor?

 

3. How do I share this DVR with the API? TestStand and the API are essentially blocked during the test. I want to pass the result back to the proxy and up to TestStand when the operator hits "stop" on my main actor interface. Is the API just waiting synchronously for a message that is passed back from the proxy containing the DVR ref?

 

 

0 Kudos
Message 6 of 11
(5,533 Views)

I answer a little out of order to help clarify.

 

2) & 3) Create the new DVR in the API, then add it to the private data of the proxy then launch the proxy. The proxy then launches the main actor. Thus both API and proxy have the DVR ref. In these types of scenarios, I typically use a queue instead of a DVR, and I'll explain why with #1.

 

1) In TestStand, you've called "create" method and now your actors have launched and are running. Let's say you next run an API method in TestStand called "run test". You want that to be blocking. This sends a message to the proxy which tells it to send the run test message to the main actor. The logic behind when the test is actually complete resides in your main actor. The proxy actor sits in waiting and will eventually receive a message that denotes "test complete" by the main actor (an abstract message of the main actor that proxy overrides). Proxy then flips the flag in the DVR to true.

 

Meanwhile, the API method, after it sends the run test message, sits in a loop and waits for the DVR flag to be true. This will be blocking in TestStand. Once true (or after a timeout or cancel notification), the vi completes and TestStand is free to move to the next step. The reason I typically use a queue in this scenario is so that I don't have to poll the DVR to see if the flag has flipped, I just wait for the first element enqueued. 

0 Kudos
Message 7 of 11
(5,497 Views)

Makes much more sense, thanks for the clarification. I think I am close now. I have a sequence that behaves like I am expecting with a few issues to iron out.

 

I decided to replace my DVR with a queue per your advice. I agree that just waiting on a dequeue makes more sense than polling the DVR. However, during debugging of my sequence, I ran into a scenario where I locked up TestStand and the actors because of the dequeue having an infinite timeout and aborting TestStand. Few more questions:

 

1. It seems to me there still needs to be a polling of some sort in the blocking method of the API: for example, a timeout on the dequeue with a TestStand execution monitor check. Is this similar to what you've done in your approach with a queue in the API that is blocking? Is there perhaps a better way?

 

2. My actor front panel (the nested actor called by the proxy) isn't showing its front panel when I launch it via TestStand calling the API launch proxy method --> Proxy --> my actor. It shows up as a standalone actor. I have the Window Appearance properties set to show front panel when called but this doesn't seem to work with it being called from TestStand. Any ideas? 

 

Thanks again for the help.

0 Kudos
Message 8 of 11
(5,487 Views)

Yeah, as with all things in LabVIEW, there are a 100 ways to solve any problem. As you mention, a simple timeout on the dequeue works. From my main actor front panel, I can stop the test and that sends a message to the proxy which uses a notifier to tell the API that the test has been canceled (as with the queue, if you want to do this, obtain the notifier in the API and hand off the ref to the proxy). I also have manual controls on the main actor UI that allow me to "fake out" the test result thus clearing the block from TestStand. I use this mostly for debugging and hide it in deployment...but I think that's what you're interested in. You can try either of these methods. 

 

When showing an actor front panel in deployment, I use an invoke node with VI server to show the front panel. I do this from TestStand now. Outside of TestStand, I've used the VI properties: appearance properties set to show front panel with actors in the past but I can't say I've ever tried it from TestStand. Are you running the LabVIEW runtime or development adapter in TestStand?

0 Kudos
Message 9 of 11
(5,482 Views)

I am using the LabVIEW development adapter in TestStand at the moment. I will need to be building this application to run using the runtime adapter very soon, within the next week or so. 

 

Good news though, I have it correctly working from TestStand! I will be cleaning up and adding some things over the next few days, but I finally have something I can use and build upon.

 

I ended up adding a 1 second timeout to the dequeue function and check the TestStand termination monitor status in between timeouts. If a termination occurs, I send a normal stop to the proxy, which stops all nested actors automatically, which is convenient. If a timeout doesn't occur, we have of course received the test results on the queue, so those are passed to TestStand and the proxy is stopped (and thus also again the nested actors). 

 

I was finally able to get my actor front panel modal to TestStand. To do this, I used an invoke node as you mentioned (instead of the window appearance properties) and set the FP.Open.Activate method to true with FP.Open.State to maximized. I also set the FP.IsFrontmost method to true as well. Not entirely sure this is needed, but I am invoking it for good measure. Setting these was not enough though to get the actor window modal to TestStand, however. To solve this, I ended up setting the "Show VI Front Panel is On" button in TestStand on the blocking step that invokes the API method to "Wait for Test to Complete". This ends up showing both the API method front panel and my actor front panel. Since I only want the actor FP open, I invoke an FP.Close immediately in the API method and this leaves only my actor FP open, modal, and maximized.

 

I appreciate all the help!

0 Kudos
Message 10 of 11
(5,478 Views)