FlexSim Knowledge Base
Announcements, articles, and guides to help you take your simulations to the next level.
Sort by:
Playing Multiplayer Tag in FlexSim! TagServer.fsm TagClient.fsm This is a side project to show off some fun things FlexSim can do using sockets. Sockets are just one possible way that one instance of FlexSim can communicate with another. In its simplest sense, a socket is just a port number and an IP address that computers use to send information to each other. For example, whenever a computer visits a website, it uses sockets to create a connection to the webserver's IP address on port 80 (HTTP) or port 443 (HTTPS). All of this occurs within the framework of the TCP/IP network. Similarly, FlexSim can establish socket connections to communicate with another FlexSim as long as you know the IP address and choose a port for both instances to connect on. Establish Socket Connection In this game of tag, the model that acts as the server uses these commands to set up socket connection with the client: socketinit(); servercreatemain(8002); serveraccept(0); Note: All of the commands in this article can be found in the documentation The client then runs the following to connect to the server. The HostIP should be the IP address of the device running the server model (or 127.0.0.1 if running both client and server on the same machine). socketinit(); int a = clientcreate(); int a_con = clientconnect(a, HostIP, 8002); On both the client model and server model, these commands are in the OnRunStart trigger and the server creates 5 socket connections for each player. 4 for inputs (up, down, left, right) and 1 for passing in their player name from the client. The server model will freeze and wait for all sockets to be set up. For example, if there are 3 players, the server model will wait until 3 clients have successfully ran the client model and connected. After all clients have connected to the server, we can use clientsend() and serverreceive() to send information from client to server. An example of this is sending movement inputs from client to server. This is what that looks like: Client // MOVE if (iskeydown(87)){ clientsend(2, "up"); } if (iskeydown(83)){ clientsend(3, "down"); } if (iskeydown(65)){ clientsend(4, "left"); } if (iskeydown(68)){ clientsend(5, "right"); } Server string up1 = serverreceive(token.Rank * 5 - 3, NULL, 100, 1); string down1 = serverreceive(token.Rank * 5 - 2, NULL, 100, 1); string left1 = serverreceive(token.Rank * 5 - 1, NULL, 100, 1); string right1 = serverreceive(token.Rank * 5, NULL, 100, 1); // token.Rank is the number of the player (1,2,3 etc.) and is used to reference the right // socket for each player's inputs //reset coordinates te.X = 0; te.Y = 0; te.Stop = 0; if (up1 != ""){ // up W meaning the server received an input on this socket te.Y = 1; // this accounts for getting multiple messages from client like "upupup" } if (down1 != ""){ // down S te.Y = -1; // this label is later used in a travel activity } if (left1 != ""){ // left A te.X = -1; } if (right1 != ""){ // right D te.X = 1; } Note: In a typical game environment, the server is also sending information back to the clients, but in this example, all visuals and logic occur on the server. Game Logic All game logic is found on the server process flow. Setup and Order of Models To play Tag, follow these steps: Note: If there are certain firewalls or security groups on your network that doesn't allow traffic into FlexSim outside local networks you may be limited on who can connect to play tag 1. Open TagServer model and change NumPlayers parameter to the desired number of players 2. Open TagClient model and change both global variables (HostIP and EnterNameHere). Again, if everything is running on the same device, use 127.0.0.1 as the HostIP global variable value. 3. Reset and Run the TagServer model first 4. Reset and Run the TagClient model. You should get this output if connection was successful 5. Run clients one at a time for each player until all players have connected and the server will run automatically. This is the output on the server upon successful connection 6. Enjoy!
View full article
Changing the packing method for task executers can be tricky and also can vary widely between types. In this article we'll explore the default packing method for each TE and how to alter it to suit the model's needs. Attached is a model which demonstrates the default packing method and the comparison. The model is also the best place to get premade code for the ASRS, the crane, and the Robot: TEStackingNew.fsm Default Stacking on Task Executers There are two types of default stacking methods on the TE's. AGV's, operators, forklifts, ASRS, and basicTE's all use a simple up and down stacking method: The other TE's (elevator, robot, and crane) don't separate the boxes at all so they all look like they're on top of each other (this is because they're mostly meant to only carry one item at a time): Changing the Stacking Pattern: AGV, Operator, & BasicTE: For these objects, changing the stacking method is relatively simple. Add 5 labels to the object: numx, numy, xshift, yshift, and zshift Add an OnLoad trigger in the properties panel Set the trigger by going to Visual->Set Location Type in this code current.xshift+item.size.x*((item.rank-1)%current.numx) -current.yshift+item.size.y*(Math.floor(((item.rank-1)/current.numx)%current.numy) - (current.numy-1)/2) current.zshift+item.size.z*Math.floor((item.rank-1)/current.numx/current.numy) The only thing that differs between these 3 objects are the label values. The labels "numx" and "numy" sets the number of objects in the x direction and how many in the y direction. For example a 3x3 grid on the AGV would set "numx" be 3 and "numy" be 3 xshift yshift zshift AGV 1 .5 .5 Operator .75 .29 1.10 BasicTE 0 0 .85 Elevator, Robot, & Crane: These objects are very similar to the TE's above. You'll follow the same steps above, except on the On Load trigger, choose to just paste custom code in the box. They have slightly different code (due to the different direction/ways of stacking) that you can copy from the model above. However, you will still add the labels to the TE's. You can set them using labels like these: xshift yshift zshift Elevator .7 1 .095 Robot .34 .35 .2 Crane .2 .5 -.25 Forklift: This is the easiest object to change because it is already built into the TE. To change the stacking pattern just add an OnEntry trigger and select Transporter Stacking Method, then just change the values to be what you would like. ASRS: For this one, you can change the stacking method by editing the model tree. The steps to change it are simple but specific: Open the model tree for the object by right clicking and selecting Explore Tree Find the behaviour node beneath the ASRS Node Add an node underneath called "eventfunctions" Beneath the node you just created add a node called "OnPreDraw" Paste in that node the code below (you can edit this to alter the stacking method how you would like): inheritcode(); TaskExecuter current = c; Object followingObj = first(current); double numx = 1; double numy = 4; double xshift = .95; double yshift = 1.45; double zshift = .1; while(objectexists(followingObj)){ double x = xshift+followingObj.size.x*((followingObj.rank-1)%numx); double y = -yshift+yloc(node(">visual/drawsurrogate/Lift/Slide", current))+followingObj.size.y*(Math.floor(((followingObj.rank-1)/numx)%numy) - (numy-1)/2); double z = zshift+followingObj.size.z*Math.floor((followingObj.rank-1)/numx/numy); double xFactor = 0.5; double yFactor = 0.5; double zFactor = 0; setloc(followingObj, x, y, z, xFactor, yFactor, zFactor); followingObj = next(followingObj); } Some things to keep in mind: Each TE is completely customizable by the user so the offset I considered to look right may not look right to you, the good thing is it's very changeable!
View full article
FlexSim 2017 Update 2 is available. If you have bug reports or other feedback on the software, please email dev@flexsim.com or create a new idea in the Development space. Release Notes Reorganized the User Manual and updated its formatting. Added more topics, tutorials, and reference pages to the User Manual. Added new Statistics Collector and Calculated Table tools. Added new generic charts for plotting statistics gathered with Statistics Collectors and Calculated Tables. Updated the pin to dashboard buttons to create and use Statistics Collectors instead of the legacy charts. Added a Variant constructor and assignment operator to Vec3 and Color classes. Added functionality for copying dashboard charts as images, and pasting images into dashboards. Added new interfaces to FlexScript, such as Math, Group, and DateTime. Added toNum() and fromNum() methods to the string class. Added a setState() method to the Object class that will work correctly with listening to state changes. Improved handling of read-only model files. Keyboard shortcuts (Ctrl+PageUp and Ctrl+PageDown) and additional enhancements for switching tabs. Added the ability to have null values in a bundle. Added the ability to make kinematics exclude incline rotation when managing rotations. Improved the parenthesis and quote autocomplete functionality. Added autocomplete for curly and square brackets. Added a new print() command to write to the output console more easily. Added support for instanced meshes. Updated the animation system so a single shape can have multiple animators from different shape files. Changed the assimp 3D importer so that it can extract and load embedded textures. Added support for using specular maps and gloss maps. Added support for FlexScript dot syntax in SQL queries. Added the capability to specify a warmup time in the interactive model run. Added options for following objects with the view. Improved MTBF/MTTR state listening to use less events and be more precise. Updated the Network Navigator to work for an object that is inside a container that is connected to the network. Fixed a bug with global variable highlighting and autocomplete. Fixed an issue with destroying a TE on a network when it blocks space on the network. Included fixes listed in 17.1.5. Backwards Compatibility Note: the following changes may slightly change the way updated models behave. Fixed a bug with min() and max() when using distribution functions. Previously, getting the number of columns in a Global Table using Table.numCols or gettablecols() returned 0 when the number of rows was 0. Column headers and data types are preserved even when there is no row data. These commands now return the number of columns. Changed operators to not change their incline rotation when traveling on inclines. This will change location calculations if you have advanced logic based on internal operator locations. NodeListArrays like Object.outObjects can no longer be implicitly cast to an Array. Use the toArray() method instead. Fixed a bug with animations drawing their first frame instead of their last frame at times beyond the endtime. Added a special rule for ambient color {0, 0, 0} to not use the ambient color. This change will make shapes with ambient {0,0,0} to appear brighter. Change the ambient color to a dark gray, such as {1,1,1} if you want them to remain dark. Fixed a bug in the shader that dulled specular highlights with the diffuse texture. This may change how shapes look; they may appear shinier now. Added the IS NULL and IS NOT NULL clauses to SQL. Math and comparison operators on null values now return NULL. FlexSim's SQL execution engine is now more in line with the SQL ANSI standard regarding null values. Specifically, if you do comparisons or math operations on elements that have null values, this will return null values. This is different than in FlexScript, where a null value acts like 0 in math operations. Also, null values will be ignored in aggregation functions like AVG(). An option to use legacy SQL nulls was added to Model Settings to preserve backwards compatibility. Upgraded models will automatically enable this option, but new models will default to using the SQL ANSI standard for nulls. Added support for more SQL query operators, such as the case-when-then-else-end operator and window functions. This adds many new keywords to SQL, meaning that if you used these as column names in older queries, they will create syntax errors in the query parser in this version. To fix this, put square brackets [] around the column name. Changed accessing dynamic label properties to use evaluate() instead of value. For example, consider the following code sample: Variant value = current.MyLabel; In 17.1 and previous, this code was the same as: Variant value = current.labels["MyLabel"].value; In 17.2 we changed it so that this code is now the same as: Variant value = current.labels["MyLabel"].evaluate(); The difference is in how FlexScript-toggled node values are retrieved. In 17.1 and previous, current.MyLabel would have just given the text that is the FlexScript code. In 17.2, retrieving current.MyLabel will actually evaluate the FlexScript as code. This is consistent with how table values are accessed. If you have old code that explicitly tried to get the code text with current.MyLabel, you will need to update that code in 17.2 to use current.labels["MyLabel"].value. Process Flow Added a Material Consumption and Replenishment template. Added functionality for pasting images into Process Flow views. Conveyor Added a Gap-Optimizing Merge Controller Process Flow template. Added instanced rendering to improve Render Mode performance. Changed Render Mode to be enabled by default. Added new visual options for conveyors. Improved run speed performance of the Conveyor Module. AGV Added unload-to-empty capability to the AGV Process Flow template. AStar Added a bridge element to the AStar network. Added functionality for collision avoidance. Improved heat maps for analyzing AStar traffic. Backwards Compatibility Note: the following changes may slightly change the way updated models behave. Changed the path finding algorithm for the AStar navigator. When you tell an AStar traveler to travel to an object, now it will behave more like the default navigator. It will calculate a "threshold radius" around the object, based on the object's size. Then it will only travel to the edge of that radius. This makes it work better especially for loading/unloading to/from rack objects. The travel operation won't commit as much to traveling to the center of the object,because that can be left to the load/unload operation, which determines exactly where in the rack to pick/place the item. However, this change does affect how older models work because it changes the routes that travelers take.
View full article
In version 2018 and forward, you can make this chart using a Chart Template. You can simply drag and drop the chart from the dashboard library. This article may help you understand how the chart template works. You can use the Install button on the chart template to view the Process Flow, Statistics Collector, and Calculated Table that make the chart. This article reviews how to use the Zone, along with the Statistics Collector, to create a bar chart of the current work-in-progress (WIP) by item type. The method scales to as many types as you need (this example uses 30 types), and can easily adapted to text data, like SKU. An example model ( zonecontentdemo.fsm) demonstrates this method. Creating the Process Flow To create this chart, we first need to gather the data for this chart. In this case, it is easiest to build off the capabilities of the Zone. In particular, we will use Zone Partitions to categorize all of our object. After we set up the Zone, we'll use a Statistics Collector to gather the data that we need. Create a new General Process Flow. You can have as many General Process Flow objects as you want, so let's one that just deals with gathering statistics. This way, gathering statistics will not interfere with the logic in our model. The process flow should look something like this: Here's how it works. The Listen to Entry is configured to listen to a group of objects. In this case, the group contains all the sources in the model, and it's listening to the OnExit of the sources. However, it could be OnEntry or OnExit of any group of 3D objects. If you want to split the statistics by Type or SKU, then any flowitem that reaches the entry group already has the appropriate labels. In this example model, when a flowitem leaves any source, a token gets created. The token makes a label called Item that stores a reference to the created item, as shown in the following picture. The next step is to link the flowitem with the token that represents it. The Link Token to Item is configured like this: Now, the Item has a label that links back to the token. The token then enters a zone. The Zone is partitioned by type: At last, the token comes to a decide activity. The decide is configured not to release the token. The token will be released by the second part of the flow. Once the token is released, it exits the zone, and goes to a sink. The second part of the flow also has an event-triggered source, that is configured to listen to all the sinks in the model. Again, the entry objects and exit objects are arbitrary; you can gather data for the entire model, or for just a small section of the model, using this method. The event triggered source also caches off the item in a label. At this point, we need to release the token that was created when items entered the system. To do this, the Release Token activity is configured as seen here: The token created on the exit side has a reference to the item, which has a reference back to the token created on the entry side. We release this token to 1, which means connector 1. Note: We could have used a wait for event activity in the zone, and then used the match label option to wait for the correct item to leave the system. However, this method is much, much faster, especially as the number of tokens grows. Creating the Bar Chart Statistics Collector The next step is to create a statistics collector that gathers data appropriate for a bar chart. Note that this method will grow the number of rows dynamically, so that it won't matter how many types (or SKUs) your model has; you will still get one bar per type/SKU. In order to make the number of rows dynamic, we need to listen to the OnEntry and the OnExit of the zone activity: Notice the shared label on this collector. Because this label is shared, both the OnEntry and OnExit events will create this label on the data object. The value of this label is the item's type. Next, we move to the Data Recording tab. Set the Row Mode to Unique Row Values, and set the row value to Partition. This means that whenever an event fires, the statistics collector will look at the partition label on the data object. If the value is new to the statistics collector, the collector will make a new row for this value. If not, then the collector will use the row that is already present. Finally, we need to make our columns. We only need two columns: one for the Partition, and one for the Content of that partition. Both of these columns can use the Integer storage type, and raw display format. However, if your partition value was text-based, like an SKU, you should use the String storage type. The value for Partition is just the data object's Partition label: Notice that the Update option is set to When Row is Added. This way, the statistics collector knows that this value will not change, and that it's available at the time the row is created. The other column is a little harder, because we need to use the getstat command: The getstat command arguments depend on the stat you are trying to get. In this case, we are asking the zone (current, the event node) for the Partition Content statistic. We want the current value. Since this is a process flow activity, we pass in the instance as the next argument. Finally, we pass in which partition we want to get the data from, the row value. In this case, we could have identically passed in data.Partition. Also, notice that this column is updated by event dependency. To make sure this does what we want, we need to edit the event/column dependency table. We want the Content column to be updated when items enter and exit, so it should look like this: Now, open the table for the statistics collector. You should see two columns. When you run the model, rows will be added as items of different types are encountered. The table will look something like this: This screenshot came from early in the model, before all 30 types of item has been encountered, so it doesn't have 30 rows yet. Making the Bar Chart This is the easiest part. Create a new dashboard, and add a new bar chart. Point the chart at the statistics collector. For the Bar Title option, choose the Partition column. Be sure to include the Content column. Also, make sure that the "Show Percentages" checkbox on the Settings tab is cleared. The settings should look like this: The resulting chart looks something like the following image. You can set the color on the Colors tab. Ordering the Data Because the rows of this table are created dynamically, the order of the rows will likely change run to run. To force an ordering, you can use a calculated table. Since the number of rows on this table don't grow indefinitely, and the number is relatively small, it's okay to set the Update Mode on the calculated Table to always. Here's what the properties of that calculated table look like: We simply select all columns from the target collector (CurrentContent, in this case) and order it by the Partition column. That yields an ordered bar chart: Example and Additional Charts The attached example model demonstrates this method, as well as how to create a WIP By Type vs Time chart: Happy data collecting! zonecontentdemo.fsm
View full article
This article demonstrates how to use the Statistics Collector and Calculated Tables to create three utilization pie charts: a state pie chart an individual utilization pie chart a group utilization pie chart Example Model You can download that model (utilizationdemo.fsm) to see the working demonstration. The model has a Source, a Processor, a Sink, a Dispatcher, and several operators. The operators carry flow items to and from the processor, as well as operate the processor. The operators are in a group called Operators. State Pie Chart First, we need to make a Statistics Collector that collects state data for the operators. The easiest way to do that is to use the pin button to pin the State statistic for any object in the model. Use the pin button to pin a pie chart to a new dashboard. The pin button creates a new Statistics Collector, as well as a new chart. Open the properties for new Statistics Collector (double click on it in the toolbox), and change its name to OperatorStatePie. On the Data Recording tab, remove the object from the Enumerated Rows table. Using the sampler, add the Operators group (you can sample it in the toolbox). Now, when you reset and run the model, the state chart should work. Utilization Pie Chart Often, users need to combine sever states into a single value that can be used to determine the utilization of an object in the model. In order to gather this data, we can use a calculated table. Make a new Calculated Table, and give it the following query: SELECT Object, (TravelEmpty + TravelLoaded + Utilize) / Model.statisticalTime AS Busy, 1 - Busy AS NotBusy FROM OperatorStatePie This query sums the time in several states into a total, and then divides by the statistical time. Be sure to set the name of the table (the part after FROM) to the name of your Statistics Collector. Run the model for a little bit of time, and then click the Update button on the properties window. You should get a table like the following: Instead of viewing the data as just numbers, change the Display Format of each column to better represent the data. On the Display Format tab, set the Object column to display Object data. Then set the other two columns to display percentages. When you switch back to the Calculations tab, the data will be formatted: Once we get the query right, set the update mode to Always. This will updated the data in the table whenever the data is needed, including every time the chart draws. If updating the table is computationally expensive, you can use the By Interval or Manual options. Generally, a small number of rows (1-100) is small enough to use the Always mode. Regardless of the update mode, we can make a chart based on this table. In the dashboard, create a new Pie Chart. For the Data Source, select the calculated table. For the Pie Title, select the Object column. For the Center Data, select the Busy column. Be sure to include the Busy and NotBusy columns. This should show you a pie chart, comparing the operator's busy and not busy time. Group Utilization To make the final utilization chart, make a second calculated table. The query for the second table should be as follows: SELECT AVG(Busy) AS AvgBusy, AVG(NotBusy) AS AvgNotBusy FROM CalculatedTable1 Again, use the Update button to be sure the query is correct. Once it is, set the update mode to Always. Finally, you can make the pie chart for this data: Things to Try If you feel comfortable with this model, you can try a couple extra tasks, such as: Remove one of the operators from the group, reset, and run. The charts will update accordingly. Add the Processor to the group, reset, and run. The state chart should work automatically.
View full article
A narrated video demonstration of the FlexSim Healthcare Tutorial described in the FlexSim 2020 User Manual has been released! Here is a link to the written documentation: https://docs.flexsim.com/en/20.0/Tutorials/FlexSimHC/OverviewFlexSimHC/ Here's a link to the video: https://vimeo.com/394012280
View full article
FlexSim 2019 Update 1 is available. If you have bug reports or other feedback on the software, please email dev@flexsim.com or create a new idea in the Development space. Release Notes Added a new graphical interface to the Calculated Table for building queries. Updated the UI for editing rack dimensions. Added more options for customizing people visuals. Moved operator shape options from the Operator tab to Quick Properties. Improved edit modes by using right-click to cancel the current action instead of immediately exiting the mode. Added global preferences for process flow and dashboard library options. Added the FlexScript API reference to the user manual and made it accessible outside of FlexSim. Added toolbar support for adding multiple model background drawings. Adjusted how the floor Z and grid Z settings work to improve multi-floor modeling. Updated the table view to show more helpful information for certain data types. Added support for pointer data in bundles. Added a pointer type to tracked variables. Added support for the NULLIF SQL keyword. Added support for linking combo boxes to nodes with pointer data. Improved the gantt chart. Updated how tree files are saved to improve saving certain datatypes. Updated pulling from lists to throw an exception when passing a bad query. Fixed a bug with the normal map lighting calculation. Fixed an issue with the picking focus when using drawsurrogate within a drawsurrogate object. Fixed exceptions on an array table that doesn't have column header information. Fixed an issue related to moving items that had not been released. Backwards Compatibility Note: the following changes may slightly change the way updated models behave. Updated the internal structure of the Rack object's variables. Removed the rackgetcontenttable() command. Removed support for running the simulation from a loaded state file. Process Flow Added an option to the container to center its title when the contents are hidden. Added a limit to the number of activity panels displayed in quick properties. Added a Milestone activity. People Added a Healthcare environment option. Added an Elevator Bank object. Added a Prop object and more options for object visuals. Added tables that automatically collect statistics for people models. Added people chart templates. Added a People Settings object to the toolbox for people models. Improved the names of people created with the Create Person activity. AGV Updated the distancetotravel() calculation to work with moving AGVs. A* Added support for multiple grids. Adjusted how conditions are defined to improve performance.
View full article
We have released a beta version of our Emulation module. The Emulation module adds a tool that enables communication between FlexSim and OPC / Modbus Servers and PLCs. Help files are included in the FlexSim User Manual to assist you. This beta version must be installed with FlexSim 2017 Update 1. 32-bit and 64-bit installers can be downloaded through the downloads section in the Modules tab of the FlexSim website: FlexSim Downloads The following are known issues: Asynchronous Write for OPC Connections is not working. The option has been disabled. Please post any feedback or bug reports either as a comment to this article or you can email them to dev@flexsim.com
View full article
In a recent model I was building I needed a case packer that had some special abilities. This "Combiner" is different than a traditional library accessed Combiner because: 1) You can set how many containers can be packed at a time. (In my model 3 cases were packed simultaneously with each cycle. I call these "batches" in my logic. This variable is accessed as a label on the 3D object. 2) It assumes that all the flowitems being packed come from the same port, you can't have multiple sources of flowitems or have a recipe. Although it could be modified to allow for that. 3) It is very easy to set home many flowitems per container. This variable is accessed as a label on the 3D object. This could be changed easily as the itemtype or some other criteria changes while running the model. 4) If the flow of containers or flowitems is delayed, the machine can time out and release a partial batch or partially filled container. I have included a model control GUI so you can manually stop the sources and test this logic. Note the labels associated with max wait time in the object labels again. 5) After a batch of containers and flowitems has been collected, there is a RobotCycleTime that occurs that represents the moving of the flowitems into the containers, this time is ran one time for the entire batch. While this object may not be the final solution for a lot of instances, I believe that it is a good starting point for a lot of objects that will be needed in future models. The Process Flow is well documented to explain the logic. Note that this is an Object Process Flow and all instances will need to be connected to the logic in the process flow. CustomCasePacker.fsm 0
View full article
This supply chain demonstration model shows both a visual and statistical representation of a company's stock and backorder from day-to-day. The goal of the model was to predict shortages and backorder trends due to COVID-related disruptions. FlexSim's 3D view is used in a novel way to visualize the current stock and demand for each product. Each queue represents a different product SKU and each box represents a product unit, with red indicating product demand and blue indicating product availability. This model also contains a comprehensive set of dashboards to help visualize and interpret the data. Logistics_Supply-Shortages-Stockouts_v22-2.fsm
View full article
FlexSim 2020 Beta is available. (Updated 26 November 2019.) To get the beta, log in to your account at www.flexsim.com, then go to the Downloads section, and click on More Versions. It will be at the top of the list. If you have bug reports or other feedback on the software, please email dev@flexsim.com or create a new idea in the Development space. Release Notes Changed models to automatically open the environment in which they were saved. Added boy and girl shapes to people visuals. Improved keyboard interactions within table views. Improved tabbing between fields in certain windows. Updated the 3D names and stats text rendering to support more fonts and Unicode. Improved the 3D view's lighting capabilities by adding Light objects that can be arranged in the model. Improved lighting in RTX Mode, including support for soft shadows and a denoiser. Adjusted the Rack Dimensions tab to be able to specify slot padding. Added an optional parameter to TaskSequence.create() for waiting until TaskSequence.finish(). Added an OnValuePulled event to the List. Added methods for creating a DateTime using a string or component parts. Added support for in-place addition and subtraction of DateTimes. Fixed bugs with DateTime methods when using certain years or ranges of time. Improved the convert() command's capabilities with converting dates and times. Improved the exporting of null bundle values to Excel. Added an excelcreateworkbook() command. Added statistics collectors and calculated tables to the Excel Export. Added an option for creating sheets using the Excel Export. Fixed rotation issues with pasting certain objects. Added a Vec3.projectRotation() method. Added a Vec2 FlexScript class. Changed the License Activation window to be responsive during licensing operations. Added an index type to statistics collector columns for improving performance. Added a categorical combo type to tracked variables. Updated the query builder to handle CASE statements. Simplified certain queries written by the query builder. Changed the tree structure to simplify creating custom webserver interfaces. Added a repeat type to animations for remaining in the last frame after running the animation. Added a Go To Row/Column option in quick properties for tables. Improved time plots to be able to show durations as well as calendar times. Added an optional wire mesh rack visualization. Added more picklist options to the storage object slot assignment strategy. Updated the animator so that keyframes are updated using a right-click menu option instead of automatically. Added an option to duplicate an animation keyframe into another animation. Changed the default network node speed limit to 0 (no speed limit). Reorganized the Use Transport pick list and added a No Transport Reference option. Fixed a bug with the rack's default pull requirement not reevaluating after becoming full. Fixed an issue with copy/pasting sub-locations. Fixed the dark patterns when zooming out in RTX Mode. Fixed a crash on certain hardware in RTX Mode when rendering too many transparent layers. Improved the Time Table Date Based GUI to draw past the last event and allow scrolling into the future. Added PushWheelchair and PushCart animations to Operators Backwards Compatibility Note: the following changes may slightly change the way updated models behave. Time tables now combine consecutive down periods if using the same state and profile or the same down behavior. Fixed issues with pick/place offsets on drive in racks to improve usability with A*. Because of performance improvements to query(), the row order is not guaranteed unless using an ORDER BY statement. Fixed excelrangewrite() so that the correct overload is available in FlexScript. Improved the FlexScript hypertext preprocessor scoping mechanism used by the webserver. Fixed object color being applied incorrectly to ambient material color on certain meshes. Changed point source light attenuation. Changed TASKTYPE_NODEFUNCTION to pass variants in as parameters instead of interpreted legacy doubles. This fixes the types of arguments that are passed when calling treenode.evaluate() as part of a TASKTYPE_NODEFUNCTION task. This allows you to add TASKTYPE_NODEFUNCTION tasks with parameters that are not just numbers, (nodes, strings, arrays, etc.) and have those parameters be preserved in a type-safe manner and properly passed into the subsequent treenode.evaluate() call. However, this change may have some consequences for older models. The following guidelines apply: If you use the inserttask() command, and cast a node to a number with tonum() to pass it in as a task variable, then you should use parnode() to get those parameters out in the nodefunction. While this method will continue to work, this mechanism is nevertheless deprecated. The now-correct method for adding a TASKTYPE_NODEFUNCTION task to a task sequence is to use TaskSequence.addTask(). This method takes full Variants as its task variable parameters, so you do not need to use tonum(). When using this, you should use param() to get the parameters back out. Older models that use neither of these methods may need to be updated to use method 2 in order to work properly in this version. Process Flow Changed the default behavior of the Create Task Sequence activity to work easier with task sequences created outside of Process Flow. Added a Finish Task Sequence activity that works with the new Create Task Sequence features. Changed the default value of Task activities from token.resource to token.taskSequence. Improved the interface for connecting activities. Added a mechanism for connecting to and from containers and routing tokens between activities using those connections. Added an option to the Run Sub Flow activity to run tokens one at a time. Adjusted the size of containers and connections based on the zoom level when created. Removed the width attributes of themes. Improved the UI for entering times in the Date Time Source activity. Change Set Color By Case and Set Object Color pick options to enable setting the color of a token. Fixed the display of task parameters in the event log. People Improved people resource shared assets to be able to reference other people resources. Added Sort By and Filter By fields to people resources. Simplified and improved several activity sets. Improved the list of labels in drop-down menus to include People Settings labels. Added a Kiosk to the list of locations. Added an Observation Room multilocation. Added an option to the Toolbox to add all people tables to the Excel Export. Added more people tables and charts. Improved the performance of many existing people tables and charts. Updated preempted resources to be able to be reacquired with a higher priority. Updated Escort Patient and Tranpsort Patient activities to set the staff's TravelingWithPatient label when escorting or transporting a patient. Improved the query builder interface with support for adding group/individual subsets. Changed people acquire activities to have the default max wait timer trigger release the token out connector 2. Changed the Split activity default to creating child tokens in the Healthcare environment. Changed the repeat type of the LayDown and SitDown/SitDown2 animations to repeat the last frame. Backwards Compatibility Note: the following changes may slightly change the way updated models behave. Changed how labels are handled by People Settings. Improved animations and positioning of transports and equipment when staff move them. Emulation Added support for OPC UA connections.
View full article
Update (22 December 2017): Version 18.0.1 now again allows you to double click in Process Flow to open the activities popup. FloWorks 18.0.0 is now available (18 December 2017). This version of FloWorks is intended for use with FlexSim 2018. In addition, FloWorks 17.2.2 and 17.0.7 have been released, containing bug fixes for FlexSim 2017 Update 2 and FlexSim 2017 (LTS) users, respectively. These will be the final 17.x releases of FloWorks. All versions can be found in the Downloads section of your FlexSim account on the 3rd party modules tab. Please do not hesitate to report any bugs, usability improvements and feature requests to support@talumis.com. About FloWorks FloWorks is a 3rd party module developed and maintained by Talumis BV ( talumis.com). It provides faster and more accurate modelling and calculation of fluid systems than the default FlexSim fluid library. It is especially useful within the oil, gas, and bulk industry both for production and supply chain optimization. This module requires a FloWorks license with active maintenance. For any questions, please email support@talumis.com. Release notes Changes in FloWorks 18.0.1 Bug fix: FloWorks broke double click in the Process Flow view to open the quick library Changes in FloWorks 18.0.0 Quick Properties panels added. Added three FloWorks tutorials to user manual. Added impact , stop and resume functions on FlowObject . Added FLOW_STATE_* constants for use in stop and optionally impact . Bug fix: In unlicensed version, license info is now correctly shown instead of “Unknown”. All bug fixes in version 17.2.2 and 17.0.7 listed below. Changes in FloWorks 17.2.2 (for FlexSim 2017 Update 2) Bug fix: FlowTank 's isEmpty and isFull return 0 and 1. Bug fix: Statistics collectors pick up content changes by content property setter. Bug fix: Cannot change mixer recipe while running. All bug fixes in version 17.0.7 listed below. Changes in FloWorks 17.0.7 (for FlexSim 2017 LTS) Bug fix: FloWorks objects remove pending events from the list when they are destroyed. Bug fix: Fixed an issue in the LP solver. Bug fix: Minor fix to internal treenode naming on reset. Bug fix: Avoid a rounding issue in utilization calculation. Bug fix: Mixer correctly resets visuals to empty in manual mode. Bug fix: Can start mixer recipe from Reset or On Empty trigger. Bug fix: Fixed reset error when opening model without flow trucks in a FlexSim installation without FloWorks.
View full article
FloWorks 2018.0.0 will be released in parallel with FlexSim 2018. This new version of FloWorks adds two features that have been sitting on our wish list for a while: support for Quick Properties and a brand new set of tutorials. Therefore we are releasing it as a public beta. The latest beta version, released December 8, can be found in the Downloads section of your FlexSim account on the 3rd party modules tab. Click "More Versions" to show the Beta release. Along with FloWorks 18.0.0, we will provide a final bug fix release for versions 17.2 and 17.0, with the changes listed below. Please do not hesitate to report any bugs, usability improvements and feature requests to support@talumis.com. About FloWorks FloWorks is a 3rd party module developed and maintained by Talumis BV ( talumis.com). It provides faster and more accurate modelling and calculation of fluid systems than the default FlexSim fluid library. It is especially useful within the oil, gas, and bulk industry both for production and supply chain optimization. This module requires a FloWorks license with active maintenance. For any questions, please email support@talumis.com. Release notes Note: the bug fixes will also be available in versions 17.2.2 and 17.0.7, where applicable. New features in FloWorks 18.0.0 Quick Properties panels added. Added three FloWorks tutorials to user manual. Bug fixes in FloWorks 18.0.0 and 17.2.2 Bug fix: Fixed an issue in the LP solver Bug fix: Minor fix to internal treenode naming on reset Bug fix: FlowTank.isEmpty and FlowTank.isFull return 0 and 1 Bug fix: Avoid a rounding issue in utilization calculation Bug fix: Statistics collectors pick up content changes by content property setter Bug fix: Cannot change mixer recipe while running Bug fixes in FloWorks 18.0.0, 17.2.2 and 17.0.7 (LTS): Bug fix: FloWorks objects remove pending events from the list when they are destroyed. Bug fix: Fixed an issue in the LP solver Bug fix: Minor fix to internal treenode naming on reset Bug fix: Avoid another rounding issue in utilization calculation Bug fix: Mixer correctly resets visuals to empty in manual mode. Bug fix: Can start mixer recipe from Reset or On Empty trigger.
View full article
We are excited to announce the release of version 25.2 of the Autodesk Interop Module for FlexSim, designed to enhance the connection between Factory Design Utilities (FDU), Vault, and FlexSim.
View full article
FlexSim 2024 Update 2 is now available for download. You can view the Release Notes in the online user manual. FlexSim 24.2.0 Release Notes For more in-depth discussion of the new features, check out the official software release page: FlexSim 2024 Update 2: Curve Fitter, Process Flow Breakpoints, and more If you have bug reports or other feedback on the software, please create a new idea in the Bug Report space or Development space.
View full article
Cycle time per process.fsm When we create simulation models, sometimes we limit ourselves to modeling a process or a part number, in which we have problems. But what happens when we run a complete production plan with different part numbers, which in turn run at different cycle times? This is a way that allows you to run different part numbers in as many different processes as you want, each with its own cycle time. What do we need? 1.- Label on each item that identifies what part number it is. For example • Label: IDpart Value: ABC12 2.-Label on each machine that identifies the process that it runs. For example • Label: Station Value: Processor1 3.- Global table that contains in the columns the different processes that you have in your production line and in the rows the different part numbers that can run in your line. The information contained in this table will refer to the cycle times of each part number in each process. For example: Processor1 Processor2 Processor3 ABC12 20 10 13 BAC21 11 30 20 4.-You must configure the processing time of your processor referring to your global table and placing the following: With this, we will obtain weighted usage statistics for the equipment. Benefits: 1. You can run different part numbers on the same line with their respective cycle time each. 2. More accurate use of equipment and operators. 3. Modifying cycle times in a global table is easier and more controlled than directly in the processes. 4. Calculation of the capacity of your line running a real production plan will be accurate. 5. You can add and remove processes or even modify the flow of your line without affecting the cycle time that processor runs. Since it is referenced by its label to the global table.
View full article
This example model was created to clarify pre-emption of task sequences created in process flows. Specifically it will show: 1) that pre-empting of task sequences generated in a process flow does not require the token generating the sequence to be pre-empted. 2) that you can push a partially created sequence to a tasksequence list type. 3) how to use recursive calls to a sub flow. and afterwards: 4) how the milestone task can be used in a PF generated task sequence 5) the use a task type nodefunction Each queue is a member of the object process flow shown in the picture. Each generates a box along with a job to take it to another queue and pulls an initial task executer from the list of FreeTEs. The first task to travel and collect the box is preemptable and so we push the task sequence to a Premptable Job list before we add that travel task and pull it off the list when the task has completed. The rest of the task sequence is a standard load, travel and unload set of tasks. When the job is complete we know that the TE is free and could preempt another TE - which could be desired if the newly free TE is closer to the pickup queue than the one currently assigned. The CheckPreempt subflow is called with a label referencing the TE that has become free. This TE may not be the original TE that we pulled from the list of FreeTEs when the job was started, and so we discover the current TE by looking for the task sequence's owner object - done with the function findownerobject() since it does not cache the value in the same way ownerobject() does, and we could have had more than two TEs assigned to this tasksequence. Since the task sequence gets destroy I do this in the assign labels activity before we finish the ts: The Check Preempt subtask first tries to pull a preemptable job where the invoking TE is closer than the current executer of that job, and chooses the one where it is the most pronounced difference. The taskssequence list type has the distance field prepopulated and from that the two other field expressions otherDistance and howMuchCloser are derived. If no task sequence is chosen then we push the finishing TE to the FreeTEs list. If we choose a task sequence to preempt then we first label the token with the otherTE and the preempt the task sequence with a simple zero delay task. The we reDispatch the task sequence to the te that is calling Check Preempt. Since we now know that we've freed the otherTE from the task sequence it had we can invoke the Check Preempt subflow for that task executer, knowing that it will either get put onto the FreeTE list or get another task sequence and preempt another TE. This the is a recursive subflow call with the exit condition being that no preempatable tasksequence is found. Note that no token preemption from activities takes place and this is because the tasksequence is still tied to the token and its activity, which will still receive the call back when a task is complete, regardless of which task executer actioned the task. TEpreemptIfCloser1.fsm Next: Changing colors to indicate preemptable TEs and their destination - using milestone and nodefunction tasks. To better see the allocation and preempt activities we'll now change the model such that the TE color reflects the following: White when idle Gray when busy and not preemptable Matching the pickup queue's color when preemptable. First of all I defined two user commands - one to set the color of the TE (setTEcolor) and another (commandNode) to get the executable node of a user commands. This is so that I can add the fn() SetColor activity (it's a custom task of type nodefunction) ; specify the function using: commandNode("setTEcolor") and pass in the queue color as parameter 2 (parameter1 will be the TE that is executing this task). This means the user command code is just: Object te=param(1); Color col=param(2); te.color=col; The milestone task allows us to define a set of tasks that need to be repeat if the TE gets pre-empted. It's added again using the Custom Task activity and selecting the type as Milestone and has a parameter to specify the number of subsequent tasks that should be considered within the preemption range that will trigger tasks to be repeated. Since we want the Travel preemption to retrigger the setting of the color we set the range to 2. However since the token only needs to be notified when the travel task is complete that it should go on to the next process, and until then wait in the travel task we can uncheck the "Wait Until Complete" box of the Milestone and fn() SetColor activities: If you don't clear this for those two tasks we expect some misbehavior/desynchonization with the token. Finally there needs to be a resettrigger on the TE to set the color to white and a regular Change Visual activity after the pickup point is reached to set it to gray. Note I prefer the use of commands to sending messages, which would be another option, mostly because users can tell the intent of the call without having to inspect the message code. TEpreemptifCloser2.fsm
View full article
This article is basically a follow-up to this question: https://answers.flexsim.com/questions/98195/simultaneous-all-or-nothing-list-pulls.html In version 22.1, we added a new FlexScript feature called Coroutines. Basically, this lets you wait for events in the middle of executing FlexScript, using the "await" keyword. Recently, I decided to revisit this question (how to pull from multiple lists at once) and to see if I could use coroutines to simplify the Process Flow. The short answer is: yes! Here is a model that behaves identically (in terms of which token gets its multi-list request filled first) but replaces about 15 activities with 2 Custom Code blocks: multipullexample_coroutines_ordering_onfulfill.fsm In addition to having fewer activities, this model also runs faster (from ~12s to ~2s on my computer). To determine whether behavior was the same, I added a Statistics Collector and logged request/fullfill times and quantities. I did the same in the original model. The token IDs are off because the older model makes more tokens. Here's the older version, but with that stats collector, if you want to do your own comparisons. multipullexample.fsm The key lines of code are found in the Acquire All activity: // ~line 47 List.PullResult result = list.pull("", qty, qty, token, partition, flags); if (result.backOrder) { token.Success = 0; await result.backOrder; return 0; } // ... The new item here is the keyword "await". When the FlexScript execution reaches this line, the FlexScript execution is paused, and waits for the "awaitable" that you specify. In this case, we want to wait for the back order to be fulfilled. In both models, tokens check all lists to see if they can acquire the complete set of resources. In both models, if a token can't immediately fulfill one of its requests, tokens "go to sleep" until something changes. In the old model, tokens would "wake up" if anything was pushed to the correct list. In contrast, tokens in the new model only "wake up" if enough items are pushed to fulfill their back order. Basically, the second model has fewer false "wakeups" and so runs quite a bit faster.
View full article
This model contains example subflows for having a team of travellers travelling and loading/unloading. The RunSubflow for each creates that subflow's expected labels: team, teamItem, teamDesintation. Currently the offset locations are just a multiple of the x size of the first traveller. They are determined from the pick offset and place offset functions. Further work could add traveller un/loading and wait states and combine travel and unload tasks. TeamSubflows.fsl TeamSubflows.fsm Update 24Oct.'24 : Corrected incorrect label name in TeamTravel subflow should be looking for 'team', not 'travellers'
View full article
Note: the demo models were created specifically for the FlexSim user community who speak spanish, and all the explanations, statistics, and documentation available in the dashboard, GUIs, and Model Documentation are in Spanish. Nonetheless, given that 3D animation is a universal language, you are welcome to download these models regardless of the language you speak. Manipulación de material / Material handling Demo_Crossdocking.fsm En este modelo, llegan tres tipos de productos a dos zona de recepción. Un primer grupo de operarios se encarga de transportarlos a una zona de almacenamiento intermedio. Desde allí, otro grupo de operarios los clasifica según la ciudad a la que serán despachados. In this model, three types of products arrive at two reception areas. A first group of operators transports them to an intermediate storage area, where another group of workers sorts them according to the city they will be delivered to. Preparación de pedidos / Picking Demo_Picking.fsm En este modelo, los pedidos llegan de manera aleatoria a lo largo del día y son revisados y preparados por un operario. En este modelo, se puede modificar si los operarios realizan la preparación a pie o utilizando un vehículo, así como la ubicación del almacén de estibas y el número de operarios asignados. In this model, orders arrive randomly throughout the day, which are reviewed and prepared by an operator. In this model, you can change whether the operator does the picking on foot or using a vehicle, the location of the pallet zone, and the number of assigned operators. AGV - Vehículos de guiado automático Demo_AGV.fsm Este modelo demuestra la aplicación del módulo de AGVs de FlexSim, que permite simular sistemas que utilizan AGVs para el transporte automatizado de material. En este modelo, un AGV con capacidad para cinco productos se encarga de transportarlos entre dos zonas dentro de un proceso. This model demonstrates the application of the AGV module in FlexSim, which allows simulating systems that use AGVs for auomated material handling. In this model, an AGV with a capacity of five productos is responsible for transporting them between two zones within a process. Preparación de kits / Kitting Demo_Kitting.fsm Este modelo representa un proceso productivo que utiliza la técnica de preparación de pedidos. Mediante parámetros, es posible activar o desactivar estaciones de trabajo para evaluar el impacto en la productividad del proceso. This model represents a kitting process. Through parameters, it is possible to activate or deactivate workstations to evaluate the change in throughput statistics. Centro de vacunación / Vaccination center Demo_HC.fsm En este modelo se representan un sistema de atención de pacientes en un centro de vacunación. Los pacientes llegan de forma aleatoria, se registran y esperan hasta que una enfermera los vacune. This model represents a patient care system in a vaccination center. Patients arrive randomly, complete a registration process, and wait until they are vaccinated by a nurse. Cajero automático / ATM Demo_ATM.fsm En este modelo, se representan un sistema de retiro de dinero en cajeros automáticos (ATMs). Los usuarios llegan de forma aleatoria y realizan un retiro si hay un cajero disponible; de lo contrario ,esperan en la fila. This model represents a cash withdrawal system at ATMs. Users arrive randomly and proceed with a withdrawal if a cash machine is available; otherwise, they wait in line. Fluidos / Fluid Library Demo_Fluidos.fsm Este modelo representa un sistema de embotellado. Se generan, mezclan, procesan y finalmente embotellan dos tipos de fluidos. Después de embotellados, un operario los transporta a la zona de empaque. This model represents a bottling system. Two types of fluids are generated, mixed, processed, and finally bottled. After bottling, they are transported to the packaging area by an operator. Navegador GIS / GIS Navigator Demo_GIS.fsm Este modelo muestra cómo se utiliza el módulo GIS de FlexSim para determinar la ubicación óptima de un nuevo almacén, teniendo en cuenta una red de distribución específica. This model demonstrates how the GIS module of FlexSim is used to determined the optimal location for a new warehouse, considering a specific distribution network.
View full article
Top Contributors