FlexSim Knowledge Base
Announcements, articles, and guides to help you take your simulations to the next level.
Sort by:
Preparation   You will need to be able to transfer plaintext XML license files to and from your offline computer.   Create manual return requests   Open FlexSim Software. In FlexSim's main menu, Go to Help > License Activation. Click the Advanced tab. Go to the Manual Return sub-tab. Each of your activated licenses is listed in the dropdown selector. Select a license you want to return. Click the Generate Request button. You will be prompted to save an XML file. Choose a location and filename to save your XML return request. Repeat for all licenses you wish to return, so that all your XML return request files can be transferred at one time.   Submit your manual return requests   Transfer your XML return requests to a computer with Internet access. From your Internet-connected computer, open a web browser and login to your FlexSim Account. Click the Licenses link in your FlexSim Account's page header. Click the Manual XML link in the submenu. Upload your XML file by dragging it onto the drop zone, or click the drop zone and browse to your XML file. Your uploaded XML request will be processed. Upon completion, you will be prompted to download the XML response. Download the response XML file. Repeat for any licenses you are manually returning, so that all your XML return response files can be transferred back to your offline PC at one time.   Process your manual return responses   Transfer your downloaded XML return responses to the offline computer you are un-licensing. In FlexSim, using the same licensing interface where you generated your request, click the Process Response button. Browse to an XML return response file. FlexSim should give you an indication of successful processing of your return, and your return will be complete. Repeat to process the XML return responses for any other licenses you are manually returning.   If you have any questions or problems, please search our Answers Community for possible solutions. There is a good chance someone else has already asked your question. Still not finding what you're looking for? Submit a new question and we'll check it out. If you're including any confidential information, such as license codes, be sure to mark your question as private! You can also contact your local FlexSim distributor for live phone, web, or email help.
View full article
Staying up-to-date FlexSim recommends staying up-to-date and using the latest Software version. New features, improvements, and bug fixes make your simulations more stable, more powerful, and easier to build.   In addition, the Software is developed for use with contemporaneous hardware, operating systems, and drivers. Among other reasons, as third parties phase out these technologies, FlexSim must discontinue support for Software versions developed for use with those technologies.   Finally, as usage of older versions decreases, FlexSim must devote its resources to supporting more recent Software versions to best serve the majority of our customers who stay current on Software maintenance and updates.   Lifecycle and Support Policy If you must use an older Software version, understanding the Software Support Lifecycle will help you make informed decisions about when to upgrade.   A Software release is generally supported until it is four (4) or more versions prior to the current release. For the most up-to-date lifecycle and support policy information, please see section 17. Software Support of FlexSim's Software License Agreement.   Lifecycle status terminology Supported - FlexSim will maintain licensing infrastructure necessary for a given Software version and will provide technical support for that version for licensed users under current maintenance or subscription. Bugfixes - Bugfixes are issued periodically for the latest Software version, as needed. A Software version typically receives bugfixes until the next Software feature release. Learn more about FlexSim version numbering and bugfixes. LTS - Long-term support versions receive bugfixes for a longer period, typically 12-15 months. Beta - Preview the next version of FlexSim Software for demonstration, testing, and validation. Beta versions may not be suitable for day-to-day production use. Beta versions are superseded by their production-release version. No support - After a Software version is 4 or more versions older than the latest release it is no longer supported. Such a version may continue to work on the computer where it is installed and licensed, but it is no longer eligible for technical support and FlexSim cannot guarantee that licensing infrastructure will remain in place to move the license key to another computer. Supported Versions The following Software versions are currently supported.    Application   Version   General Availability     Lifecycle Status  FlexSim 25.1 2025-04-14   supported + bugfixes FlexSim 25.0 2024-12-11   supported + LTS FlexSim 24.2 2024-08-05   supported FlexSim 24.1 2024-04-08   supported   Unsupported Versions The following Software versions are past their supported lifecycle. We recommend updating your software to a supported version.    Application   Version   General Availability   End-of-Life   Lifecycle Status  FlexSim 24.0 2024-12-06 2025-04-14 no support FlexSim 23.2 2023-08-07 2024-12-11 no support FlexSim 23.1 2023-04-03 2024-08-05 no support FlexSim 23.0 2022-12-05 2024-04-08 no support FlexSim 22.2 2022-08-02 2024-04-05 no support FlexSim 22.1 2022-04-04 2024-04-05 no support FlexSim 22.0 2021-12-06 2024-04-05 no support FlexSim 21.2 2021-08-09 2024-04-05 no support FlexSim 21.1 2021-04-02 2024-04-02 no support FlexSim 21.0 2020-12-04 2024-03-26 no support FlexSim 20.2 2020-08-11 2024-03-26 no support FlexSim 20.1 2020-04-10 2024-03-26 no support FlexSim 20.0 2019-12-06 2023-12-31 no support FlexSim 17.0 - 19.2 various 2023-12-31 no support FlexSim 7.7 - 16.2 various 2022-06-30 no support HC 5.3 2017-10-13 2022-06-30 no support FlexSim < 7.7 various 2020-12-31 no support HC < 5.3 various 2020-12-31 no support   Notes The date format used is YYYY-MM-DD Bugfix releases follow the same lifecycle as the major release with which they are associated. Versions not listed should be assumed as past their supported lifecycle.
View full article
RailWorks 25.0.1 is now available (19 March 2025). This version of RailWorks is intended for use with FlexSim 2025. 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 developmentbrflexsim@flexsbr.com.br. Rail Network: New feature in RailWorks The Rail Network feature provides users with an intuitive and efficient way to design and connect railway systems. With a user-friendly interface, this tool enables seamless track placement, automatic node linking, and real-time validation to ensure smooth rail operations. Users can quickly define routes, junctions, and stations while leveraging smart snapping and alignment aids to simplify complex track layouts. This feature is designed for both beginners and advanced users, offering powerful tools to build scalable and efficient rail networks with minimal effort. New Speed Table: New feature in RailWorks Offering more speed possibilities to configurate all the movement parameters, the new speed table covers all movement speeds, acceleration and deceleration parameters, making the model more plausible and adherent to the real world process. About Railworks The FlexSim Brazil RailWorks module consists of premade custom objects, designed to represent a real environment for the Rail problem modeling, with less configuration. Our approach is to unite 3D modeling with the Process Flow functionality, allowing object configuration and visualization through the native 3D FlexSim solution, and the rail system events to be triggered by the Process Flow, using not only defaults FlexSim Process Flow activities, but also new ones developed by our team. Release Notes View the full release notes in the online documentation. RailWorks 25.0.1 (19 March 2025) Features Feature: Rail Network A new way to create and connect your rails into the model. Simple as network nodes, now you can connect the RailNetwork nodes and easily create your own rail tracks. Feature: New Speed table Offering more speed possibilities to configurate all the movement parameters, the new speed table covers all movement speeds, acceleration and deceleration parameters, making the model more plausible and adherent to the real world process. Bug-Fixes Fixed moveWagon auto decouple operation. Fixed a bug where SendToPortal was not freeing rails. RailWorks 24.2.7 (17 January 2025) Bug-Fixes Fixed moveWagon auto decouple operation. Fixed a bug where SendToPortal was not freeing rails. RailWorks 24.2.6 (17 October 2024) Bug-Fixes Improved couple and decouple internal operations. Improved offset calculations internal operations. Fixed a bug where all flowItem classes was the same in different stations. Fixed a bug with passenger locomotive. RailWorks 24.2.5 (25 September 2024) Bug-Fixes Fixed a bug on creating Station object.
View full article
Dear FlexSim user, Update: Please see the FlexSim Newsroom announcement here: FlexSim Answers to migrate to Autodesk Forums on April 25 | FlexSim Original First and foremost, thank you for being an active and valued member of our forum. Your contributions help make this community a valuable resource for everyone, and we truly appreciate your participation. As you may know, FlexSim was acquired by Autodesk in late 2023. As part of this transition, we will be migrating some of our tools, including this forum, to a new platform which we expect to be completed by May 2025. You will be able to access Autodesk forums here. What This Means for You: Seamless Knowledge Transfer – All existing forum content will be migrated, ensuring continued access to the wealth of knowledge shared by our community. A Community-Driven Experience – The forum will evolve into a more self-sustaining, peer-to-peer support hub. While FlexSim support engineers will still visit the forum, when possible, our goal is to empower users to help each other, making this a truly community-led space. Ongoing Support for Entitled Users – We will share more details soon on how eligible users can reach the FlexSim support team directly. For now, we encourage you to continue engaging with the forum as you always have. Your involvement is what makes this community thrive, and we’re excited to embark on this new chapter together. Stay tuned for more updates and thank you for being an essential part of FlexSim! Best, The FlexSim Team
View full article
Intersection with traffic lights in an AGV network This model aims to showcase how allocations of control areas can be manually controlled to achieve more complex logic than the default “first come first serve” implementation. It depicts a four-way road intersection with arriving cars being able to continue in any of the three other directions. Cars driving straight on or turning right use the right lane, cars turning left use the left lane and must give way to oncoming traffic. Traffic lights manage which cars are allowed to enter the intersection at any given time. AGV network and general concept In order to understand the logic behind it, let’s first look at how the AGV network is setup. In the screenshot below we deactivated the visualization of the roads to show the paths and areas more clearly. For each of the four directions there are two incoming paths and one outgoing path. Control points (red) are placed on the incoming paths at the points where cars must stop (based on object center) when the light is red. A single, large control area that control the entry is placed such that is encompasses the entire intersection. Within this control area, an additional control point is placed on each of the left turning paths (orange). This is the location where left turning vehicles must wait for the oncoming lane to be clear. To enforce this the four smaller, rectangular control areas are used. The lane turning left and both the straight and right turning lane coming from the other direction pass through one of these areas. We will later explain how the straight and right turning cars are given priority to allocate these areas, resulting in cars wanting to turn left having to wait until no other allocation requests are present. As all paths are one-way and the geometry is pretty simple, all things considered, the distance between cars is handled by an accumulation behaviour set on the paths. The logic controlling the vehicles is very simple. If we zoom out, we can see that cars leaving the intersection in any direction eventually just turn around and return. At the turning points control points are placed that serve as the travel destination for the cars. A Process Flow with one token per car randomly chooses the next destination when the previous travel task is finished and sends the car there. The cars will automatically use the correct lanes, since those are the shortest paths to reach their destination. For the intersection logic each combination of origin and destination (meaning every possible way of crossing the intersection) is represented as a number. These numbers are stored as global macros for ease of use. The letters represent the four cardinal directions (north, west, south, east). For example, using the intersection to travel from east to west would be represented by the ‘mode’ number 4. At the same time as a new destination is chosen for the car, the respective mode number is also written to a label on the car. In the logic that controls entries into the intersection, these modes are used to identify which vehicles are allowed to enter. Powers of two are used, so the numbers can simply be added together to get a single number that encodes which lights are green. The light phases are defined in a global table. One of the simplest sensible configurations is shown below. At first, all lights are red (no entries in the “Green” columns) for 5 seconds. Then all cars coming from the west and east directions receive a green light for 20 seconds. This is followed by another 5s of all red lights and finally the other directions are allowed to move on. The table is then repeated from the top. The phase in line two would be represented as mode 1365 (1 + 4 + 16 + 64 + 256 + 1024). This becomes a lot more obvious when the mode is written in binary: 0000 0101 0101 0101 Each bit represents one of the possible directions. Allocation logic explained The control area is set to allow 0 concurrent allocations. Meaning for a request to actually result in an allocation, we need to override the return value of the “On Request” event of the control area. This happens in the control logic for the intersection that is implemented as an Object Process Flow linked to the control area. An Event-Triggered Source reacts to the On Request event and writes a reference to the “Allocator” (meaning the car/AGV) to a label on the token. Note that the “Will Override Return Value” box is checked. The token then enters a Finish activity in whose “Return Value” field the current traffic mode of the control area is compared to the mode of the requesting car. The “&” is the bitwise-and-operator. It goes through both numbers bit by bit. If the bit at a given position is 1 in both numbers, it will also be 1 in the returned value, 0 otherwise. If the mode of the car is part of the current traffic mode (which is a sum of such modes) the result will be the mode. This non-zero number is interpreted as “true” in the if-condition and the return value of the code is to allow the request to go through. Otherwise, the request is blocked. (The “Allow” and “Block” properties return 1 and -1, respectively.) The second part of the Process Flow is a loop with a single token that reads the next traffic mode from the global table. It then ‘announces’ which phase the intersection will enter next, so that the draw logic of the traffic light objects can start the process of switching from red to green or vice versa if needed. After a delay, in which those lights would show yellow, the current phase of the control area is updated. The same code that updates the label then also searches for cars that are now allowed to enter the intersection among the pending allocation requests. Since, as far as I could tell, there is currently no direct method to refire an allocation request, those cars receive a pre-empting task sequence that uses a break task to immediately return to the previously active sequence. The restart of their travel task then causes them to try to allocate the control area again. After waiting the duration assigned to the current traffic phase, the token once more updates the mode of the intersection to an ‘intermediate’ mode. This mode is the result of another bit-wise comparison of the current and the next mode. This allows lights that need to change to red to do so, while lights that stay green remain unchanged. Once the next phase is activated, additional lights might then become green. If the next phase doesn’t have any green lights, all lights will already be red in the intermediate mode, meaning the Process Flow block that updates the mode can be skipped and the token instead just waits out the duration in the “All Red Duration” Delay activity. The logic that makes left turning vehicles give way to oncoming traffic works in a similar way. It is also implemented as an Object Process Flow, linked to the four smaller control areas within the intersection. These areas allow a single allocation by default and also have a “Mode” label. But it’s not set based on a timer and otherwise static. Instead, these areas start in mode 0 and if a request is made while the area is empty, the allocation is always allowed, and the mode is set to match that of the allocator. When another request is made, the areas mode is compared with that of the new requesting car. If they match, the request can potentially be granted. First however, the code searches other pending requests for a mode with a higher priority than that of the current request. (The mode numbers are assigned in the order straight < right turn < left turn, so they can also be used as a priority value, where lower is better.) If such a request is found, the current one is blocked, to allow for the area to empty. At that point, a token created by a source listening to the “On Deallocated” event of the control area will reset the mode of the area to 0 and sort any pending requests by priority, before those get re-evaluated. In summary, this logic allows an arbitrary number of cars with the same mode to enter the area. As soon as a higher priority request that can’t immediately enter is created, other requests are blocked; they must ‘give way’. Visualization and parameters The traffic lights are BasicFR objects that draw colored circles as lights in their On Draw trigger, depending on a label. That label is updated in the On Message trigger whenever the intersection changes its phase. The roads are drawn along the AGV paths in the On Draw code of a dummy object placed to the side of the intersection. How wide and in what interval the white lines are drawn is determined by Array labels on the paths containing all necessary parameters. The model comes with five parameters: The first controls which table is used to determine the traffic light phases, the second and third set the time it takes a light to switch from red to green and green to red. The fourth sets the number of cars and the final one switches the visualization of the left turn lights to arrows. agv-traffic-mode-intersection.fsm
View full article
Requirements FlexSim 25.0 or later (found in the downloads page) NVIDIA's Omniverse USD Composer Background Historically, users have used USD Stages in FlexSim to create a live connection with an Omniverse application to be able to simulate animations in Omniverse. However, this relies on a live connection between FlexSim and Omniverse. Sometimes this type of connection is sub-optimal for a user's situation. This article will explain a workflow for writing animation data to a USD file to play in an Omniverse application independent from FlexSim. Disclaimer All the data we record during this example is meant to help us write meaningful data into a .usd file so we can generate an animation in USD Composer. When I say "animation", I mean positional and rotational data along with showing/hiding flowitems. If you want to see Operator Skeletal Animations, I'll post a similar article with a few tweaks later to showcase how to do that using USD Composer's Sequencer, which uses Tracks and Asset Clips to handle small-scale skeletal animations. Example Model I've built a sample model demonstrating the changes to the USD API and how to use them. This example model is just one way to use the API -- there are other ways that users are free to explore. example_model.zip Explaining the Model When you open the model, you'll see a few different windowpanes. In the top-right corner, you'll see a Global Table. If you reset the model, you'll see column headings appear. Each column is a different piece of data we'll be writing to the USD Stage. Each row is a different entry of data to write. In the center views, you'll have a 3D view on the left side and a Process Flow (PF) on the right. At the bottom, there's a script window with a few lines of code. Those lines of code are User Commands I defined to summarize the functionality they encapsulate. The 3D View In the 3D view, you should see some queues, processors, operators, and conveyors. This is a simple workflow where items come into the queues, operators move them into the processors for processing, and then the operators send them down the conveyor lines. With this model, we'll demonstrate (1) operator movement and (2) flowitem movement on conveyors. Setting Up the USD Stage There should be a "USD Stage1" present in the model. If you click on the USD Stage, its properties will appear on the right-side of the screen. In it, you'll see a blank edit field. This is where you put the path to the USD file you want to work on have appear. If you want to save a fresh one, while the edit field is blank, click the "Save" icon next to it. Once you select where you want to place the file, name it, and close the file explorer popup, the edit field should populate with the full path to the .usd file. For more info, you can check out the docs page on the USD Stage object. Viewing the Model in USD Composer Once you've saved your USD Stage, you can open the .usd file in any software that can view .usd files. For this demonstration, we'll be using NVIDIA's Omniverse application which as a USD Composer module. The Process Flow Open up the Process Flow tab to view the simple setup. I'll walk through each part of the PF to give you an idea of how it works. Operator Movement This block of PF is in charge of recording information about Operator positions and rotations. It records information whenever an Operator starts and ends a task. You can expound on this concept and record information when specific triggers or events happen, but for this example I kept it simple and record when any task happens. User Command: RecordInfoToTable Within the "Record Info" Activity, it calls a User Command to record information to the table. This function simply takes a token as the first parameter. This is what the code looks like: Token token = param(1); // Setup row for this iteration Table animInfo = Table("AnimationInfo"); animInfo.addRow(); int curRow = animInfo.numRows; token.labels.assert("Row", 1).value = curRow; animInfo[curRow]["Object"] = token.operator; animInfo[curRow]["AnimTime"] = Model.time; animInfo[curRow]["TaskType"] = token.taskType; // Record positional and rotational data Object operator = token.operator.as(Object); animInfo[curRow]["PosX"] = operator.location.x; animInfo[curRow]["PosY"] = operator.location.y; animInfo[curRow]["PosZ"] = operator.location.z; double Z = Math.fmod(operator.rotation.z, 360); if (Z < 0) Z += 360; animInfo[curRow]["RotX"] = operator.rotation.x; animInfo[curRow]["RotY"] = operator.rotation.y; animInfo[curRow]["RotZ"] = Z; To summarize: Start by assigning the value of the token (parameter 1) to the local variable "token" We get a reference to the Global Table (AnimationInfo) and add a row for the data we're about to write Record (1) which operator this data is for, (2) what time this is happening, (3) and the type of task they're performing. The task type isn't as important - it's for finer details and debugging if necessary. Then we record the positional data of the operator. We previously saved the "operator" label onto the token, so we can use that and "cast" it to be an Object. We do this because the Object class has a "location" property which holds the x, y, z coordinates of the object. Lastly, we do the same thing with "rotation", except we need to bound the rotation to be a positive number between 0 and 360. To do this, we call Math.fmod() to get the reminder after dividing by 360. If the value is negative, we add 360 to get a positive value. Running the Model If you reset and run the model to the stop time at 200, you'll see the Global Table populate with data. There should be valid data for all the columns except the last 3. The "BoxNum", "EntryConveyor", and "Show" columns are for recording flowitem data. We'll discuss that later. Once you've got data in the table, we can run the User Commands in the script window at the bottom of the screen. They should be: ClearTimestampedData(); return WriteToUsd(); The first one "ClearTimestampedData()" is used to loop through the operators and clear all their time-sampled data. We do this so no old data is used if you change things in the FlexSim model and export new data. The second one "WriteToUsd()" is what reads the Global Table line by line, defines and finds prims, writes time-sampled data to them, and saves the information to the .usd file. View the Animation in USD Composer After running these scripts, you should get a prompt in USD Composer to "Fetch Changes". Fetch the changes. Then, open the Timeline feature (Window > Animation > Timeline). This opens an animation timeline at the bottom of the screen. You can save predefined start and end times for the whole stage using the Flexscript API if you choose. Otherwise, you can change the settings manually in USD Composer. (I've color-coded the image below to help explain the tool.) On the far-left (green circle) is the starting frame of the animation while the far-right (red circle) is the ending frame. The inner numbers allow you to set specific sections of the animation to play. If not set, it will play the whole animation. The top-right value and blue "scrubber" (blue circle and arrow) denote the current frame. When you hit your space-bar (or click the "Play" button), that scrubber should move. The value next to FPS (yellow circle) represents the "Frames per Second" the animation runs at. If you want it to play faster, then you can set it to a higher FPS. Note that this example model is built assuming 24 FPS. There is a User Command "TimeToFPS" that simply multiples the given Model time by a desired FPS, defaulting to 24 FPS. If you want to change that rate, you can set it in the code. Now that we've got the animation timeline setup, hit play and watch the animation. You may need to adjust the animation range to be 850 to 4800 so you can see the movements. Like I mentioned in the Disclaimer, if you want to see skeletal animations in the Operator, I'll have another article explaining how to add that functionality. Add Flowitem Movement on the Conveyor Let's go back to FlexSim and check out the Process Flow again. I have two other containers labeled "Box Movement: Time-based" and "Box Movement: DPs". These flows represent two different ways to record this data: either based on a time interval or based on Decision Point positions. The time-based way can be more accurate, but it adds much more time-sample data than the DP version. Choose one of the versions to test out, open the properties of their Source, and then Enable it. If you reset and run the model, you'll start seeing entries for Flowitems. They'll utilize the last 3 columns of the Global Table to keep track of (1) the Box# they are, (2) the Conveyor they entered on, and (3) whether or not to "show" their prim. Click here to learn more about prim visibility. Run the scripts to export and save the model. Then, fetch and view the changes in USD Composer. Conclusion We've covered how to use some of the new features of the USD API in FlexSim 25.0 to create stand-alone animations in .usd files. We used FlexSim to record and export data to .usd files to then display in USD Composer. You can now play a standalone animation in USD Composer without a live connection to FlexSim.
View full article
MQTT is a communication protocol designed for IoT devices. Clients (the devices) connect to a Broker which allows them to publish (send) and subscribe (receive) messages. Each message is associated with a Topic. Each client can choose which topics to use for publishing and subscribing. Usually, the MQTT broker discards messages once they are sent to all subscribers. However, a publisher can mark a message as "retained." This means the broker will keep the last message for that topic and make it available to other subscribers. Only the most recent message is retained. When developing a digital twin, you may need to access these retained messages. This article describes how to do that using FlexSim's Python connection. This article is not meant as a comprehensive guide, but as a starting point, which you certainly will modify for your circumstances. Here are the python scripts and FlexSim model used in this example: MQTT.zip A quick note: since MQTT is a device communication protocol, support for MQTT in the Emulation module is in progress. This article describes how to import data from an MQTT broker like any other file/database/http server, rather than connecting for Emulation purposes. Step 1: Gaining Access to an MQTT Broker Your facility may already have an MQTT Broker running. In the end, your digital twin will need to connect to that broker to retrieve the latest retained messages. However, for testing, or if you don't have an MQTT Broker yet, you can easily get one. One possibility is to use Docker to run the EMQX Broker. However, there are dozens of brokers and installation steps You can download Docker Desktop here: https://www.docker.com/products/docker-desktop/ Once docker is running, you can use the following command in a terminal to download and run the EMQX Broker: docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx Note that this command runs a Linux container, so if Docker is in Windows mode, you'll need to switch before running this command. Step 2: Publishing Messages to an MQTT Broker A real facility will have many publishers and subscribers. However, for testing, it can be convenient to create publishers and subscribers that you control. Once your broker is running, you can use code like the following to create a publishing client: https://github.com/emqx/MQTT-Client-Examples/blob/master/mqtt-client-Python3/pub_sub_tcp.py For this example, I created two clients that publish tabular data: one that publishes a set of "raw materials" available for use in the process, and another that publishes a set of "finished goods" available to fulfill orders. To create some data, run the finished_goods_client.py and raw_materials_client.py files for a few seconds each. Note that both of these clients mark the messages to be retained, so FlexSim can access the latest message, even if neither client is actively running. Step 3: Writing a Python Script to Retrieve Messages This approach is demonstrated in fs_client.py, shown here: import paho.mqtt.subscribe as subscribe import json def get_retained_msgs(topics): auth = { 'username': 'emqx', 'password': 'public', } msgs = subscribe.simple( topics, qos=0, msg_count=len(topics), retained=True, hostname="localhost", port=1883, client_id=None, auth=auth, keepalive=5) if type(msgs) == list: return [json.loads(m.payload) for m in msgs] else: return [json.loads(msgs.payload)] if __name__ == "__main__": topics = ["python-mqtt/raw-materials", "python-mqtt/finished-goods"] print(get_retained_msgs(topics)) Run this script to verify that it returns the latest data from the two publishers. When FlexSim calls this function, FlexSim can convert python Lists and Dictionaries into FlexSim Arrays and Maps. So you can return complex data structures directly to FlexSim. Step 4: Writing a User Command to Call the Python Command In FlexSim, create a new user command, and edit the code. Be sure to toggle the node for external use, and set it to the following: /**external python: */ /**/"fs_client"/**/ /** \nfunction name:*/ /**/"get_retained_msgs"/**/ To use Python like this, you need python installed on the path. You also need the paho-mqtt package installed globally. Finally, you need to verify that your global preferences indicate the correct version of Python. For more information on connecting to python functions, see FlexSim's documentation: https://docs.flexsim.com/en/23.2/Reference/DeveloperAdvancedUser/ConnectingToExternalCode/ConnectingToExternalCode.html Step 5: Writing a User Command to Write Messages to Global Tables In this example, the messages we are interested in store tabular data, so it makes sense to store the data in Global Tables: Array tables = ; Array topics = ["python-mqtt/raw-materials", "python-mqtt/finished-goods" Array msgs = getRetainedMessages(topics); for (int m = 1; m <= msgs.length; m++) { Table fsTable = tables[m // header code elided; see example Array msgData = msgs .data; Table msgTable = Table(msgData); msgTable.cloneTo(fsTable); // header code elided; see example } If you run this new user command, you can see the latest data pulled in to FlexSim. Conclusion This example shows just one way you could import data from an MQTT broker into FlexSim. In addition, the kind of data you import or what you do with that data is up to you as the user.
View full article
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
This model demonstrates a method of giving a task executor a set of tasks (or jobs) to accomplish in a specific sequence by referencing information stored in a global table. In this case, an operator needs to move boxes between queues in a very specific order. The global table defines the order of operations, with each row representing one job. The row contains necessary information about the job: the item to be moved and its destination. These jobs are to be carried out in order, row by row. First, Product1 will be moved to Queue1, then Product2 to Queue2, Product3 to Queue3, Product1 to QueueOut, and so on and so forth. Any modifications made to this table will directly modify the model’s behavior. The logic behind the process flow is relatively simple: a single token loops through a task sequence, with the operator completing a job with every loop. Assign Labels activities are used to get information about the job from the global table and attach that information to the token. The “Assign Labels: Get Table Data” activities reference the current row in the global table to access and store information about the current job (the item name and its destination). The “Assign Label: Item” activities use custom code to search through a group containing all the queues in the model until it finds the item matching the item name from the global table. The task sequence directs the operator to travel to the item’s queue, load the item, travel to the destination, and unload the item. The token’s labels contain the information that is needed for these activities. After this sequence is completed, the label “row” is incremented so that the next row in the table will be used for the following job. Although this demo model shows an operator moving boxes between queues, this method of acquiring data from global tables to define an order of operations can be used in a variety of other applications. GlobalTableDemo.fsm
View full article
This model, developed by @Jacob W2, demonstrates a method of using a kinetic tracked variable to measure process completion on a processor. This allows a processor to have a dynamic processing time, which isn’t possible using the standard processor logic. This is all handled though the use of an object process flow that easily allows other processors to be used in a similar fashion. Kinetic tracked variable.fsm This is the basic layout for the model: a source, a basic fixed resource, and a queue. A basic fixed resource is used in lieu of a processor because it has no innate logic that needs to be dealt with. This is the object flow layout. It’s fairly simple, but handles all of the logic we will need for the processor to work. The “Model Start Logic” container allows the first item to enter the processor. The “Item Control” section is the main feature of the model. A token is created whenever an item enters the processor. A process time label is created on the token, which sets when the process will be completed. This value should be set in model time units. For example, if a part takes one minute to complete and the model time is in units of seconds, the value should be 60. The Initialize Tracked Variable custom code activity is what actually creates the tracked variable that represents the processing progress. First, a treenode has to be created for the label, and then the tracked variable needs to be initialized with the correct type; in this case, a kinetic level tracked variable. A token is then created in the Variable Rate Loop. This token is used to set the processing rate. First, the token will set an initial rate for the tracked variable, and then after a random delay, it will set a new rate for the part processing. It continues to loop until released by its parent token. While the token for tracking the rate is looping, the token in the “Item Control” container is at the Wait for Event activity watching the tracked variable that we created. Once the tracked variable reaches the value of the process time label, the token releases the item from the processor, and then readies the processor for the next item through a custom code activity. The tracking rate token is then released to a delay and sink activity block, and the original token is then sent to a sink activity. When another item arrives, a new token is created in the “Item Control” container, and the process outlined above is repeated. This application of kinetic tracked variables can be extended to a more complex model that has varying process times based on the availability of operators. More specifically, this model allows operators to be added to the process dynamically when they are available, and the number of operators working on the process directly affects the processing time. KTV_Operators.fsm This model layout contains two sources, two basic fixed resources, and two queues in parallel. It also contains five operators, which are grouped according to their shift. A kinetic tracked variable is once again used to represent the processing time or completion rate of an item, and the rate changes dynamically based on the number of operators working on the job at a time. The logic is contained in an object process flow, which is attached to the two basic fixed resources. The first of the three main containers, “Create Tracked Variable and Wait,” creates the tracked variable for the processing time and waits for processing to be complete. The second container acquires the operators from a list based on the current shift. The last container controls operator movement and changes the processing rate. This logic allows operators to come and go during shifts. The rate can be changed dynamically. As illustrated with the above examples, kinetic tracked variables are a powerful and versatile tool, allowing a greater level of control and customization over your model.
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
Introducing FlexSim Galaga! GALAGA.fsm This is an example of how a game could be made in FlexSim. Feel free to download the model and try it out (FlexSim Version is 23.1). Or if you are interested, see below for how the game works. How it works FlexSim Galaga uses Process Flow to perform all logic that occurs in the game. It also takes advantage of Global Variables to keep track of game data as the game is played. This allows one token to set a variable, for example WaveCounter, and that same value can be referenced anywhere in the model. Player Movement and Inputs I used the function iskeydown() for all player inputs. A token loops through a Custom Code activity that continuously checks for which keys are being pressed and makes the corresponding changes in the model. An example of this for player movement looks like this: if (iskeydown(65) && te.location.x > -90){ // left A te.location.x = te.location.x - 10; } if (iskeydown(68) && te.location.x < 90){ // right D te.location.x = te.location.x + 1 For shooting, similar code is written and assigns a label to the player. This label is used for the token to act differently depending on what the player has bought from the shop. The shop inputs are similar and check if the player has enough money for the selected item in the shop. (See the process flow activities 'Shoot Inputs' and 'Shop Inputs' for how this is done.) Wave Health and Speed As the game plays out, waves get more difficult and arrive faster. Each enemy ship has a certain health value and money value that the player earns when destroying it. These values come from the Global Table WaveHealth. After 50 waves, this table is repeated to spawn new waves. This can go on forever in Endless Mode or this table can be modified during the Model run by buying Extreme Mode. The game starts with Waves that last 20 seconds. To make the waves arrive faster over time, this code lowers the WaveDuration from 20 to 15 to 10 etc. every 12 waves. 5 seconds is the fastest wave time and doesn't get any faster. if (WaveCounter % 12 == 0){ if (WaveDuration > 5){ WaveDuration = WaveDuration - 5; } } Enemy Ships and "Collision" Logic When enemy ships are created, they are added to a Global Map called ColShipMap. The key is the column number the ship is in (1-20) and the value is an array of all ships in that column. This makes it easy to check if a shot has hit a ship. While shots are moving the token they are associated with constantly checks the distance between the shot and any ships in that column (thanks to ColShipMap). The column the shot belongs to is calculated based on the x location of where it is created. When the distance between the shot and a ship in that column is close enough, labels are changed on the token so the game knows which ship was hit and to decrease the health or destroy the object entirely. double x = token.shot.getLocation(1, 0, 0).x; // inverse of token.item.location.x = ((index - 1) * 10) - 95; int index = (x + 95) / 10 + 2; token.Index = index; Array spaceships = ColShipMap[index]; Vec3 shotPos = token.shot.as(Object).getLocation(0.5, 0.5, 0); for (int i = 1; i <= spaceships.length; i++){ double spaceshipY = spaceships.location.y; if (Math.fabs(spaceshipY - newY) < 2) { token.Hit = 1; token.target = spaceships; token.SpliceIndex = i; break; } } Display There are several Billboard objects in the model that toggle depending on the state of the game. (switch_hideshape() is used to make them appear like they are flashing) Feel free to look in the process flow for when these occur, but the overall purpose is to inform the player of what is happening in the game. Note: If you zoom out and want to re-center the model for an optimal display. Open properties and click on the view called 'Menu.' Then close the properties window. All other windows like the Toolbox are closed to make game visuals better. Feel free to look into the Process Flow or Model Triggers for anything I didn't mention. Enjoy!
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
Cycle time per process.fsm Cuando creamos modelos de simulación en ocasiones nos limitamos a modelar un proceso o un numero de parte, en el cual tenemos problemas. Pero ¿Qué pasa cuando corremos un plan de producción completo con distintos números de parte, que ha su vez corren a diferente tiempo ciclo? Este es una manera que permite correr diferentes números de parte en diferentes procesos tantos como tu desees, cada uno con su tiempo ciclo. ¿Qué necesitamos? 1.- Etiqueta en cada ítem que identifique que numero de parte es. Por ejemplo Label: IDpart Value: ABC12 2.-Etiqueta en cada máquina que identifique el proceso que este corre. Por ejemplo Label: Station Value: Processor1 3.- Tabla global que contenga en las columnas los diferentes procesos que tienes en tu línea de producción y en los renglones los diferentes números de parte que pueden correr en tu línea. La información que contenga esta tabla será referente a los tiempos de ciclo de cada numero de parte en cada proceso. Por ejemplo: Processor1 Processor2 Processor3 ABC12 20 10 13 BAC21 11 30 20 4.-Deberas configurar el tiempo de procesamiento de tu processor haciendo referencia a tu tabla global y colocando lo siguiente: Con esto, obtendremos estadísticos ponderados de utilización para los equipos. Beneficios: Puedes correr diferentes números de parte en una misma línea con su respectivo tiempo ciclo cada una. Utilización de equipos y operadores mas exacta. Modificar tiempos ciclos en una tabla global es más fácil y controlado que directo en los procesos. Cálculo de capacidad de tu línea más exacta corriendo un plan de producción real. Puedes agregar y quitar procesos o incluso modificar el flujo de tu línea sin afectar el tiempo de ciclo que corra ese procesador. Ya que esta referenciado por su etiqueta a la tabla global.
View full article
So you were trying to record a video and the Video Recorder crashed. Here is a step by step guide on how to debug the video recorder: Step 1: Is there a stop time in your model? In some older versions of FlexSim (2022 and older), if there is a stop time in your model that occurs during the model recording time, the video recorder will stop indefinitely at that time. Try removing any stop times that occur during the recording. Step 2: Are your graphics drivers up to date? (!!!!!!!!) This is the most common problem we see as to why the video recorder is not working. To start debugging this issue, check what graphics card FlexSim is using. If you open a model then go to Help->About FlexSim from the top toolbar, you will open this screen: The highlighted text that starts with OpenGL tell you what graphics card FlexSim is using. Now you might need to do a little research to find what graphic driver that card is using and then update it, but we've found in most cases updating the graphics card driver fixes video recorder issues. There's an article here the explains more on how to update your graphics driver (it's a very helpful read that also deals with some special cases on certain graphics cards). Make sure you're downloading either directly from the makers website or for your specific computer type, your computer will not be able to tell you if they're out of date. Step 3: Can you record a simpler video? If you make a very simple model (Source -> Queue -> Processor -> Sink), can you record it without issue? If you can then at least you know your video recorder can work, it is just having a issue with running a bigger model. If this is the case you might be running out of VRAM or the bigger model is taking so long to run that an outside manager is forcing it to close. If that is the case, here are some things to try: Update your graphics drivers (this is always the biggest issue). Revert your graphics card settings back to their defaults (for example, in the Nvidia Control Panel). For the next two suggestions go to the toolbar and click File -> Global Preferences -> Graphics Turn off Shadows and/or record a smaller resolution video to see if that helps. If it does, then the issue is likely that FlexSim is trying to use more VRAM than your graphics card supports. Make sure you are using the Recommended OpenGL Context and not the Generic (No GPU acceleration) or Core Profile contexts Step 4: Did your model crash previously while recording a video? There may be some corrupted data stuck in your recorder. It's an easy fix, you just need to delete your video recorder from toolbox and then re-add it: Step 5: Are you using a much older version of FlexSim? In a few of the older versions (2019.1 and older), temporary nodes from previous recordings caused the Video Recorder object to crash. To fix it all you need to do is clear the nodes Open your model, execute the following script, and then re-save your model: Model.find("Tools/VideoRecorder>variables/active").subnodes.clear(); Step 6: None of the previous steps worked, what now? If none of the above steps worked you can create and check debug log files, check the filepath, check various computer settings, and see the VRAM allocations to start solving the problem. Check the filepath FlexSim is putting the video from the video recorder into, if it is trying to put it in a strange place that can cause issues. FlexSim uses ffmeg to encode the captured frames into a video file, which leaves an ffmpeg_log.txt file in the directory where the video was created. That file might have something in it that might explain what is happening. You can create fslogfile.txt and exfslogfile.txt files in your FlexSim 20XX Projects directory that FlexSim can write debugging information into. Sometimes you might be able to get exception information in those files in certain cases: Check your settings in Windows or Group Policy or other IT software. It's possible something on your machine separate from FlexSim is noticing that the FlexSim process is taking a long time to respond and then killing its process because it thinks it is hanging. Try clicking the Record button and then not clicking any more anywhere on your machine until the recording is done. Or try recording a shorter timeframe to see if that helps. In Windows' Task Manager, you can add the Dedicated GPU memory column on the Details tab to see how much VRAM FlexSim is using. If FlexSim tries to use more memory than your graphics card supports (or if the total usage of FlexSim and all the other programs currently running exceed your hardware's limit), then FlexSim will likely crash the next time it tries to allocate and use any graphics objects stored in GPU VRAM (such as output buffers used by the Video Recorder, textures, 3D meshes, etc.). You can use Window's "dxdiag" tool to see how much VRAM your graphics card has: If you tried all of these suggestions and nothing worked, feel free to ask a question on the Q&A board and we can work to see if we can find a different solution for you!
View full article
Receiving products from the bottled water manufacturing plant using 11 Rial Guide Vehicles (RGVs) for transportation to the Automated Storage and Retrieval System (ASRS), which serves all three production lines. The RGVs' operation works as follows: when products are placed in the receiving buffer with two available positions, the system immediately sends commands to the RGVs to pick up the products from the buffer. The RGVs prioritize picking up the nearest products first. Consequently, the production line located farthest away (Production Line 1) experiences the highest downtime from January to May 2566, with an average downtime of 449.48 minutes. Production Line 2 has an average downtime of 65.12 minutes, while Production Line 3 experiences 76.00 minutes of downtime during the same period. If a production line stops for more than 20 minutes, it requires a complete drainage of the ongoing production process, including scrapping all unfinished goods. This significantly increases the production costs. Consequently, conducting experiments to address this issue becomes complicated, as full-scale production is necessary to identify the causes and implement effective solutions. Thus, stopping production for testing purposes is not a viable approach in this case.
View full article
Attached is a sample model that uses Google's OR-Tools python module to find optimal AGV dispatching solutions. I recently stumbled on Google's OR-Tools, which includes several classes for finding optimal solutions to things like vehicle routing, scheduling, bin packing, etc. Since FlexSim now has a mechanism for easy connection to python, I decided to try and see if/how it could be connected to FlexSim for testing AGV dispatching strategies. I threw together this model just to see how/if the connection can work. All source/destination locations are chosen at random, and work inter-arrival rates are random with a user-defined mean inter-arrival time. To get this model running on your side: Install a version of python Run the following from the command-line: python -m pip install ortools In FlexSim, make sure your preferences are configured for the correct version of python, and that python is part of your PATH environment variable. Open the model. In the Parameters table, set DispatchMode to 'VRP Solver'. This model uses the Vehicle Routing Problem solver to find optimal AGV assignment strategies. The main work generation logic is in the 'Work Generation' process flow. At random intervals, work requests arrive. They are assigned to random source and destination locations. Then, when dispatching in 'VRP Solver' mode, the logic calls the optimizeVRP() user command. This command packages the current state of the model into a valid vehicle routing problem, and then passes it to the py_optimizeVRP() user command, which is implemented in python, in the AGVVRP.py file. The command creates the VRP problem using the OR-Tools classes, and then calls the solver, returning the results. OptimizeVRP() then interprets the results and assigns AGVs as needed. Note that the VRP is re-solved every time new work arrives. You'll see little 'freezes' in the execution of the model, because it is solving the VRP at each work arrival. Note that the standard Vehicle Routing Problem is slightly different from the problem this model needs optimized: In an AGV model, there’s no depot. Instead AGVs may be currently located anywhere in the warehouse. There’s no ‘depot-loaded’ capacity of an AGV, and no ‘demand’ at customers. The standard VRP is a situation where trucks are loaded at the depot, and then depleted as they visit each customer in the route. This is not present with single-capacity AGVs. When an AGV picks up at an origin location, it must immediately deliver to the destination location. In order to wrangle the AGV problem into a valid vehicle routing problem that can be solved by OR-Tools, I constructed the problem as follows: I made each AGV’s ‘current location’ a node in the graph The distance from the depot to the AGV’s current location is 0 The distance from the depot to any other node in the graph is prohibitively large. This will cause vehicles to always go to their 'current location' first, with 0 cost. The distance from any node in the graph back to the depot is 0 A given AGV must visit its current location as part of its route. This can be added as a constraint to the problem in OR-Tools For immediate unload after loading, I initially tried adding this rule as a constraint, but the solver hung when solving. So, instead of graph nodes being locations in the facility, I made graph nodes represent ‘tasks’, i.e. visiting this node means picking up the item AND dropping it off. As such, the ‘cost’ of ‘visiting’ a ‘task’ node is the cost to travel from the ‘destination’ of the previous node to the ‘origin’ of this ‘task’ node, plus the cost to travel from the ‘origin’ of this task node to the destination of this ‘task’ node. Once I did this, OR-Tools was able to solve the problem 'optimally'. By optimally, I mean it was finding the AGV routing that minimized the maximum 'travel makespan', which is the maximum distance route of all of the AGVs. Once I had done this, I wanted to compared it with various heuristic-based scenarios. So I set up a 'Closest' dispatch mode. Here, when an AGV finishes a task, it will take up the next task whose pickup point is closest to its current position. I also created a 'FIFO' dispatching mode, which is that work will be dispatched to AGVs always in FIFO order. These three dispatching modes I compared with the experimenter. My initial experiments showed some interesting results. Most interesting was that in 'VRP Solver' mode, work task time-in-system was relatively high. This is because the objective function completely ignored time in system of the work, and was only optimizing for vehicle travel distance. So some work was being pushed off until much later because vehicles could get better travel distances by pushing it off. To account for this, I added a 'soft upper bound', which is kind of like a 'due date' for the work. Namely, work is due to be finished 800 'meters-of-agv-travel' after it arrives. This was a quick-and-dirty workaround and could certainly be improved, but it did serve to get the time in system for VRP Solver mode down. Below are some of the resulting experimenter results. AGVTaskTime - Time from starting a task to finishing it (i.e. a kind of takt time) The VRP solver performed the best across all scenarios here, and was especially better than the other strategies in low-demand scenarios. This intuitively makes sense. When there are a lot of under-utilized AGVs, the closest and FIFO strategies will always dispatch idle AGVs to do work, which could potentially make them travel long distances. However, the VRP solver can find opportunities to decrease travel distance by waiting to dispatch an AGV that will be near a task in the future, and leave other AGVs idle. Note that I think the 'closest' strategy only finds the 'closest' next task for an AGV that just finished a task, not the 'closest' idle AGV for an arriving task. Obviously that could be changed for a better performing 'closest' strategy. On the other hand, I think in this model all idle AGVs go back to the same park location, so such a change would require distributed park locations to take advantage of closer idle AGVs. AGVWorkStaytime - time-in-system for a given AGV task Here the 'closest' strategy actually performed better than the VRP. This would seem counter-intuitive at first, but upon further evaluation, it does make sense. The VRP, in its current form, only optimizes for total AGV travel distance. It completely ignores job time in system/due dates/etc. So the solver will always assign a route that is shorter even if that route pushes back jobs that have been in the queue for a long time. The solver also re-solves every time a new job arrives. So we may be having scenarios where some jobs are always 'better' to be pushed to the end of the route, and so they keep getting pushed back, resulting in poor time-in-system performance. The solver does include soft and hard job 'due dates', so we could make adjustments to the problem to make the VRP get better time-in-system results. AvgAGVUtilization AvgAGVUtilization is where the VRP especially shines in low-demand scenarios. It finds opportunities to leave AGVs parked because there will be opportunities for busy AGVs to take up jobs in the future with minimal extra travel overhead, whereas the 'FIFO' and 'Closest' strategies will always dispatch idle AGVs to unassigned jobs, causing extra unnecessary empty travel. I am still a bit perplexed by the high-demand scenarios though. Here the 'Closest' and 'FIFO' strategies both beat the VRP in the 120/hr and 102/hr scenarios. This probably would warrant further investigation as to why the other strategies do better here. It may be that, in these scenarios, the AGVs cannot keep up with demand. So there is a queue of jobs that is ever-increasing. The VRP solver is optimizing the full plan, meaning it is scheduling job assignments, and finding travel distance minimization opportunities, that are way out into the future. And it is not getting the opportunity to execute those optimized routes because the problem is being re-solved at each job arrival. With an increasing job queue, the 'closest' and 'fifo' strategies might be actually doing better specifically because they are short-sighted. Just take the closest job to you. On the other hand, if we have increasing job queues (i.e. the AGVs can't keep up), then the AGV utilization should be around 100% anyway, which it's not. Anyway, it's something still to churn on. ThroughputPerHour The throughput per hour indicator tells us whether the AGVs actually kept up with the jobs. If the AGVs were able to keep up with jobs, then the resulting means should be right around the scenario's throughput/hr number. It looks like FIFO got way behind on both the 120/hr and 102/hr scenarios. 'Closest' and VRP both got a little behind in the 120/hr scenarios. One exciting possibility of using this design is that the python script is not technically dependent on FlexSim. So you can use FlexSim to test your python-based optimization, and then you can deploy that python script in a live setting. AGVVehicleRoutingProblem.zip
View full article
Introduction Several times per year we release a new feature-version of FlexSim Simulation Software. In order for your PCs to be able to run a licensed version of the upgraded software, you'll need to upgrade your standalone FlexSim license. Licenses with a current maintenance subscription are eligible to be upgraded to the new version. If you don't understand how licensing works for different FlexSim versions, please review our Answers article FlexSim Version Numbering. Overview After installing your new version of FlexSim, there are 3 main steps to upgrading your standalone license: Return the licenses you intend to upgrade Upgrade your licenses Activate the upgraded license Several of these steps have their own fully documented procedures. We'll link you to those resources below. 1. Return the licenses you intend to upgrade The steps to return a standalone license are fully documented. Choose the link below that best matches your needs, depending on whether your PC can connect to the Internet: Standalone - Return - Online Standalone - Return - XML / Offline Be sure to return ALL licenses you wish to upgrade. 2. Upgrade your licenses NOTE: Licenses with expired maintenance will not upgrade. Timed licenses do not upgrade. Only permanent (not timed) licenses under current maintenance can be upgraded. Log in to your FlexSim Account. If you were already logged in to your FlexSim Account, in the top navigation menu hover over your initials icon and choose Reload Account. Now in the top navigation menu, choose Licenses > List. Check that the available seat count is equal to the total. All of a license’s seats should be returned for it to upgrade. Click on the Upgrade Licenses button. If you have several licenses to upgrade and all are owned by or shared with your FlexSim Account, they will all be upgraded at once. Please be patient while the upgrade process works in the background. When the page refreshes, eligible licenses will have a new activation ID for the latest version of the software. Your license code indicates its version at the end of the code to help you know what versions your license will properly activate. Review license code format. You'll be able to use the upgraded license codes in the next step. 3. Activate the upgraded licenses The steps to activate a standalone license are fully documented. Choose the link below that best matches your needs, depending on whether your PC can connect to the Internet: Standalone - Activation - Online Standalone - Activation - XML / Offline If you have any questions or problems, please search our Answers Community for possible solutions. There is a good chance someone else has already asked your question. Still not finding what you're looking for? Submit a new question and we'll check it out. If you're including any confidential information, such as license codes, be sure to mark your question as private! You can also contact your local FlexSim distributor for live phone, web, or email help.
View full article
"switch by case" is a stucture in many programming languages. It is a availbale in Flexscript. A case must be a number for a switch by case structure in Flexscript. A decide activity can switch even to string value cases. All you need is to rename the connector from a decision activity to a following activity. process_flow_by_case.fsm
View full article
Article space for Production Engineer Book including FlexSim Examples from Brasil Este material de apoio faz parte do Livro Administração de produção e operações, manufatura e serviços: uma abordagem estratégica, dos autores Henrique Correa e Carlos Correa, em sua 5º Edição. Para auxiliar o aprendizado, este livro conta com exemplos em vídeo e modelos de simulações de processos disponíveis em diversos capítulos. O acesso ao material é gratuito e pode ser acessado através dos links abaixo nas descrições de cada capítulo. Aqui você encontrará o conteúdo detalhado, referente aos arquivos dos modelos de simulação (*.fsm) e os links dos vídeos no YouTube. Dessa forma, o leitor poderá usufruir dos arquivos de simulação criados para facilitar e enriquecer o seu aprendizado. Capítulo 10 Projeto do Produto e Seleção de Processos (Bens e Serviços) Call Center download modelo clique para assistir o vídeo Restaurante download modelo clique para assistir o vídeo Clínica download modelo clique para assistir o vídeo Loja de conveniência download modelo clique para assistir o vídeo Segurança de um aeroporto download modelo clique para assistir o vídeo Terminal Rodoviário download modelo clique para assistir o vídeo Hospital clique para assistir o vídeo Estacionamento clique para assistir o vídeo Capítulo 13 Localização e Arranjo Físico de Unidades da Rede de Operações Layout Celular clique para assistir o vídeo Layout em Linha clique para assistir o vídeo Layout por Processos (em breve) Layout Posicional (em breve) Capítulo 14 Capacidade Produtiva e Filas em Unidades da Rede de Operações Teoria das Filas download modelo clique aqui para assistir o vídeo Capítulo 15 Teoria das Restrições em Redes de Operações TOC Princípios 1-9 download modelo princípio 1 download modelo princípio 2 download modelo princípio 3 download modelo princípios 4 e 5 download modelo princípio 6 download modelo princípio 7 download modelo princípio 8 download modelo princípio 9 clique para assistir o vídeo Sistema Drum-Buffer-Rope (Tambor-Pulmão-Corda) download modelo clique para assistir o vídeo Capítulo 17 Gestão de Estoques na Rede de Operações Simulação de Reposição Periódica / Contínua (em breve) Capítulo 19 Sequenciamento, Programação e Controle de Operações Sequenciamento de Produtos e Otimização download modelo clique para assistir o vídeo Job-Shop download modelo clique para assistir o vídeo Capítulo 20 Just in Time (JIT) e Operações Enxutas (Lean) Produção Puxada vs. Empurrada download modelo clique aqui para assistir o vídeo Cartão Kanban Assista o vídeo e veja na prática um exemplo de simulação do sistema kanban. download modelo clique aqui para assistir o vídeo Desperdícios do Sistema Toyota de Podução (Lean) download modelo clique aqui para assistir o vídeo Setup Assista o vídeo da simulação de um processo de troca de piso da quadra de uma arena multiuso, utilizada para partidas de hóquei e de basquete. clique aqui para assistir o vídeo Informações Adicionais Os modelos de simulações e os vídeos apresentados foram construídos com o Software FlexSim, plataforma digital, a qual possui uma versão gratuita, FlexSim Express, disponível para download através da URL https://www.flexsim.com/pt/ Vídeo passo a passo download e instalação do FlexSim Express Vídeo requisitos de sistema hardware para utilizar o FlexSim Express Contatos suporte@flexsimbrasil.com.br / @Rodrigo Lamas / @Michael Machado
View full article
Top Contributors