Simio
  • Transportation Library - Trains, Robots, Tanker

  • Do you have objects, models, libraries, path decorators, textures, symbols, custom API code, documentation, or anything else others might find useful? Please attach it here with a brief description.
Do you have objects, models, libraries, path decorators, textures, symbols, custom API code, documentation, or anything else others might find useful? Please attach it here with a brief description.
 #5206  by gdrake
 Sun Feb 23, 2014 10:02 pm
ASagan wrote: Interesting pick-up on this one Mark. I actually think the tanker is correct and the standard objects are wrong. I have worked on systems before where both volume and weight have been constraints depending on density.
The property design of the Flow Library Tank object, for user simplicity, assumes either a flow contents unit type of 'Volume' or 'Weight'. The tank's initial capacity, as well as the tank level mark locations, are then specified in either volume or weight units. The tank was designed this way under the assumption that normally a user has a tank capacity (and level marks) specified in either volume or weight. Not both and not with two distinct volume and weight capacity constraints at the same time.

If an advanced user wants to model a Flow Library Tank object with both volume and weight capacity limits, that of course is still possible.

Simply assign the TankName.FlowContainer.CurrentVolumeCapacity and/or TankName.FlowContainer.CurrentWeightCapacity state variables using an Assign step in process logic (perhaps in run initialization logic or can be dynamically during the run at any time). All the Flow Library Tank's properties are doing is on run initialization setting one of those capacity constraints to the specified value and then the other capacity constraint to 'Infinity'. But you can re-assign both capacity constraints to your own values in logic if you want. Using those provided state variables.
 #5211  by MEagar
 Tue Feb 25, 2014 7:30 pm
Glen...

This logic clashes with the stacked bars since the entity density has been omitted from this discussion, hence the stacked bars animation always need be corrected.

the equation goes volume = mass/density...Thus 2 variables need to be available as user inputs whilst one variable should always be calculated to ensure that human error does not prevail in Simio. If you want to display volume and weight as user inputs, then you have to FIX/LOCK density. Having the three variables not add up = ERROR in Simio.

The equation is fixed in stone thus its possible to use volume and weight at different points in the model as you SHOULD always get the same answer.

Not sure how the infinity is handled in the equation but I will leave it up to you.
 #5213  by gdrake
 Tue Feb 25, 2014 11:05 pm
Mark, when you replied to 'Glen' did you mean me? We have a 'Glen Wirth' and then me (Glenn Drake!). Small company but they have to hire two Glen(n)s just to occasionally confuse us ha ha.

Totally separate note, today I looked at that possible issue with using Filler and the Emptier objects in the Flow Library to possibly deal with floating point round off error issues automatically, and tried a few things, but found nothing that felt really good to actually put in there.

Simple example, if you have a Tank with 1.0 cubic meters, and then an attached Filler object removes flow from that tank in 0.2 cubic meter increments...then what happens on my machine is 1.0 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 = 1e-16 (more or less). Now, after that fifth container entity got filled, you might expect the Tank to be at 0.0, but instead that 1e-16 is still in there.

If you then actually have those 5 filled container entities, in the same model, go and empty their contents into a second Tank using an Emptier...then on my machine I see 0.2 + 0.2 + 0.2 + 0.2 + 0.2 = 1.0000000000000009 (or something like that) added to the Tank. Again floating point math error. Adding up 0.2 five times does not equal 1.0.

This kind of stuff is incredibly difficult to try to deal with automatically. Generally, there is a rule in trying to clean up round-off errors in general purpose code that if 'You don't know what you don't know' then to tread carefully. I could start trying to put in EPSILON tricks but that is invariably like throwing darts at a dartboard. Not only guessing what a 'good' epsilon value might be but also the fact that round-off errors might be a little bit less or a little more and in a variety of situations (as illustrated in my simple example above).

Usually, I try to avoid like the plague getting into EPSILON stuff. I'm always looking for cleaner ways to correct round-off (i.e., situations where the true value is very clear and thus the variable can be simply forced to that value without any kind of epsilon related checking).

We can keep thinking about this, but for now, if you are doing flow transfers involving discrete quantities of fluid/mass that need to be 'exact', but round-off error calculations are sometimes throwing a wrinkle either into logic or into animation, then for now all that I can recommend is to put in extra process logic checks as convenient and necessary to deal with such things.

For example, in my above example, after filling the 5th container then making sure any residual flow left in the source Tank is destroyed. Or, if possibly the flow quantity in the source tank is 0.999999999999999 when you really need it to be '1.0', because there was round-off error when the flow was added to the tank, then perhaps setting quantity variables accordingly to make sure the flow transfer is still successfully completed.

I know this can be a bit painful depending on the situation. This continuous flow stuff can certainly be a bit of pain at times compared to simulation discrete items due to floating point arithmetic...we'll keep working hard on it and beating on it and gradually improving stuff when we can.
 #5214  by MEagar
 Wed Feb 26, 2014 12:01 am
Hi Glen,

I feel your pain...hahaha....and please whatever you do stay away from Math.Epsilon for this...

Lets have a look at this based on the impact that this problem will have on a Tanker object (Transportation Requests) for I think the ultimate generic solution for all FlowContainer elements should be based on this logic...

1. There can always be a positive or negative residual around a specified level (0.0001 + 16000 MT - 0.0001) in a tank (cap of 25 000 MT)...

2. If there is a positive residual, there will be an entity in the output regulator's flow request queue...Thus an erroneous transport request will be logged....

3. If there is a negative residual, there will be no entity in the output regulator's flow request queue...Thus transporter will be stuck as it would not have reached its load level of say 16 000 MT....

Based on these assumptions we have discarded the problem with the residual in the tank, which kinda really can be disregarded...and redirected the problem to the Flow regulators where the actual residual problem becomes more evident...

What I typically do is set the variables on the monitors watching the transfer, to the specified level WITH plus or minus 0.0000000001 depending on the transfer performed. The monitor will thus trigger the end transfer process just before the specified level, and then I simply adjust variables back up by means of rounding up to a higher decimal. (0.0000001 instead of 0.0000000001 )

ALTHOUGH, you HAVE to clear your regulators' flow request queue before and after ANY transfer if you use the above option. This brings another catch 22 for each time you do this, a new entity instance is created.

To be quite honest, I would program in hard code a function that executes after every transfer to round the value up to a higher decimal. i.e. perform the transfer in the code with the monitor to a level of variable - 0.00000001 (HARD CODE) and then have a function call after transfer to cut some decimals and round up back to the specified level which is at a higher order i.e. 0.000001.

Truly think the solution to this conundrum lies close to this logic and its difficult to explain the on the blog...Perhaps we can set up a skype conference call and I can demonstrate as well as enlighten you to ALL potential pitfalls and workarounds we have discovered pertaining to these transfers...
 #5215  by MEagar
 Wed Feb 26, 2014 12:24 am
Also, just a note, I have cracked all this logic but would like to see how you would approach these problems....
 #5216  by gdrake
 Wed Feb 26, 2014 8:46 am
Mark:

Specifically for the Flow Library Filler & Emptier objects, what I will probably do is add something like a 'Stop Early Event' option, where you can optionally specify to stop the filling or emptying operation early if some specified event occurs.

Then in the Filler for example, you could specify to fill the container entity until full or until the source tank is empty (i..e, the tank's 'FlowContainer.Empty' event occurs). Whichever of those events happens first.

In your sort of model, that kind of simple approach would guarantees the container is 'filled' and exits the Filler regardless of round-off error. If your fill target is 2.0 and there is only 1.99999999 in the source tank, then the tanks goes empty first and the filler stops. If there is 2.000000000000001 in the source tank, then the container entity full event happens first and the filler stops. Either way, the container entity is exiting the filler and away it goes.

Now, in the above latter case where there was 2.00000000000001 in the source tank, of course then you might have some tiny residual left in the tank after the filler is done. In that case, what I have been considering is adding an 'Auto Destroy Contents Mode' to the Flow Library Tank, which allows you to auto-destroy the tank's contents if some specified event occurs and perhaps a condition is also true. Thus, for example, you might want to auto-destroy a tank's contents if the inflow entity type is changing and new product is entering the tank (to 'clean' the tank). In this filler case, when the container entity exits the Filler, you might want to have the Tank be notified of that event and then check if there is some tiny amount still in the tank and if so then just automatically destroy it.

If I put in features like above, I think you'd be able to model your flow transfer situations using the Flow Library Tank and Flow Library Filler for example without having to worry about any EPSILON tricks to account for round-off error. And the above are generally the type of features that I lean towards. Getting into Simio's flow engine itself artificially adjusting flow quantities by small epsilon amounts to try to deal with possible round-off errors doesn't feel so good.
 #5221  by MEagar
 Wed Feb 26, 2014 6:32 pm
Auto destroy is a good idea.

Just one thing on the filler to keep in mind, the source tank may have a capacity greater than or less than the entity being filled. Important to test fringe conditions.
 #5255  by gdrake
 Mon Mar 17, 2014 11:56 am
MEagar wrote:Auto destroy is a good idea.

Just one thing on the filler to keep in mind, the source tank may have a capacity greater than or less than the entity being filled. Important to test fringe conditions.
Mark, just an FYI that in Sprint 102, the following objects in the Flow Libary:

Tank
ItemToFlowConverter
FlowToItemConverter

Have all been enhanced to provide new 'Purge Contents Triggers' functionality.

For the Tank object, the 'Purge Contents Triggers' feature will allow you to specify conditional event-driven triggers that will immediately remove and dispose of any contents held in the tank, putting the tank into an empty state. This will easily allow you for example to clear residual flow contents in a tank due to round-off errors, by having the tank perform a conditional check when some specified event occurs (e.g., each time a filled container exits a Filler that the Tank is supplying, then purge the tank if the remaining contents is smaller than some epsilon quantity). A 'Purge Contents' trigger might also be defined to purge/flush/clear the Tank for any other sort of reasons, to reset the flow line back to an empty state.

For the ItemToFlowConverter object, the 'Purge Contents Triggers' feature will allow you to specify conditional event-driven triggers that will immediately remove and dispose of any generated flow waiting to exit the converter object, putting the converter's flow container into an empty state and cancelling any further outflow for the discrete item entity whose conversion was in-process.

For the FlowToItemConverter object, the 'Purge Contents Triggers' feature will allow you to specify conditional event-driven triggers that will immediately remove and dispose of any inflow collected by the converter object for creating the next discrete item entity, putting the converter's flow container back into an empty state.

In addition to the above features, based on some of the discussion that was going on in this Forum thread regarding the Filler (or Emptier) being more flexible dealing with possible round-off calculations, a new 'Stop Early Event Name' property may be found on those two objects in Sprint 102.

The 'Stop Early Event' feature on the Filler & Emptier objects will allow you to define an optional event that will end the filling or emptying operation early (before reaching the desired fill or empty target) if the specified event occurs. If, for example, you have a Tank supplying a Filler, you might specify that the Filler should stop filling the current container entity if the container becomes full OR if the tank becomes empty, whichever event occurs first. This type of logic would ensure that the container entity is always going to finish the filling operation and exit the filler, even if say there is a scenario where the container entity's capacity was 0.2 but the contents in the tank was 0.199999, the tank would go empty and the filling operation would be considered completed.

Thanks again for the feedback on this thread. The input on this forum is appreciated, and we often use information here as input into possible new enhancements and design evaluations.
 #5257  by ncollins
 Mon Mar 17, 2014 1:59 pm
Note that there is a new TransportationLibrary.zip file posted. The latest includes behavior changes involving RailCars/HopperCars, specifically Cars that are being detached from the train at a node and also being loaded/unloaded at the same node. Our existing behavior was that the train waits for both the car to be detached AND loaded/unloaded before restarting. The new behavior will be that the car will be detached, the train will restart, and the loading/unloading will take place after the train restarts. There have also been some bug fixes and re factoring as well as an additional examples added to the zip file.
 #5339  by ncollins
 Mon Apr 07, 2014 1:29 pm
Note that there is a new TransportationLibrary.zip file posted. The latest includes behavior that allows a RailCar to request a Locomotive. This is done by the RailCarby executing the RequestTransport process on the desired Locomotive. The Locomotive can use the “Remain In Place” option on the Idle Action property, and then respond to the request to go pick up and move a RailCar. Please see example DropPickTrain_DetatchToLoadUnload. spfx to see how this feature now works.
 #6435  by BenLankford
 Fri Mar 27, 2015 2:36 pm
Love the articulated robot! Is there a way to specify which direction it rotates? On my initial trial it only moved clockwise when loaded and counter-clockwise when empty.

In the model I have the robot loading a server and then unloading it. I figured the travel direction was because of where I located the nodes. I moved the output node of the server so that it would be less distance to go CCW but it still ran CW. I continued moving things around until I made it work. It seems to be tied to where the node is located left/right (or east/west) of the robot's base node?

It's not a big deal for me right now, but I figured it might come up if I try to send a robot through a wall or something 8)