From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

How could I implement something like "interfaces" with the Actor Framework?

Hi all,

I'm working on a medium-sized Actor Framework based design. One of the requirements is that it has robust hardware abstraction, since it will be running on systems that have a heterogeneous mix of hardware plugged into them. (Otherwise known as "all that old stuff we have lying around").

I'll describe my thinking up until this point, and then the problem I've run into.

Lets say I have an actor (I'll call it "Power Controller") which is in charge of ramping a power supply in a specific pattern. It has two child actors: 1) a power supply, and 2) a feedback current meter. It's job is to control the power supply with some sort of closed-loop feedback from the meter. Simple enough, I think.

I can implement the power supply and feedback meter as concrete child classes of abstract parent classes (e.g. the "ACME Power Supply 3000I" inherits from an "Abstract Power Supply", and overrides the "Set Output Amperes" method). The abstract parent classes have AF messages which call these dynamic methods and define the API. The power controller can then spin up a concrete power supply, based on a configuration file, and send the "Set Output Amperes" message to it, and all is working great.

BUT!

Then someone goes and buys a power supply which has a built-in current meter! I've now got one piece of hardware (one actor) which needs to do two jobs. If I was in C#, I'd say this might be a place for interfaces. I want to say "This actor implements the 'Power Supply' interface, and also the 'Feedback Meter' interface". Then I would like to be able to send either kind of message to it, and have it work.

I don't know how to do that in LabVIEW or the Actor Framework. This seems to break my concept of having abstract hardware classes, since there's obviously no multiple inheritence in LVOOP.

How could I architect this system, to make my dual-function hardware work?

0 Kudos
Message 1 of 14
(8,480 Views)

Interesting!!! Could you continue to have two actors, one for each job, even thought those jobs reside in one instrument?

Message 2 of 14
(5,132 Views)

Dear TobinJones,

I'm not yet fully familiar with the AF, but I will try to answer your question, since that might increase also my understanding of the AF.

If I understood the AF correctly, there is no need for a combined implementation of power controller and feedback meter.

Since the actor framework you describe allows already for a separate operation of such two devices, the more generalistic case is already implemented.

There is no problem to handle the built-in feedback meter like a seperate meter, that just happens to be in the same physical device.

Depending on your implementation of the communication to a comparable power controller you just have to make sure, that concurrent access to th device can be handled (but for example if you are using RS232, that should be handled pretty much automatically in LV).

Regarding the multiple inheritence: I think this is accordingly not the simplest way to think.

You want to create an abstaction for different devices of hardware (power controller, feedback meter, etc.), not represent every possible combination of hardware that you can buy. If you choose to abstract power controller and feedback meter separately, than there also shouldn't be anything trying to represent both at the same time, since that is not your scope.

(A great example for this is https://decibel.ni.com/content/docs/DOC-21441)

I'm not sure if my answer is correct. If not, please everyone, help educate TobinJones and me.

Best regards

Niels Göran

Message 3 of 14
(5,132 Views)

I have not done this sort of thing with AF, but have done it with LabVIEW classes, and the approach should work with actors. For any particular measurement, you would use three actors - a measurement manager, a driver, and a function. When you need a particular function, you query the measurment manager for availability. If the function is available, it will spin up the driver for the function, if it is not already spun up, then tell the driver to spin up the function and return a reference, which will then be returned to you. At that point, you use the function. The function uses the functionality of the driver. The driver has all the functionality of the specific instrument and does the state caching so that you don't try to do something like taking a voltage and current simultaneously with an instrument that cannot do that. Function locking and reservation can be done in either the driver or the measurement manager (I used the measurement manager).

I used "abstract" classes which returned errors if called directly to write top level code.  These were subclassed for particular implementations of functions and drivers. Functions only called driver code, never the native driver.

This is once over very lightly. Let me know if you need more information or particulars.

Message 4 of 14
(5,132 Views)

Ignore the AF at first. Figure out how you would do it with any class structure. Then apply it to AF.

LabVIEW does not have interfaces at this time (wish it did, and someday it will, but not today). There are several kludges to get around this limitation.

  • Creating a parent class that has all the methods and returns runtime errors for methods that are not overridden is one option (with obvious downsides).
  • Damien's "query for functionality" system mimics the "To More Specific" cast that you would do if LabVIEW actually had interfaces... as such, it is probably the most like interfaces, but obviously isn't as simple to write
  • You can combine the two previous concepts to make a system that is far simpler version of Damien's mechanism, which sufficies for most small and mid-size projects but is less flexible for large scale projects. As with #1, you add all the methods for all interfaces onto the ancestor class. Then you create an enum of your interfaces ("power supply", "current meter", etc). Add one dynamic dispatch VI at the root of your hierarchy that returns an array of enums... the returned array lists every interface that the actor implements. This way you guarantee that your runtime check occurs at only one point, not at all of your downstream functions. Still lacks the elegance of interfaces guaranteeing that the child class really has overridden all the methods that are part of all the interfaces it claims, but assuming you program correctly, it has better runtime behavior.

Those are the best ideas I know of for solving this at this time.

Message 5 of 14
(5,131 Views)

TobinJones wrote:

Then someone goes and buys a power supply which has a built-in current meter! I've now got one piece of hardware (one actor) which needs to do two jobs. If I was in C#, I'd say this might be a place for interfaces. I want to say "This actor implements the 'Power Supply' interface, and also the 'Feedback Meter' interface". Then I would like to be able to send either kind of message to it, and have it work.

As an aside to the "interface" conversation, this particular example doesn't need it.  Your new hardware is clearly a type of "Power Controler"; its actor would inherit from "Abstract Power Controller" and would not need "Power Supply" or "Feedback Meter" sub-actors.  If you stuck with the tree hierarchy, then all outside interaction with "Power Supply" or "Feedback Meter" was via "Power Controller", so you can drop-in replace it with the new hardware.

Message 6 of 14
(5,131 Views)

First off, thanks to everyone for your replies. They're all very helpful. I've got some thinking to do, but I'll reply to a few points here.

nbhollenback and ngblume

You guys seem to be advocating just having two actors working independently. I can see where you're coming from, but my problem here is one of responsibility: Which actor is then responsible for controlling concurrent hardware accesses, or configuring the instrument, or noticing that something is wrong and restarting the device? I think here I would need another layer below these two actors to take care of these sort of hardware details, but that kind of starts to get away from a nice tree structure for my actors?

drjdpowell

If I understand correctly, you're also saying that I already have everything I need. It's a good point. My sticking point here is just a mental convention: I think of my "power controller" actor as a business-logic controller, and not part of my "Hardware abstraction layer". That might be an artificial distinction, though. It just feels a bit weird subclassing a business logic controller with a hardware driver implementation? I think that quite possibly my problem is that I'm still thinking in a sort of MVC or tiered-architecture way rather than in a fully Actor way? Do you think so?

DFGray and AristosQueue

You guys are suggesting ways to implement "interface-like" systems.

DFGray, I think I understand your suggestion: It seems complex to me at this stage, but I think I might try implementing it and see how understandable it ends up being. I can see that this has advantages. AristosQueue, I do quite like your simple enum-as-interface idea. I think I will also try this out and see how it feels. In reality, there's a lot in AF that's not statically typed already, so I guess there's really nothing too crazy about implementing this in runtime logic... I'll give it a shot.

0 Kudos
Message 7 of 14
(5,131 Views)

Tobin,

The main advantage of language-supported Interfaces is you can invoke the Interface methods without knowing exactly what class your object is.  For example, you could put a Baby object and a CellPhone object in an array and invoke the Sleep method on both of them through the ISleepable Interface.  (Link to example on the LAVA code repository.)  I don't see you doing that here.

TobinJones wrote:

BUT!

Then someone goes and buys a power supply which has a built-in current meter! I've now got one piece of hardware (one actor) which needs to do two jobs. If I was in C#, I'd say this might be a place for interfaces. I want to say "This actor implements the 'Power Supply' interface, and also the 'Feedback Meter' interface". Then I would like to be able to send either kind of message to it, and have it work.

I think you are mixing ideas.  Are you trying to figure out how to get the new dual-function device working in your application, or are you trying to figure out how to create reusable actor libraries to control your instruments in other applications?

The former is pretty straightforward, and James (drjdpowell) described the easiest solution for that problem.  No Interfaces necessary.

The latter scenario is a classic case for Interfaces, but as you said... Labview doesn't provide them.  (Not to worry though.  IMO Interfaces are not well suited for reusable instrument code anyway.)  What I do is create an abstract class at the business layer with the high level calls the application needs to function correctly.  Then I implement a thin low level wrapper class around the device calls for each instrument.  Sometimes this will include inline error checking and other sundry details to make sure the device is working correctly.  That becomes part of my reusable code library.

Then I build a facade(-ish) class to glue the business layer to the hardware layer.  I create a device-specific subclass from the abstract class ("Abstract Power Supply" in your case), override the high level calls, and implement the required functionality in those high level calls using my reusable instrument class and aggregation/composition.

Capture.PNG

Here is one way to translate that idea into actors.  Notice the top three actors describe an inheritance relationship, but the bottom two actors do not inherit from the Medieval 1K actor.  They are completely separate actors that control their devices independently.  Of course, the Medieval actor doesn't have to delegate to other actors.  You could make the calls to the HP 9 and Agilent 7 devices directly in the Medieval actor.  Whether or not they should be separate actors depends on the instruments and business requirements.

Capture.PNG

Message 8 of 14
(5,131 Views)

Thanks, Daklu, for your input.

Your point about using implementing a HAL as a "facade" using composition of reusable drivers is a good one and I understand the advantage there.

I'm not sure your actor solution quite works for me, since it hard-codes the idea that a "power supply" must be bundled with a current meter into the actor design. Also, the "Whizbang 3K" is now not of the same type as the "HP IX", and so I can't use the Whizbang as a simple power supply. (for a business reason why i'd want to do this, it may be the case that we'll want to use a more precise current meter than the built-in one in the Whizbang. I should be able to plug an "Agilent VII" in, and use that instead of the built-in one).

Perhaps, though - this should be solved by simply implementing two interfaces to the Whizbang 3K, one as a concrete implementation of a "power supply" class and one as a concrete implementation of "power supply and meter combo" class. Then I could have a second "power supply and meter combo" implementation which just delegates to two separate devices. That covers all the bases, I believe.

As an aside, By my count, I've got 6 different solutions at this point! Wow.

0 Kudos
Message 9 of 14
(5,131 Views)

TobinJones wrote:

...since it hard-codes the idea that a "power supply" must be bundled with a current meter into the actor design.

Hmm... the top level actor should be labelled "power controller," not "power supply."

The functionality that must be bundled in the power controller is defined by the high level calls defined in your business layer.  If you create a high level call named "Set Output Current" and expect that to include closed-loop feedback functionality, then whatever actor implements that method needs to bundle a power supply and a current meter.

0 Kudos
Message 10 of 14
(5,131 Views)