Jump to content

PaulL

Members
  • Posts

    544
  • Joined

  • Last visited

  • Days Won

    17

Everything posted by PaulL

  1. Thank you, all! We are happy the telescope is working so well! The LabVIEW developers on the DCT team are Michael (http://lavag.org/user/4721-mike-nrao/) -- who delivered the aforementioned presentation at this year's CLA Summit, Ryan (http://lavag.org/user/15218-rgodwin/), and I. I hope to see many of you at NI Week!
  2. It is possible to use a heartbeat or something similar. There are some ideas in this thread: http://lavag.org/topic/15531-detecting-network-drop-out-from-crio/page__fromsearch__1. You could combine this with a watchdog, I guess. I haven't done that myself. Paul
  3. Thanks for the links! The solution we found that worked best for our purposes was the following: Our "data listener" (kind of a message handler) on the desktop periodically sends a heartbeat command to the RT controller using the same mechanism as other commands. (There is only one shared variable since we are using the Command Pattern. In other words, the data listener just periodically writes a heartbeat object.) We wire the timeout on the "Read Variable with Timeout" function (in the controller, now) to be whatever we want the heartbeat timeout to be. If there is a breakdown in communication the timeout will occur, and the controller responds appropriately. This solution has turned out to work quite well and allowed us to achieve what we wanted just by adding a small piece to the existing communication scheme.
  4. I favor this approach, too. Within a view element (and for us a view is a composite of individual view elements, not a large monolithic VI) the code handles user events (eg., button clicks) to send messages orresponds to messages by changing state (updating data or appearance). There is (generally) no need to pass control references; although I think passing control references can be a valid approach, most often I think it is not the best option in LabVIEW. Note that we do invoke lots of common code within the view elements themselves. With this approach views are quick and easy to create, and simple. (What is important is to keep the view decoupled from the controller, by the way.)
  5. Congratulations! Enjoy!
  6. We use LabVIEW objects on RT (cRIOs) for many applications in LabVIEW 2011. It works quite well for us, so that I would highly recommend using it now, but there are some important things to note. See these threads: http://lavag.org/topic/11928-lvoop-on-rt-stories-from-the-field/page__fromsearch__1 and especially http://lavag.org/topic/15449-lvoop-on-rt-concerns/page__pid__93244#entry93244. The most critical advice I have is to use interfaces if you plan to deploy applications of any significant complexity! Paul
  7. Hmm... We don't see either excessive build times or long delays when editing class methods (except under special circumstances, such as we are making the first edit to just deployed real-time code, but that has nothing to do with classes). The class properties dialog does still take too long to populate. For the record, I just looked at one of the simpler RT controllers and it has more than 60 classes in the hierarchy. We are using LabVIEW 2011 presently. (A very special case where we did have problems that did have lots of classes was really an issue with the DSC Module during the build process and we have a workaround for that. I think this is not an issue in 2011 anyway.) One thought I have is that we use many interfaces and a few implementations of the Factory Method Pattern that together dramatically reduce source code interdependencies. Before we did this deployments on RT in the development environment very often didn't even complete. Now these deployment issues are a thing of the past.
  8. Two suggestions: Probe the input wire. If you double-click the "Display Info" VI in-situ does it bring up a dialog asking you to choose an implementation?
  9. Hmm... "Delegation Pattern" is not one of the GoF patterns. There is a Wikipedia article (http://en.wikipedia.org/wiki/Delegation_pattern) that gives us simple example without an interface and then many examples with an interface. This article (http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/delegation.html) gives similar examples, and mentions that "Several other design patterns use delegation - the State, Strategy and Visitor Patterns depend on it." It looks to me like the key idea is that a class assigns a task to some other class that it possesses through Composition. The type of the attribute may actually be abstract so we can vary the specific type. Anyway, that's after a brief read. I haven't looked at this before.
  10. I finally had a chance (after travels and paper submissions) to read the document. This topic is quite important to us. (You can read my related idea here: http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Support-serialization-of-LabVIEW-objects-to-interchangeable-form/idi-p/1776294). Background: We are approaching this from the use case in which we serialize/deserialize objects we share with nonLabVIEW and LabVIEW applications. For the former we write custom code for each class (yuck) until we get to something EasyXML can handle; for the latter we use the native LabVIEW VIs to flatten to string or XML without any customization. Both approaches work for their use cases but the first is quite cumbersome, so we will be happy when there is another option. I think this functionality is essential, not just a nice-to-have (and hence deserves the proper emphasis from NI), and I think it will greatly enhance the marketability of LabVIEW for use in large systems, where LabVIEW applications are almost certain to need to interact with nonLabVIEW applications. (In other words, the potential benefits could be quite substantial.) Some comments I have on AQ’s draft document (v 0.4): Nomenclature (trivial): “Deserialize” is a much more commonly used term than “unserialize.” (Check the results from a Google search.) I’m guessing that the particular scheme AQ followed used “unserialize”? Both seem appropriate to me. Inheritance relationship for Serializable (just pondering): Anytime I have to inherit from a class in a language that doesn’t have multiple inheritance or interfaces I become concerned. On the other hand, since every serializable class must call its parent, this may make sense in this situation. At first glance I think it will work for our use cases (but see below). Terminology (minor; probably already in the works): I realize “Magic Serialization Scripting Tool” is just a conceptual (and facetious) name, but, NI, please don’t use “scripting tool” in the name of the final product. First, it makes me wonder if it is a tool that will help me write scripts (which it is not). Second, scripting has a connotation for me of something that is at least possibly ad hoc, temporary, and that possibly won’t be supported someday. (Others may think quite differently, of course.) I’m sure AQ’s plan is to make this permanent (right?), and I realize there will still be scripting underneath, regardless of the name, but I want this just to be a “Tool” or “Wizard” or the like. Default values not described (reiteration of major issue): This is the most important limitation (for external sharing) of the present implementation of LabVIEW’s object serialization schemes. Nomenclature (important but won’t change implementation): The document refers to a “standard Factory pattern.” This might seem picky, but I’d like to see more careful wording. The Gang of Four Design Patterns book describes Abstract Factory and Factory Method patterns, and these are different from what the document refers to here. Head First Design Patterns includes a “Simple Factory” “programming idiom” that I think is effectively what applies here, although the implementation differs (reading the object from disk is certainly not the only solution, nor even the most obvious). Yes, there are websites that refer to “Factory Pattern” as well but what the authors mean is often ambiguous. Note that I think the proposed solution is fine for the purpose. I am just urging a little more care in terminology. On types (critical): How will this handle DBLs with units? (We have done this within the constraints we have—and I am happy to share it with AQ; it is nontrivial.) In an XML representation the units should appear as attributes. I think the schema must handle this correctly. ShaunR asked about clusters. The document says, “Some, like, numeric clusters, can be done by writing the individual fields (Point.X and Point.Y as two separate properties in the property bag).” Where and how does this happen? I didn’t see this in the document, but perhaps I overlooked it. (I hope this doesn’t require customization.) I think it would be really helpful to create a UML class diagram so that we can see the different classes and their relationships. (Hint, hint!) Objects as attributes (critical but probably in place): One of my colleagues was curious how this approach handles objects that have other objects as attributes (what the document calls “complete objects”). It seems pretty clear that AQ thinks there is a way to do this, and the document even describes a tree structure, but we didn’t see anything in the document that explains how this works. Again, a UML diagram would help a lot. (I’m wondering how many designers of LabVIEW Object-Oriented solutions would write code of any significant complexity without creating a UML or equivalent model first? I can say our designs are much better when we use UML, even if we iterate between the model and source implementations a couple times. I consider models to be an essential, not an optional, step in the design process.) Representing object-typed attributes (critical): How will this approach represent attributes that are objects? I guess I’m thinking mostly of the XML representation. We opt (and I think this is the most correct way) to use the attribute name as the XML tag and the type as an attribute. (Note that the type is necessary since it is possible for the attribute itself to be defined as an abstract class, but the deserializer will need to know the instantiated class.) [Related note: Similarly, accessor methods should change to use the attribute names, not the types.] The four required methods (minor): Presumably any schema would only need either the version with names or the version without names, correct? So it usually wouldn’t be necessary to create all four required methods per class, but only two. On the one hand there is clutter. On the other hand AQ might have to subclass Serializable and that would mean only one option would be available. EasyXML (major?): The paper describes delegating to EasyXML. I’m not quite sure how that works with object-type attributes, since EasyXML can’t handle objects even as variants. Maybe the framework handles this separately, but somewhere the object needs to end up in the XML representation, and I don’t yet see where this happens. As far as multi-dimensional arrays go I’d recommend looking at how EasyXML handles this (minor, probably already considered). Maybe this won’t work for this effort because those methods rely on variant representations of the data, if I recall correctly, but there still might be something there that is helpful. Response to open issues: The only issue that I can comment on right now is the one concerning arrays. Definitely we would need 2-D arrays, quite possibly 3-D. Dimensions beyond that would be nice to have from my perspective. Overall, this looks promising. We are looking forward to seeing the prototype!
  11. Jon brings up a good question. Will the pieces be on the same machine or networked? Will they be part of the same application? (We purposely break up the pieces into several applications, but that isn't always necessary. Moreover, our applications need to run anywhere on the network.) I guess I would emphasize that I suggest thinking of this (and I think you do) in terms of messaging (sharing data) between separable (which can mean many things) components. My recommendations are to separate messaging from the application logic and to separate the message content from the messaging mechanism. By the way, earlier I said our fastest loops are 62.5 Hz. I realized that's perhaps not the best way to say that. Our RT messaging/state control loops run that fast. We have loops in our FPGA VIs (on compactRIOs) that run extremely fast. Edit: I thought about this on Friday and I realized I should explain further. Our application speed is limited by processor usage on the compactRIO-9074, only a couple percent of which is due to handling shared variables. In fact, a while back I tried to see how fast I could loop just doing a round-trip with single variable. I think I got to 2 kHz before seeing messages getting behind, but even that I decided was due to the processor, not shared variables themselves. The DSC Module offers the ability to use shared variable events, and we have implemented a simpler version of this on RT with user events. We very rarely read a shared variable value without handling an event, and then only when we want to read a pre-existing value (e.g., on start-up on RT). OK, this is more controversial, but we avoid mutexing and transactions in our communication paradigm because we make sure we are doing messaging only. (Or maybe I am missing something and we need these capabilites for messaging for some reason?) Anyway, my point is that we use shared variables for messaging only. The application logic itself handles any state changes. The messaging system never does. I actually think this is quite important, which is why I am bringing it to attention. [OK, this is the most important reason why we stopped using "action engines" ("functional global variables" with an emphasis on the functional) years ago.] We think messaging and what the application does with those messages should be separable concerns. You will, however, find many people on this forum who will disagree. :-) These are just my (reasoned, I think) recommendations. :-) On a simpler note, we have found it is much easier to have "unidirectional" writing. In other words, the recipient of data never writes to that data. (That isn't quite the same thing as saying we have only one writer for a message. For instance, a "Start" command can come from a view for the component or from another component at a higher level in the hierarchy.) OK, that's a lot to chew on for a while....
  12. What are your data rates? We use networked shared variables for communication between components. We send a lot of data, but our fastest loops run at 62.5 Hz. Within these constraints this approach works quite well and is quite powerful and easy to work with after going around the learning curve. (The learning curve itself can be a bit steep.) We use shared variable events but this requires the DSC Module. Maybe Jon can clarify his comment about shared variable race conditions. I don't understand that claim. I admit I don't share his concerns about user events either, but I expect that this is due to a different design approach. We use networked shared variables since they offer the best out-of-the-box publish-subscribe solution. Is publish-subscribe something your application needs? One more thing. Our views are separated from the controllers and models. The views send and display information.
  13. Thanks! I look forward to your questions!
  14. Thanks for the feedback. I'll see what I can find. It is worth noting that the GoF book uses the term when discussing the Strategy Pattern (p. 318).
  15. 1) Yes, although we use the State Pattern -- implemented in exactly the same way -- more often -- in every component, actually, and it is not too much to say that the latter has changed our lives. The pattern itself is a GoF pattern and is the focus of the first chapter in Head First Design Patterns (http://www.amazon.co...35546001&sr=1-1). 2) Of course you may. It is already linked here, actually (https://decibel.ni.c.../docs/DOC-13311), albeit as an add-on. I hope you do read the paper. I think you will like it. Paul
  16. I'm quite happy to hear it was helpful! Thanks for the feedback!
  17. Mike, Thanks. In my first post I showed that if the number is a legacy number the class doesn't recognize the VI correctly. I'll have to try and force a recompile of the VI and see if that fixes it. Otherwise we need to get the number "correct" somehow, I think.... Paul
  18. A VI in a .lvclass file has a property NI.ClassItem.State of type "Int". Does anyone here know what that value represents? Yes, this is a strange question. :-) We are trying to see if we can figure out a way to do merging with .lvclass files. This is the immediate problem. I don't know if we will be able to do a merge in every detail even if we resolve this particular problem. What we do see is that if we delete a method in the working copy and do a Diff (with TortoiseMerge, for the record), we can add the text for the relevant method (which is already on disk in the working copy for this test), but LabVIEW is unhappy (reports that the class is missing a VI) until we remove the VI we just surreptitiously added and then readd the VI through the LabVIEW interface. When we do that it has a different NI.ClassItem.State value. If we know what the value means we might be able to work around this issue....
  19. James, Thanks for sharing! We took a close look at it, and observed the same issue. The queue idea is clever, though.... It does point out a potential issue with what I did. If you abort the top-level VI the subVIs still run (in the development environment). I'm not sure that's a problem for us. Paul
  20. So the previous version had a problem if we ran a high-level view VI (e.g., A), then ran one of its children (e.g., D) afterwards without closing the project. D still had the old value of the input wired so it thought the event was valid, but it wasn't. There are a fews way we thought of to deal with this. The simplest we considered was to add a timestamp when we created the event. If the timestamp isn't recent (presently hard-coded to 0.5 s, which handles all the use cases we expect we will encounter), then we treat the event as invalid and create a new one. I did some other clean-up in this version, but that's the major change. StoppingSubpanelsUserEvent2.zip
  21. OK, here is a quick version with events. StoppingSubpanelsUserEvent.zip It really is what Neil suggested in the first place, I suppose.
  22. Yes, we thought of the temporary named queue approach. It might work. In any case, I will see if I can get this to work if I pass the event reference by wire first. I'm working on it now.... Thanks for not giving up on this thread!
×
×
  • Create New...

Important Information

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