Jump to content

Universal FGV


Recommended Posts

Hi everyone,

I had this (possibly hairbrained and madcap :D) idea a few weeks back - and have been trying to figure out a solution to it since. I've been playing around with LV OOP a lot recently and thought it would be really cool if I never had to make an FGV again. I'm not sure if someone has done this in the past but I thought I would give it a go.

My thought was that I could create a heirachy of LV classes for different data types and then when I need a new FGV, just create a sub-class off one of the data type classes to build a new FGV.

I've now got this working for standard data types (string, boolean and numeric - I could easily build classes for others if needed but haven't done so yet). Check out the attached code. Because I'm using OOP and dynamic terminals in places, I can't use the standard FGV uninitialised shift register, so am using a single element queue to store the data. This seems to be working OK now (feel free to use the code if you like - but I'm not promising it is bug free).

The part that I'm having real trouble with is supporting custom data types. I thought it would be really cool if the user could create a new FGV class - and then add in private data to the class which would then be converted to be the data type stored in the FGV. The problem I'm having with this is the connector pane on the FGV, as I can't find a way to easily update the data type on the input and output to the FGV. I have tried a few ways but none seem like less hassle than just creating the FGV from scratch anyway......

 

Probably the easiest method I've found is to create separate dynamic accessors which can be dropped either before or after the FGV vi which stores the data. This isn't too bad but doesn't give the simplicity and ease of use I was hoping for.....

 

Any ideas???

 

Let me know what you think. I've possibly made this far more complicated than it needs to be but its been a bit of fun anyway.....

 

Cheers,

 

Pete

Universal FGV.zip

Link to comment

You'll be happy to hear that people have thought of similar things before (for instance - http://forums.ni.com/t5/LabVIEW/LV2OO-Style-Global-VIs-from-NI-Week-2007-presentation/td-p/562527) and that LV has a much simpler mechanism for doing this - create a regular class, then create a data value reference to an object of that class. The DVR allows you to access the object using the reference. If you create property folders for the class, then the property node can even accept a DVR and get the object out of it automatically.

 

A simple example:

 

post-1431-0-93341500-1363623822.png

Edited by Yair
  • Like 2
Link to comment
  • 2 months later...

WOW, I had no idea that you could hook the DVR directly up to the Property node. Thanks for showing this here.

 

I am trying to think of a good way to pass UI settings (i.e. On/Off switch states or  User location) down to Data Processor Actors.

 

I think I'll just create a UI-Real Time Variable Class, make a DVR then Send a Message to the Actors with the DVR.

 

Then any Actor Process that needs these Real time Updateable Values set by a User can pull what it needs directly from the DVR.

This method would be instead of Messaging each Actor with the new Value every time that the UI had a setting Change.

 

Any Thoughts on this?  Does this seem exactly what I should do?

 

Should I just Use a <gasp>  Global?

Edited by monzue
Link to comment

Hi,

 

I am not sure I understang the last question you asked (should you use a gasp global?).

 

Just to point 2 things out in addition to the post of Yair:

 

DVR over Classes are indeed very powerful (to make sure you can use the same object instance in 2 loops for examples). However it is advised not to allow to use the In Place Stucture outside of the class method (it can be forbidden in the class properties in the Inheritance menu). This mean only working with the DVR in the main program and getting the object instance only inside your FGV. This also means using a create and destruct method to instanciate your class.

 

Using DVR you can still use most of the common OO Design Pattern as the classes references are castables. HOWEVER you can not define the Class Reference Input Terminal of a method as dynamic dispatch terminal. This means, if you want to use dynamic dispatch methods, you have to wrap them around a static dispatch method which would get the object out of the reference (it basicaly obliges you to use the channeling pattern for dynamic dispatch methods).

 

Summary:

* DVR are good. 

* The object should only be accessible from the class method

* You should use a create and a destruct methos tocreate the object and delete it

* References are castable

* You have to use the Channeling Pattern for Dynamic Dispatch method from a class reference

 

Hope this helps

Link to comment

drjdpowell,

 

using your messaging framework,

 

My main reasoning was using a DVR requires less code work to recieve the data in the Actors and there are no memory copies(granted, most UI settings are not very memory intensive): 

 

When not Using a DVR:

--

one has to make sure that every actor recieves an update when the UI actor has a user change something.  -  This could be done easily enough with writing the variable to the Notify Observers (Event) in your messaging framework and having all actors that need to be updated register for this event.

 

Then each Actor should contain the UI-Settings class stored in a shift register that is the same as the one in the UI actor.  And as events happen, the UI-Settings class is updated with the new values.

 

NOW, here is something that Gets me also....... Some of my actors have a communication loop AND a processing loop that Runs as fast as it can. Now i have to not only pass my UI-settings to the Communication loop, but also to the Processing Loop. So In this case, I am passing the UI-Settings between the two loops on the vi via Notifier, and the Notifier updates every time the Communication loop gets an update.  Much like what you have in the Metronome Class.

--

 

If Using a DVR,  then the Reference is passed once, and every time a Process actor needs a parameter from the UI, it simply pulls the Correct value from the DVR.  I am sure you may loose some encapsulation here, but the gain in coding speed from not having to register for all the events and no memory copies may be worth it?  Granted if the UI-Settings needed to be shared over a network, the way to go would be not using a DVR.

 

I started thinking about DVR's because i just used one in my code.

Consider This Case:  The User launched a TCP Client Actor from a setting on the UI.  This TCP Actor was constantly fed an image.  The way I handled this, was I created an Image DVR and put it in the class that launched the Actor.  So i fed the Image DVR around to every Actor that needed it and as the TCP Actor Updated the Image, it was accessible everywhere very conveniently.

Edited by monzue
Link to comment
However it is advised not to allow to use the In Place Stucture outside of the class method 

I would suggest it is not as black and white as that. If you are trying to guarantee the correct use of the object in a reference design that is correct.

 

However I have used designs where I still make the methods take the object directly and the application is in charge of dealing with the DVRs. There are a few advantages:

  • The class is more reusable, it can be used by value or by reference.
  • DVR is a form of communication, the application architecture should and can dictate the communication method, not the library.
  • You can decide what functions are 'atomic operations' i.e. you have methods A, B, C. If each method passes a reference to another and you have two loops you could have the execution order A1,A2,B1,B2,C1,C3 or any other combination. If the methods pass objects you can wrap all 3 inside a in place element to guarantee A1,B1,C1,A2,B2,C2 or 2 then 1.

Link to comment

Maybe a hybrid approach could work... You could create a singleton class that provides global access to an encapsulated DVR that references your 'Model' data.  You can put semaphore mutex functions in the class so that Read/Modify/Write sequences can be safely performed by any processes in your app.

Link to comment
 

I would suggest it is not as black and white as that. If you are trying to guarantee the correct use of the object in a reference design that is correct.

Hi,

First of all, I just realized I got some stuff wrong on this toppic. I did not see at first that Petehorn and Monzue are not the same users and my message was more ment for Petehorn. Sorry for that.

Secondly, I tend to disagree with what u said (not the use of both object and reference for a class instance, but the use of in place structures outside the class methods). Not to pollute the thread with 2 parallel discussions, I opend a new thread in the OOP.section with some follow-up questions to your post. The link is http://lavag.org/topic/16866-use-of-in-place-structure-outside-a-labview-class/

 

Cheers

Link to comment

Some random thoughts:

1)  I tend not to have an actual “UI actor”; instead I have each actor have it’s own UI on its front panel, and have the main actor present the subactors in one or more subpanels (or just open their windows.  This involves less messages to pass around.

2)  One can also deal with needing lots of messages for lots of UI controls by treating the controls generically using techniques illustrated below.  This is a “Control Server” example that I don’t think is in the version of “Messenging” in the code repository, but will be in the next version.

post-18176-0-32082200-1370178616_thumb.p

Changing any control in Pane 2 of the “Control Client” sends a Variant Message that then fires a Value Change event in the Control Server.

 

You can do the same thing with “Notify”, and you can also write generic code for setting cluster items using OpenG functions.  Would this kind of stuff help reduce the programming burden?

 

3) The above technique in (2) is event driven (User pushes button —> sends message —> fires Value Changed event).  In contrast, using a DVR requires the receiver to poll for changes to the UI settings it cares about.  It also works remotely (the example above works over TCP), though that is often not needed.

Link to comment
  • 1 month later...
monzue: yes, it seems easier. Yes, the code can be lighter. It is one of the best ways to introduce race conditions into your actor interactions.

 

I understand that this can easily introduce race conditions.

However, in my case where I used the DVR (as essentially a FGV by reference) , I only desired to have access to a recent image for viewing.  I understand that this DVR method would not work effectively if I was trying to capture every single frame sent over the network, or if I needed to associate a real time parameter to an exactly timed image.

 

 

Maybe a hybrid approach could work... You could create a singleton class that provides global access to an encapsulated DVR that references your 'Model' data.  You can put semaphore mutex functions in the class so that Read/Modify/Write sequences can be safely performed by any processes in your app.

 

Why would I simply not use the In-Place Structures?

 

Some random thoughts:

1)  I tend not to have an actual “UI actor”; instead I have each actor have it’s own UI on its front panel, and have the main actor present the subactors in one or more subpanels (or just open their windows.  This involves less messages to pass around.

2)  One can also deal with needing lots of messages for lots of UI controls by treating the controls generically using techniques illustrated below.  This is a “Control Server” example that I don’t think is in the version of “Messenging” in the code repository, but will be in the next version.

attachicon.gifControl Client Server.png

Changing any control in Pane 2 of the “Control Client” sends a Variant Message that then fires a Value Change event in the Control Server.

I have a Main UI actor that has subpanels, menus, right-click menus on the subpanels as well as the controls inside the subpanels.  For charting, I mainly have Simple Vi's that only process and display a chart information.  For example, the Main UI actor will get a Chart1 data message and this variant will be directly passed into a simple Charting vi that executes once and Updates the Chart control on the Front Panel, which is user selectable to be placed into a subpanel on the Main UI.  So basicly I didn't see the point in making the simple VI another actor.

 

However, I do also have other pop up windows that are actors in themselves that are launched by the Main UI.

 

My Main problem is communicating the UI Variable information to the select locations / actors in the code where the processing happens.  Currently, I am doing a mix of event messages, and DVR UI Variables that are polled by the processor when the select variable is needed.

The thing is, I seem to be having to pass the DVR UI Variable Reference to almost every Actor, and I don't think that I should be doing that.

 

Anyways, I am going to think on how my UI is laid out, and I am going to describe it more in this thread:

 

http://lavag.org/topic/15438-re-designing-multi-instrument-multi-ui-executable/

 

I'll continue to comment on UI layout and communication with controls there to save this thread from going off topic too much.

Edited by monzue
Link to comment
3) The above technique in (2) is event driven (User pushes button —> sends message —> fires Value Changed event).  In contrast, using a DVR requires the receiver to poll for changes to the UI settings it cares about.  It also works remotely (the example above works over TCP), though that is often not needed.

 

Yes, I like the way that this is flexible for any control,  but my Multiple Actors individually need different control events.

 

Polling  is ok for me, because usually in the Proccess actors, the process is started on a timed basis, or is freerunning in a loop as fast as it can go.  In these cases, I just want the latest or close to latest desired variable from the UI as parameters in the process math.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.