ATTENTIONThis FlexSim Community Forum is read-only. Please post any new questions, ideas, or discussions to our new community (we call it Answers) at https://answers.flexsim.com/. Our new Question & Answer site brings a modern, mobile-friendly interface and more focus on getting answers quickly. There are a few differences between how our new Q&A community works vs. a classic, threaded-conversation-style forum like the one below, so be sure to read our Answers Best Practices. |
flexsim.com |
#1
|
||||
|
||||
Queuing coordinated task sequences?
Hi,
I am a bit unsure of how the coordinated task sequences work when I have a dispatcher and and e.g. two operators which need to act together. When I have two objects both using a coordinated tasksequence to transport a part to the object and one object request transport before the other transport is finished, what will happen? Is the first coord. tasksequnce aborted? The manual say that coordinated taskseuqences are not queued up like normal tasksequences but are executed immediatley. What when the operator involved is still busy with another task? Is there any chance to have a queue for coordinated taskseuqneces or even a priority rule? By now I have to write my own dispatcher and check availablity and sort orders by my own routines. Nico.
__________________
kind regards Nico. |
#2
|
||||
|
||||
Hi Nico,
Coordinated task sequences do queue up (or more accurately, the allocated tasks within them queue up as explained in post #12 below). On the "Request Transport From" of most Fixed Resources there are already two standard coordinated task sequences options which you can select and try. I've added an example based on one of them here. In the example the tree is open for the task executer to which the coordinated tasks are sent (in fact you can send the coordinated tasks to any task executer). You can see during the simulation that in the coordinatedtasks node the tasks queue up. So, here the information of the coordinated tasks and the order inside a coordinated task are stored. From here, task executers can be allocated, perform tasks, synchronize with other task executers and can be deallocated. Martijn Last edited by Cliff King; 02-29-2008 at 03:26 PM. Reason: reference post #12 |
The Following User Says Thank You to Martijn van Oostenbrugge For This Useful Post: | ||
Stefan Trabut (04-05-2011) |
#3
|
||||
|
||||
An addition. I've changed the example a bit. Now there are 3 task executers from one side. You see that the third operator already starts with a coordinated task sequence. In the queue of de Dispatcher an allocate task to the dispatcher of the other operator is queued up, waiting for a free operator to allocate.
Martijn |
#4
|
||||
|
||||
Hi Martijn,
thank you for your answer. So queueing up the coord.tasksequences is no problem. I want to use the coordinated tasksequences to let a pool of OPs use a limited number of carts. As a cart can not travel on its own an will be left on different places in the modell I have to determine the location of the cart to let the OP travle to the cart, then let the OP perform the task with the cart and leave the cart where he used it. So getting a reference to the cart and aquiring the position doesnt work out well. The operatorkey1 and 2 do not contain any references to the used OP, so I don´t see how to determine the position of a used cart or OP. By now I have my own logic dispatching OPs and carts. The carts are loaded as a flowitem. This is working well, but I wonder if I could have solved this problem with less effort using the coord. tasksequences.
__________________
kind regards Nico. |
#5
|
||||
|
||||
Nico,
Although I' have an idea what you want to do, I'm not exactly sure what you are want to do. But 2 hints that might help you are: If you include a sendmessage task that is send to NULL, it is send to the taskexecuter that is executing the task. In the sendmessage you can include other data by using the parameters. With the command "getallocatedfromkey" you might be able to trace which object did get allocated. I hope these 2 small remarks can help you. Regards, Steven |
#6
|
||||
|
||||
Sorry if the description seems to be confused..
I need a reference to the allocated object of a coordinated tasksequence. Lets say we look at Martijn example. I want the two operators to meet at the position of operator 1 before they travel to the item.. So I need the position of operator 1 at the moment the tasksequence is starting to be executed. (I really need the position of the OP not of a fixed meeting point) How to get a reference to the allocated object (operator 1)? I tried this in the 'request transport from' trigger of the queue: treenode item = parnode(1); treenode current = ownerobject(c); int port = parval(2); /**Coordinated Task Sequence Example 2*/ /** \nCreates a coordinated tasksequence manually.*/ /** \nIf this "Request Transport From" field returns a 0 rather than a valid pointer to either a dispatcher or taskexecuter, then no call is made, and it is assumed that the user will dispatch their own tasksequence. This example shows the code that is required to create a coordinated tasksequence that calls for two operators to transport the same flowitem together.*/ /* The idea here is to get two operators to travel over to this object. Then after both have arrived, have one of them load the flowitem. Then after one has loaded the flowitem, have both of them walk together over to a destination and unload the flowitem. */ treenode destination = outobject(current,port); //the destination is determined by the previous evaluation of the "Send To Port" field. treenode operatorteam = centerobject(current,1); // OPS treenode cartteam = centerobject(current,2); // Carts treenode myts = createcoordinatedtasksequence(operatorteam); //the coordinated tasksequence can be created on any dispatcher in the model (the operatorteam is used for convenience). int operator1key = insertallocatetask(myts, operatorteam, 0, 0); //allocate the first availabe operator connected to the dispatcher and record a numeric key pointing to the chosen operator int cart1key = insertallocatetask(myts, cartteam, 0, 0); //allocate the another availabe operator connected to the dispatcher and record a numeric key pointing to the second chosen operator treenode cart= getallocatedfromkey(myts,cart1key); pd(getnroftasks(myts)); pr(); pt(getname(cart)); pr(); stop(); So there are 2 tasks dispatched but the cart is NULL??
__________________
kind regards Nico. |
#7
|
||||
|
||||
Nico,
What you have to do is use a callsubtask to travel to the right cart, because when you create the tasksequence you don't know which cart is going to be selected so you can never create a complete tasksequence. So what you can do is that you utilize the operator and do a sendmessage to the cart containing the opkey of the operator. Than on the onmessage of the cart you send a message to the operator telling him what cart he has to go to (storing the pointer in label) and then free the operator. The next task should be a call subtask to itself (so again it's onmessage is fired or the breaktotrigger) and there you create the travel task to the cart and then you can continue. so your tasksequence might look somethink like: treenode destination = outobject(current,port); //the destination is determined by the previous evaluation of the "Send To Port" field. treenode operatorteam = centerobject(current,1); // OPS treenode cartteam = centerobject(current,2); // Carts //the coordinated tasksequence can be created on any dispatcher in the model (the operatorteam is used for convenience). treenode myts = createcoordinatedtasksequence(operatorteam); //allocate the first availabe operator connected to the dispatcher and record a numeric key pointing to the chosen operator int operator1key = insertallocatetask(myts, operatorteam, 0, 0); //Then utilize this operator until the other is selected insertproxytask(myts, operator1key, TASKTYPE_UTILIZE, .......) //this tasksequence is blocked on the allocate task but otherwise be carefull, the order in which the tasks are written in the tasksequence is not necessarily the order in which they are executed!! //Then create the callsubtask. This one triggers the breaktotrigger so create you travel there but you can also use the key to specify to which object your callsubtask has to go insertproxytask(myts, operator1key, TASKTYPE_CALLSUBTASKS, NULL, NULL, 1, 0, 0) //allocate the another availabe operator connected to the dispatcher and record a numeric key pointing to the second chosen operator int cart1key = insertallocatetask(myts, cartteam, 0, 0); //Send a message to that cart containing a pointer to the tasksequence and the key of the other operator insertproxytask(myts, cart1key , TASKTYPE_SENDMESSAGE, NULL, myts, operator1key, 0, 0); Now on the sendmessage of the cart you write: treenode myts = msgsendingobject; int myoperator = msgparam(1); treenode Operator = getallocatedfromkey(myts, myoperator ); //The next message should be used to store the pointer of the cart (passed as msgsendingobject) sendmessage(Operator, current, 1, 0, 0); //And then free the operator to let it's tasksequence continue freeoperators(Operator, NULL); Ofcours I didn't test this code so don't just copy but fill in the right data etc. I hope this is the solution you are looking for |
#8
|
||||
|
||||
Hi Steven,
thanks for your answer. So this is a little more complicated as I thought. I will try this when I find time and let you know if this works out... regards Nico..
__________________
kind regards Nico. |
#9
|
||||
|
||||
Nico,
Your problem is an interesting one which might have universal appeal. If you ever get the time to put together an example model of your "best approach", I'd love for you to share it! Thanks in advance. Cliff |
#10
|
||||
|
||||
Hi Cliff,
so here is what I could get out of normal tasksequences, some tables and a lot of message sending.... You can modify the number of OPs and carts in the "Parameter" table. Maybe using coordinated tasksequences for such a model is inadequate?? Anyhow I think there should be a more elegant solution for such a 'universal problem.'
__________________
kind regards Nico. Last edited by Cliff King; 02-29-2008 at 04:10 PM. Reason: Updated model to v4.3 |
#11
|
||||
|
||||
Nico,
I've built a sample model that I think does the operation that you are looking for. CoordinatedCartSharing.zip There are two lines next to each other. The first line shows the case with no network travel. This one is pretty simple. The insertproxytask command allows you to pass in the allocation key (instead of a direct object reference) as either involved1 or involved2 of the task. This lets you use certain tasks such as TRAVEL or PICKOFFSET or LOAD to travel to the cart. In this case, I just use a travel. Once the operator finishes traveling to the cart, I have both cart and operator travel to the different locations in conjunction. The second line adds a travel network to the equation. This complicates the situation because, in the first example, since there was no travel network, the operators just traveled directly to the location of the cart. If you are using a travel network and want the operators to travel to the cart via the network, then you'll have to do some extra logic to update the "blue line" destination network node of the cart each time the cart moves, so that the operators will travel to the right location. Unfortunately there's no task type that will do this for you, so you have to add some delayed execution logic that fires once the cart has been allocated, so you can get access to the cart as a pointer. You could use a sendmessage to do this, but I decided to do a "trick" with the request transport from field. The trick allows me to put all of the code in the same field, the request transport from. I use a nodefunction task, and I pass in c as involved1, and cartkey as involved2. c is actually the node that is being fired, the request transport from node. That task causes the request transport from to fire again once the operator finishes unloading the item, and a pointer to the cart (since I specified cartkey as involved2) will be passed as parnode(1) into the field. The key is to have some way of distinguishing decisively whether the nodefunction is being fired in the default case or because of my task. I test to see if up(p1) == current. If so, then it's a flowitem, and this is the default case, otherwise, p1 is the cart, and it's the specific case. In the specific case I move the cart into the model, then disconnect it from its previous location and reconnect it to the operator's network node. Here's the code: Code:
treenode p1 = parnode(1); treenode current = ownerobject(c); int port = parval(2); /**Coordinated Task Sequence Example 2*/ /** \nCreates a coordinated tasksequence manually.*/ /** \nIf this "Request Transport From" field returns a 0 rather than a valid pointer to either a dispatcher or taskexecuter, then no call is made, and it is assumed that the user will dispatch their own tasksequence. This example shows the code that is required to create a coordinated tasksequence that calls for two operators to transport the same flowitem together.*/ if(up(p1) == current) { // if parnode(1) is in me, then this is the normal case treenode item = p1; treenode destination = outobject(current,port); //the destination is determined by the previous evaluation of the "Send To Port" field. treenode operatorteam = centerobject(current,1); //assumes a dispatcher is connected to center port 1 (the dispatcher should be connected to two or more taskexecuters). treenode cartteam = centerobject(current,2); treenode ts = createcoordinatedtasksequence(operatorteam); //the coordinated tasksequence can be created on any dispatcher in the model (the operatorteam is used for convenience). int operatorkey = insertallocatetask(ts, operatorteam, 0, 0); //allocate the first availabe operator connected to the dispatcher and record a numeric key pointing to the chosen operator int cartkey = insertallocatetask(ts, cartteam, 0, 0); //allocate the first availabe operator connected to the dispatcher and record a numeric key pointing to the chosen operator insertproxytask(ts, operatorkey, TASKTYPE_TRAVEL, cartkey); insertproxytask(ts, operatorkey, TASKTYPE_LOAD, cartkey, cartkey); insertproxytask(ts, operatorkey, TASKTYPE_TRAVEL, current); insertproxytask(ts, operatorkey, TASKTYPE_FRLOAD, item, current, port,0,0,0); //create an frload task for op1 and record a numeric key pointing to this task in order to sync with it later (only one operator needs to actually "load" the flowitem). insertproxytask(ts, operatorkey, TASKTYPE_TRAVEL, destination, NULL, 0,0,0,0); //create a travel task for op1 to travel to the destination. insertproxytask(ts, operatorkey, TASKTYPE_FRUNLOAD, item, destination, opipno(current,port),0,0,0); //create an frunload task for op1 to unload the flowitem to the destination object. insertproxytask(ts, operatorkey, TASKTYPE_NODEFUNCTION, c, cartkey, 0,0,0,0); //create a insertdeallocatetask(ts, operatorkey); //de-allocate op1 insertdeallocatetask(ts, cartkey); //de-allocate cart dispatchcoordinatedtasksequence(ts); //dispatch the coordinated tasksequence return 0; //return a 0 so this object will know that you made your own tasksequence and it doesn't need to make the standard tasksequence automatically } else { // if up(p1) is not current, then it is the cart itself and this nodefunction is being executed specifically due to the task that I added to call a nodefunction here // Here I need to move the cart back into the model, then reconnect his blue connection line to the current networknode that the operator is on. // This makes it so that the operator will travel to the right location as part of his travel. treenode cart = p1; treenode op = up(cart); treenode lastnetnode = getnetnode(cart, 1); if(objectexists(lastnetnode)) contextdragconnection(cart, lastnetnode, 'E'); treenode newnetnode = gettenetnode(op); if(objectexists(newnetnode)) contextdragconnection(cart, newnetnode, 'D'); moveobject(cart, model()); setloc(cart, xloc(op), yloc(op), zloc(op)); return 0; } Last edited by Anthony Johnson; 04-03-2008 at 11:43 AM. |
The Following User Says Thank You to Anthony Johnson For This Useful Post: | ||
Cliff King (06-07-2008) |
#12
|
||||
|
||||
Also, in response to your question of whether coordinated task sequences queue up. There is a queue of coordinated task sequences, but the actual ordering of those aren't used in the simulation. As soon as you call dispatchcoordinatedtasksequence(), that coordinated task sequence will start to be executed, so there is no queueing there. However, there is queueing when it comes to allocating resources. Whenever it gets to an allocate task in the coordinated task sequence, it will create and dispatch a new, non-coordinated task sequence with a TASKTYPE_TE_ALLOCATED task in it. This task sequence basically represents the allocation of whomever you're trying to allocate. These task sequences do queue up, and they queue up in the regular manner, i.e. they share the same queue as regular task sequences, and they have a priority that helps determine which to do first, etc. You specify the priority of the allocation task sequence through the parameters of the insertallocatetask command. So coordinated task sequences themselves don't really queue up, they start executing as soon as you call dispatchcoordinatedtasksequence(). It is the allocation requests themselves that will queue up and have to wait for shared resources, etc. By default, the insertallocatetask() command will cause further execution of the coordinated task sequence to "block" until that allocation request is satisfied. So it is the queueing up of the allocation requests that causes things to have to wait for shared resources.
|
#13
|
||||
|
||||
Guys,
I just like to check. If I open Nico’s model in v4.30 I can not see any shape. In v4.01 it works correct and I can see the shapes. I checked the path and made the path manually to a shape (fs3d\Source.3DS) but it does not work. So I can not see any shape even if the paths looks correct (and they are standard). If I check the tree, the tree looks correct. Does anyone else has this problem? Does the model work for you guys correct? Thanks for your help. tom the (A)tom
__________________
tom the (A)tom: "We have solved our problems ... now we have to fight the solutions." |
#14
|
||||
|
||||
Tom,
I haven't opened the model but have you checked if the model node is toggled as flexscript? If so, untoggle and everything is visible again. Steven. PS. We have seen that quite a few times lately. Maybe somebody at Flexsim has an idea why this happens? |
#15
|
||||
|
||||
On Feb 29th, I downloaded Nico's model and noticed that the "model" node in the tree did not have object data as it is supposed to, but instead was a string data node that was toggled as a flexscript node. I thought this was very strange and blamed it on a something Nice accidentally did because I had never seen that problem before. Anyways, I fixed it and converted the model into a v4.3 model. I edited Nico's original post and uploaded the v4.3 version of the model (see my revision comments). Tom, I'm guessing you are working with the original model...
Steven, you say you have actually seen this problem before?? |
#16
|
||||
|
||||
Cliff,
Yes we have seen it before and more than once, but I can't give you any info on how and when etc, but I think it has to do something with opening older models in new versions say from 4.1 to 4.3 or 3.5 in 4.0 or something. Steven |
#17
|
||||
|
||||
Actually I open Nico’s model and the tree and also realize that the model was a String Node and toggled as Flexscript.
But than I opened a new model and it had the same and I thought it’s normal. But I was in a hurry and did not dive into it. Now it is working and I am glad that we found the source of the issue. Thanks Guys, that you made clear what the problem was. tom the (A)tom
__________________
tom the (A)tom: "We have solved our problems ... now we have to fight the solutions." |
#18
|
|||
|
|||
Hello,
I was looking at Anthony Johnson's CoordinatedCartSharing model I was trying to do something similar. When you run Anthony's model, stop it and reset it, everything goes to its initial position. I tried to figure out how he does that by looking at the model, but I can't find where. May you please help me on this? Thanks, Alex, a green rookie. |
#19
|
||||
|
||||
Alex,
The operators and carts for the top group have had their reset position set. This is done by placing the object where you want it to reset to and then right clicking on it and selecting the "Set Object Reset Position" option. The operators for the bottom group have been connected to a network and so will set their position on reset to the node that they were connected to the network with. This is done when you first connect the operator to the network and can be changed by reconnecting the operator to another network node. Brandon
__________________
thats not normal. |
#20
|
|||
|
|||
Thank you for your help brandon,
I am trying to do something similar as Anthony's model, but having some difficulties. Enclosed is my model. Here is what I want to do: 1. The operator go to the Forklift (as the driver) 2. The forklift (with its driver) go to the queue 3. Load a piece 4. go to the sink 5. unload the piece 6. go to the initia position 7. The driver get out of the Forklift 8. He walk to the dispatcher. As you probably guess, my model is not doing that and I don't know why. Also, I would like my operator to be move in the lift as the driver instead of as a piece. Thanks a lot Alex |
Thread | Thread Starter | Forum | Replies | Last Post |
The transporter and operator task sequence... | syseo | Q&A | 1 | 09-22-2007 01:26 AM |
creating a batch trip task sequence | Paul Dowling | Q&A | 5 | 09-11-2007 06:55 PM |