Jump to content

drjdpowell

Members
  • Posts

    1,969
  • Joined

  • Last visited

  • Days Won

    172

Posts posted by drjdpowell

  1. I would still have to create some sort of case structure (perhaps not, though, because all my child classes will probably have overridden the VI in question) and/or a sequence that would rely on working with the paths of the VIs, correct? 

    No.  The static VI just calls the dynamic VI, passing in the class instance and so allowing dynamic dispatch.  Below is the static VI I use:

    post-18176-0-52608400-1357657741.png

    • Like 2
  2. I have a 2D array in a cluster in a 1D array in a cluster. after flattening, in the JSON string, the 2d array looks like 1d. if I try to unflatten this string to my cluster, the variant to data primitive throws me an incompatible datatype error. it seems, 2d arrays are generally unsupported?

    I am having a problem uploading a new version to the Code Repository, but you can download it from bitbucket.  It is extended to work with multi-D (rectangular) arrays.

  3. On the question of whether LV is object oriented or actor oriented: Neither, inherently. Both of those are design styles, and they are orthogonal to each other. One speaks to a way of data packaging (object) and the other speaks to a way of controlling execution flow (actor). 

    Are they “orthogonal”?  Actors encapsulate their internal data, and messages to the actor can be thought of as methods of an object.  

  4. Hello,

    I’ve just found that I can’t upload files to the LAVA CR.  I was trying to submit a new JSON LabVIEW version and I kept getting a “This Upload Failed” error message.  See below:

    ...

    Well, I was about to attach a png image to this post to show the error, but I couldn’t, as I have the same error when attaching files to posts  :angry:   

     

    Anyone else have the same problem?

     

    — James

  5. The typical architecture in larger systems is several PID or lesser controllers, often per component basis, and one single MPC controlling all the other controllers...

    Yes, that’s how I (and many or most others) would do.  I would have dynamically-launched VIs as “components”, which I think of as “parallel processes” or “actors”.  I use LVOOP for the inter-process communication (“messages” and “addresses”), with each parallel process being represented by-reference to its LVOOP address object.  The address is effectively by-reference because it wraps some communication reference like a queue, user event, or TCP client.

     

    Note that an “actor” is effectively like a by-reference, asynchronously-accessed, active object, which is not the same as standard OOP objects in text languages, which are by-reference, synchronously-accessed, non-active objects.  One can create the latter using a DVR in LabVIEW, but whenever I’ve considered using one I’ve always decided that stepping up to an actor is better (one concern, though, would be speed; straight DVR access will be fast compared with a request-reply exchange of messages via queues).

  6. Well. Decoding an N dim array is not that hard (a 1d array of values with offsets). But I'm not sure how you envisage representing it internally .

    If you can give me a 1d array, and the dimensions to calculate the offsets, it will be easy to recursively convert to nested JSON arrays inside of JSON arrays (and it will work for any number of dimensions).

    — James

    BTW> One other issue that occurs to me is “ragged” arrays, arrays of other arrays of varying size. In LabVIEW, I would make a ragged array from an array of clusters containing arrays; in JSON, it would be just an array of arrays of varying length. I would probably try and add support for conversion between these types, too, if we’re going to support multi-D arrays.

  7. I like the idea of SQLite as well, ..., I think this can just operate in memory though

    You can use SQLite entirely in memory by using “:memory:” as the filename. Also note that SQLite uses a caching mechanism that makes it effectively in-memory as far as reading goes, as long as the database is smaller than the cache size (2 MB by default).

    post-18176-0-28201100-1355405383.png

    • Like 2
  8. I assume you have no control over the format of the message? Objects are best flattened/unflattened upwards from child to parent, which means the child information should precede parent information in the message. Your messages are the opposite. I suspect you can still parse it without “downcasting”. You’d have to generate a “type” object to call a parse method, but rather than set the private data of the parent type, the parse method would call further parse methods on the remaining bytes to actually return the subclass. So the parse method called on the “type” object would actually return a different object of the final subclass. Does that make sense? It’s a bit like the onion skin of recursion; instead of calling methods one after the other, you call them one inside the other, going all the way down to the final subclass, and then rising back up through the inheritance hierarchy setting the private data of each level.

    — James

  9. I need to install the latest LabVIEW version to look at your code, but some of what you describe sounds very similar to what I’ve done. My Transports are called “Messengers”, and I have “Actor” objects that contain a Messenger that is the method to send messages to a process running in parallel. But other stuff mystifies me. It sounds like you have message classes as the children of your Process classes; but aren’t messages and processes entirely different things.

  10. Didn’t really follow the description of the problem (you’re sending message classes over a CAN bus?) but the fact that you have a reference (the CAN bus) that is needed by multiple processes (the zones) suggested there should be one dedicated process to encapsulate that reference. It shouldn’t be the Zone Manager because that has a well-defined job (managing zones) that is independent of CAN bus. So you need a “CAN bus actor/active process/whatever” that is the gatekeeper of the CAN bus and forwards all the messages.

  11. [whatever]MQ is a great solution if you need to open communications with another programming language. But why take your messages out-and-back-in to LabVIEW environment if you don't need to? Sure, RabbitMQ was easy to install and configure for you... but what about the end user? Complex deployment = more difficult maintenance.

    By “easy” I meant dead easy. Google instructions, run two installers, run LabbitMQ examples. Now, configuring a cross-machine, robust-against-failure message broker would be a whole higher level of complexity, but then John’s N-client, M-server system with the requirement of robustness is going to be complex regardless.

    I couldn't agree more. Publish-subscribe messaging is an essential feature of many types of today's applications, and to do publish-subscribe messaging without events (or the equivalent) is pointless.

    Can one do it the poor man’s way; have a reentrant subVI that waits on a Shard Variable and forwards message to a User Event?

    Polling is definitely the right name here, and this kind of scheme proved to be quite messy for me as requirements evolved. I initially thought the only challenge would be dynamically adding and removing connections from the polling loop and efficiently servicing the existing connections. Before long, I had dozens of connections, some required servicing small amounts of data at rapid rates (streaming, essentially), while others were large chunks published infrequently. While the polling loop was busy waiting-then-timing-out for non-critical items, some critical items would experience buffer overflow or weren't being replied to fast enough (my fault for architecting a synchronous system). So I incorporated dynamically configured connection prioritization to scale the time-out value based on assigned priority level. I also modified the algorithm to exclusively service, for brief-periods, connections flagged as potential data-streams when any data would initially arrive from these connections.

    This quickly became the most complex single piece of software I had ever written.

    I wrote a TCP server the other way, using dynamically-launched processes, and it actually came together quite well, and seems scalable (though I have yet to had the use case to really test it). There is a “TCP Listener Actor” that waits for connections and launches a “TCP Connection Actor” to handle each one. The Connection Actors forward incoming messages to a local queue (or User Event). As each actor only has one thing to deal with, they are conceptually simple, and don’t need to poll anything (this is in my “Messenging” package in the CR if your interested).

    An advantage of making your own TCP server is that you can customize things; my server is designed to seamlessly support my messages, which carry reply addressed (callbacks) and have a publish-subscribe mechanism. Supporting both with Shared Variables would (I suspect) be just a complex in the end as going straight to TCP.

    — James

×
×
  • Create New...

Important Information

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