Jump to content
dsturrock

Transportation Library - Trains, Robots, Tanker

Recommended Posts

The Transportation Library provides a collection of objects for modeling cargo transportation using trains, trucks, boats, pipes, and robots.


The Tanker object is sub-classed from Vehicle and used to transport discrete and flow entities between node locations. The Tanker has all the same functionality as Vehicle, except it has been extended to have weight and volume limits. In addition to standard discrete pickups and drop offs, the Tanker can also perform continuous flow pickups and drop-offs using a Dock object. The Dock object provides support for flow into and out of entities and vehicles (like a Tanker or HopperCar) supporting flow. The Dock is seized/released by the Tanker/HopperCar during loading/unloading operations at the Dock. The Dock may also follow a Work Schedule.


The Pipe object may be used to model continuous flow through a fully filled pipe. In contrast to the FlowConnector the Pipe requires time for the flow material to travel. The Pipe can be used to connect flow between Tanks or between a Dock and a Tank to more accurately model the travel time of material flow from one location to another. This is particularly useful in applications where heavy liquids are transported over long distances through a pipe.


The Railcar, Locomotive, and HopperCar objects represent various types of train-related vehicles. Train movements are modeled by defining a track network comprised of ControlNode and Track objects, over which trains move. A train is a linked sequence of RailCars, where the first RailCar in the sequence is a Locomotive. The RailCar can represent a wide range of train cars including freight cars, cabooses, passenger cars, etc. In addition a HopperCar is special RailCar that is provided to support fill/empty operations at a Dock. The HopperCar is a RailCar with the added functionality of a Tanker. The RailCars can be linked together in any order; for example a train might contain two or more Locomotives.


The RobotBase, RobotLowerArm, RobotUpperArm, and RobotHand objects are the components used to model a multi-axis robot. The RobotHand is specified as the transporter and the movements of the other robot components are automatically calculated to support the required hand movement.


Like all Simio-provided libraries, this library is open so you can look at how it was built, learn from it, and subclass your own objects to improve them. The Transportation Library was created totally by deriving its objects from other Simio objects and then supplementing with Process Logic. No C++, Java, or other user code was required to write or use these objects. And you can also customize the behavior to match your own needs.

Unlike our built-in libraries, this is not fully supported (although we can provide some help) and we may not continue enhancing it, particularly if we decide to build this capability into the base Simio products. We are anxious to receive your feedback on this library.


Here is a zip file containing the library, documentation, and a few examples.


Updated 2014-01-23 - The InputFlow node's Initial Maximum Flow Rate property on the Dock object was not being used to regulate the rate the Tanker was filled. This has been Fixed. The rate the Tanker is filled can now be adjusted using the InputFlow node's Initial Maximum Flow Rate property.

Updated 2014-02-17 - Updates to the Tanker and Dock objects

Updated 2014-03-17 - Updates to HopperCar and Locomotive behavior when dropping off. Also bug fixes.

Updated 2014-03-19 - Bug fixes - Loaded car no longer takes off on its own after loading, but waits to be picked up by the locomotive and The Loaded add-on process now runs after the loading is complete.

Updates 2014-04-07 - Added ability to allow a RailCar to request a Locomotive. See example DropPickTrain_DetatchToLoadUnload.spfx

Updates 2014-04-17 - Bug Fixes to previous update

Updates 2015-03-23 - Bug Fixes to previous update

TransportationLibrary.zip

Edited by Guest

Share this post


Link to post
Share on other sites

I just updated the library in the original post and included some examples. We welcome your feedback.

Share this post


Link to post
Share on other sites

I see that if I trace Robot, there are some variables that are updated more times in one step. Is it like that those variables make conection with some other part of robot.

So I can use asign step to set varA:= varB/2 and then varA is updated instantly on the change of varB?

Share this post


Link to post
Share on other sites

The pipe object appears to have artificial maximum on its rate of transfer.


The pipe initially starts with a desired speed state value of 2 m/s has a hidden property input. This means that any entity transferring into the pipe starts at a maximum of that speed. Attempting to transfer entities at mass/volumes that correspond to a linear speed greater than 2m/s doesn't work.


Changing this property/state however, does not appear to fix the problem. Entities remain capped at 2m/s.

Share this post


Link to post
Share on other sites
So I can use assign step to set varA:= varB/2 and then varA is updated instantly on the change of varB?
Not quite as easily as that, but you can set a monitor on state VarB so that when it changes you can then "automatically" update VarA.

Share this post


Link to post
Share on other sites

Any ideas when the next update on the Tanker and Dock objects will be completed such that I can plan to redo my old models ?

Share this post


Link to post
Share on other sites

I just uploaded the latest version with the updates to the Tanker and Dock objects. You can find the updated file in the first post.

Share this post


Link to post
Share on other sites

Thanks for the update Glen but I will wait till the next update till the Tanker has been standardized to with the rest of the Simio Flow objects.


i.e. Capacities assignments of a Tank, Filler, Emptier, Flowcontainer:

 

586696312_RightCapacityAssignments.PNG.e9384b4de867702d67598adec4ff1029.PNG

 

vs. Capacity assignment of a Tanker:

 

1397236427_WrongCapacityAssignment.PNG.6788b65ac1bcb0309e1457d12dce7ffa.PNG

 

Not going to have to assign volume and weight at every point in the model where capacities fluctuate due to no "Load Level" capabilities as well as not going to get frustrated again because transfers don't work...i.e. transfer times don't equate real loading times time.....

Share this post


Link to post
Share on other sites

Hi Glen,


There is also no onEntered process on the FlowInputNode on the dock....


Since the feed will 7/10 times be from a tank, how do you change the priority of the entity that is flowing to effect the Priority routing on the Transporter ??


Since entity instances change as they flow through regulators, this process will have to be included at the dock ??


Did you make any changes to the Pipes ??

Share this post


Link to post
Share on other sites
Thanks for the update Glen but I will wait till the next update till the Tanker has been standardized to with the rest of the Simio Flow objects.


i.e. Capacities assignments of a Tank, Filler, Emptier, Flowcontainer:

 

Transport the wounded in combat .zipWrong Capacity Assignment.PNG[/attachment]

 

Not going to have to assign volume and weight at every point in the model where capacities fluctuate due to no "Load Level" capabilities as well as not going to get frustrated again because transfers don't work...i.e. transfer times don't equate real loading times time.....

 

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.

Share this post


Link to post
Share on other sites

Thing here is Alan, if you look at the example included in the transportation library, you will note that they assign volume = 5 and weight = 5. Thus if you want to use this transporter for weight or volume you have to make a double assignment each time. Throw some other conversions such as weight = metric tons and boom, transfer time goes out the window.


There is also the density variable and flowcontainer fringe conditions on top of that.


Bottom line, I can break this transporter so not worth using till fixed.

Share this post


Link to post
Share on other sites

I will remind everyone that libraries posted in the shared folder are not supported Simio products. These are example utility libraries that someone felt might be useful to others.


While we welcome suggestions and even enhancements, these objects are all open and the intent is that you can modify the behavior to meet your own needs.

Share this post


Link to post
Share on other sites
Thing here is Alan, if you look at the example included in the transportation library, you will note that they assign volume = 5 and weight = 5. Thus if you want to use this transporter for weight or volume you have to make a double assignment each time. Throw some other conversions such as weight = metric tons and boom, transfer time goes out the window.


There is also the density variable and flowcontainer fringe conditions on top of that.


Bottom line, I can break this transporter so not worth using till fixed.

 

While I stated that both can be constraints, I do find this rare. When I've used the transporter with weight = 100 metric tons and volume = infinity (say, a train wagon), it seems to work just fine. I don't think I understand your problem.

Share this post


Link to post
Share on other sites
how do you change the priority of the entity that is flowing

 

Just a note that in Sprint 101, the Flow Library Tank object has been enhanced to provide a 'New Inflow Entering' add-on process trigger as well as new built-in 'On New Inflow Entering' state assignment options.


The 'New Inflow Entering' add-on process trigger occurs when a new inflow is starting to enter the Tank object, which may be either the first inflow into an empty tank or a change in the inflow entity type into a partially full tank.


Note that a token executing this add-on process will be associated with the flow entity that is entering the tank. Also, if the logic of the specified process includes any delays, then the inflow rate into the tank will be halted until the process has completed.


You will be able to use these new features to easily assign state values of a flow entity entering the tank, such as its Priority state value.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

Also, just a note, I have cracked all this logic but would like to see how you would approach these problems....

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest ncollins

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.

Share this post


Link to post
Share on other sites
Guest ncollins

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.

Share this post


Link to post
Share on other sites

×