Jump to content

drjdpowell

Members
  • Posts

    1,994
  • Joined

  • Last visited

  • Days Won

    183

Everything posted by drjdpowell

  1. I suspect simply writing to an IMAQ image indicator inside the producer (and get rid of the consumer entirely) will be less overhead than your complex structure.
  2. You’ll need to mark your Image Indicator as “Synchronous Display†if you want it to display before the Producer overwrites the buffer. Indicators are asynchronous by default and update at something like 60Hz, slower than your 400 frames/second. BTW, I can’t see how this code would interface with some other process doing the main application work on all 400 frames. What do you do with the full 400 frames?
  3. I don’t have enough of a feel for your application to give specific advice, but are you sure it wouldn’t be simpler to attend to the main processing of your 400 images per second in a simple clean way, then just make a copy for display 20-30 times per second for the separate display part, rather than invent a complex locking system to avoid those 20-30 copies? You might be able to do the display with a single IMAQ reference, making it very simple.
  4. I wish they would extend this to User Events. Last-only User Events could be very useful.
  5. Again, check that your frame grabber isn’t already buffering, with a “Get latest frame†method. That is what I would expect it to do. And this would greatly simplify your program as you’ll only need one loop. However, you can get “lossy behavior†by getting the Consumer to flush the queue and only process the last element, passing any other IMAQ refs returned back to the C—>P queue. You might need more than 3 refs if your Consumer is very slow.
  6. Uh, it aint magic. If you can consume 90 frames a second then you can’t produce 100 frames a second. In that case, a single buffer would lead to something like 45 frames/sec, as the Consumer waits about half the time for the producer. With two buffers the frame rate would still be less than 90/sec, as jitter in the Producer sometimes causes the Consumer to wait. With three buffers the jitter doesn’t matter, and one gets 90 frames/sec. But you don’t get 100. BTW, you should check to see if your Matrox frame grabber isn’t already buffering frames asynchronously, rendering additional buffering pointless.
  7. Why don’t you just use two queues and three IMAQ refs? Producer takes a ref from one queue, fills it, and puts on the other queue. Consumer takes from that queue, reads it, and puts it back on the first queue. Simple. Why do you need some complex locking system?
  8. Are you sure of that? I wouldn’t expect a queue to make a copy of a pointer-based data structure like an array or object. Unlike Notifiers, which must make a copy on reading.
  9. Version 1.3 contains the following significant changes/additions: 1) new pallet location under “Data Communicationâ€. 2) a new “DEV Actor Template†which is my attempt to combine two past templates I have used into a singular one with the advantages of both. Find the templates under “<LabVIEW>\examples\drjdpowell\Messenging\Actor Templatesâ€. This design owes a debt to the excellent JKI “state machine†template. 3) I have had a project where I have dealt with an array of actors (and analysis chain), and this has let me exercise and extend the “FutureToken†part of the library. A Future Token is a single-use address that can be used to represent and organize messages that have not yet been sent. This is mostly used to deal with the indeterminate response order when gathering information multiple actors at once (for example, when requesting configuration information from many actors for saving to a single file). This allows the gathering of multiple response messages into a single “Message Bundle†that can be acted on as a single step. The Bundle can be easily converted into an array or cluster of the required type. (Originally described in this conversation.) This is a form of the Scatter-Gather messaging pattern. This helper actor deals with the fact that replies to a series of requests can come back out-of-order, leaving the last reply not consistent with the last request. I developed this in an app where mouse-move events over icons representing running actors triggered a request-reply to the relevant actor to get a description for display to the User. Fast mouse moves could exceed the response time of some busy actors, resulting in an inconsistent description. This is a form of the Resequencer pattern.
  10. Could you explain more? Your initial description gave the impression of being very complex, a lot more complex that the Extensible Session Framework.
  11. If the User is comparing “runs†then how about an overlay feature. Display all plots twice (with the second plot having the same colour but being dashed to distinguish it) and provide a single deltaT time shift to the second plot. This delta can be based on something that defines the start of a “run†or can be User adjustable.
  12. I believe Quick Drop uses the VI Title, rather than Name, so we can easily change the titles without causing any other issues. String values are escaped; however I realized recently that the name strings in JSON Objects aren’t escaped. That’s on my list of changes to make when I have the time. —James PS> since we are listing issues that need to be addressed, the parsing fails on empty subObjects, such a {subObj:{},â€OtherItemâ€:1}
  13. As a word of warning, any system of waiting on multiple different channels of information in one loop is very tricky to get right. Not impossible, but one is well advised to attempt to get away with one channel instead, or alternately with additional receiving loops, one per channel.
  14. I apologize to users of this library. When NI made me rename the library to “SQLite Library†from “SQLite LabVIEWâ€, I inadvertently allowed VIPM to rename the root directory accordingly, so this might cause your minor conflict headaches when opening old projects. Sorry.
  15. I keep meaning to make time to work on JSON but here’s an idea: Instead of storing the JSON Object’s values in a Variant look-up table, store them in an array and store the index to that array in the lookup table. That might have better performance since one may be able to do some operations in-place on the array (Variant attributes always make copies, sadly). As an added advantage, one can output the JSON Object in the original order by using the array order. There would be some overhead here, as you’d have to sort the names based on the indexes to match them to the array order, but this part could be easily be optional based on a boolean input (similar to “Pretty Printâ€). Let me think about it some more...
  16. The basics isn’t complicated. I don’t even have a formal MVC architecture like mje and couldn’t tell you exactly what’s the “model†in my projects. The central idea is that state is held (“ownedâ€) by the component furthest down towards the actual thing that the state is about (data, as mje talked about, or hardware, as is more likely in my case). This component is the Model. UI commands flow down to this Model. UI “views†(the information shown to the User) flow up from the Model. There is a clear C —> M —> V linear chain of action. The simplest MVC in LabVIEW is to call a write method on an object, setting it with a Front Panel control, then calling the read method periodically and writing to a local variable of the same control. For example, if set “Output Voltage†to 6V and the limit is 5V, then my control will say 5V, the actual output value, rather than 6. If an automatic safety feature kicks in a limits voltage to 1V, then my control will show 1V. My FP control, acting as a “Viewâ€, will always reflect the true state of the system, while still serving its dual role as a “Controller†element. Note: I also highly recommend abstracting away the transport method from the sender of information via a “callbackâ€-like feature. That’s a central feature of the framework I use.
  17. Start thinking in those terms. The Model IS the state. The Model never requests anything from the UI (View Controller). Nor is state “copied†into it. The Controller commands the Model and the Model updates the View with a copy of any state info the View requests.
  18. I haven’t looked at the change, but I imagined that it involved building a separate array of item names. If so, that is a significant additional overhead that will reduce performance. If this ordering can be added either without significant overhead (or can be turned on optionally when needed) then I don’t really object. Note, though, that “what we all kind of expect and know to be right†is the assumption that caused the other-language JSON implementation to be released in such a flawed and brittle state. — James
  19. Side comment: you’re using Property Nodes; relative to that, “Get LVOOP Name†is fast.
  20. SQLite is the nicest solution, but if you only need a decimated graph of the full data (no zoom in for fine scale), then a quick fix is a “self-compressing arrayâ€. An example taken from a past project: Self Compressing Array.zip This automatically decimates the data to keep the total under a fixed size. Never allocates memory except at initialization. But you can’t zoom in; for that and other cool features you have to go with SQLite.
  21. I wouldn’t be in favor of adding overhead to all uses of JSON Object just to support one badly broken implementation in another language. You might be able to make a child-class of JSON Object (“Ordered JSON Object�) that you could optionally use.
  22. Some overheads on common messaging patterns I use from a talk I gave recently: Synchronous Request/Reply Asynchronous Request/Reply Subscribe for future Notifications Asynchronous Dialog Asynchronous Multiple-Actor Request/Reply (aka Scatter-Gather)
  23. A link to the conversation on why the AF uses the pool-of-clones ref in the way it does. Don’t change things until you know what “root loop synchronization†means. I use the same method in non-AF code and haven’t had any issues, so there must be something else involved in the library-locking problem.
  24. The problem is when I recursively dive into sub clusters and convert them into arrays of variants (inside individual elements of the outer array). For example, if I am setting a cluster that matches the JSON text, {subcluster1:{a:1,b:2},subcluster2:{c:3,d:4}} then I will end up with an array of two Variants, each of which is an array of two Variants.
  25. Question: can Xnodes be recursive? If the cluster has a sub cluster, and the corresponding variant in the array contains, not a cluster, but another array, can the Xnode recursively call itself?
×
×
  • Create New...

Important Information

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