Robot pick-and-place

All topics on coding 4Dscript in Enterprise Dynamics.
raguthri
Posts: 7
Joined: Wednesday 25 May, 2011 - 10:22

Robot pick-and-place

Post by raguthri »

Hi,

I haven't used ED for a while so I'm a little rusty, hence my turning to this forum. Hope you guys can help!

I'm trying to model a simple system where I have a queue of items and a robot picks up the first item and places it at one of four "test" stations. The item must visit each station once before it can leave the system. The robot moves the items between each station. I need it to be able to place the items from the source into any of the four stations (whichever one is free), and once the item has visited all four stations, to then place it into the sink. Additionally, I need to robot to always be working, so it's either moving an item from one station to the next, or picking up a new item from the source queue and placing into a free station.

How do I go about writing a script for this? I assume I need each station to give the item a label and when it has accumulated a label from all four stations, then the robot sends it to the sink.

I hope I explained this properly!

Cheers,
Rabi
JeroenSteenbakkers
Posts: 16
Joined: Tuesday 11 January, 2011 - 09:34

Re: Robot pick-and-place

Post by JeroenSteenbakkers »

hello rabi,

what i propose is that you use label.

on the exit trigger of the station you can use for instance:

Code: Select all

label([counter], i) := 2
Based on this label you can then send it to the right output channel of the robot, for instance:

Code: Select all

if(
 label([counter], first(c)) = 2, 
 3,
 2
)

the code means, if the label on the atom is 2 then move it to channel 3 else to channel 2.

Good luck!
raguthri
Posts: 7
Joined: Wednesday 25 May, 2011 - 10:22

Re: Robot pick-and-place

Post by raguthri »

Jeroen,

Thanks for the reply!

I understand this part of the script, but I need the atom to move to any of a number of other empty stations,

i.e.

if(
label([counter],first(c)) = 1,
1,
2,
)

if the label on the atom is 1, then move to channel 1 else to channel 2.

I want it to say "if the label on the atom is 1, then move to channel 1 else to channel 2 OR 3 OR 4.

Once it's visited the station, and then say the next station gives it another label (let's say "2"), then does the atom have both labels (i.e. 1 and 2).

How do I get the robot to send the atom to the sink once it has visited all of the stations? There is no specific order in which the atom has to visit each station (they all have different operating times so the order will inevitably change from atom to atom), but each atom must visit each station, only once.

I hope this makes sense?
MarvinH
Posts: 93
Joined: Tuesday 25 January, 2011 - 11:07
Contact:

Re: Robot pick-and-place

Post by MarvinH »

Hello Rabi!

Maybe try using a string! Each of the four stations is labelled with "StationNr" 1, 2, 3 or 4. Add a label on the product, called "VisitedStations". In case a product exits a particular station, add "*StationNr" to the label "VisitedStations" of the product.

Code: Select all

Label([VisitedStations], atmProduct) := Concat(Label([VisitedStations], atmProduct), [*], String(Label([StationNr], atmStation) ) )
For example, in case a product has vistied station 3 and 1, the label "VisitedStations" would look like "*3*1".

Now, in case a product is finished, you can determine whether it has to visite a particular station by checking whether the StationNr is present in its "VisitedStations" label.

Code: Select all

StringPos(String(Label([StationNr], atmStation)), Label([VisitedStations], atmProduct)) > 0
So, for the product mentioned in the previous example, the check above will return True for station 3 and 1 (and thus it can be sent to station 2 or 4, based on the status of the station). In case the check returns True for all four stations, (i.e. the string looks something like "*3*1*2*4"), it can be sent to the sink.

Hope the idea is clear to you and it suits your problem.

Kind regards,

Marvin
raguthri
Posts: 7
Joined: Wednesday 25 May, 2011 - 10:22

Re: Robot pick-and-place

Post by raguthri »

Marvin,

Thanks for the reply. I understand it in writing, you definitely understand what it is I am trying to do, but I just cannot understand the code or where to place it! I tried using your script but just got the robot to continuously send an atom back and forth to the first station over and over. I'll explain my exact layout below to give you a better view:

Here's the order of play:

Source attached to Queue (labelled "HOME").
In the Source atom, I put the following script into the "inter-arrival time" part;

Label([VisitedStations], c)

I assume this adds a label (called "VisitedStations") to each product exiting the source.

The queue is then attached to a Robot. This in turn is attached to four stations, as well as a sink.

Each station I have renamed "Station1" through to "Station4". The sink is labelled "Station5".

On the robot, channel 1/send is attached to "Station1", channel 1/receive is also attached to "Station1". This goes through to channel 4 send/receive attached to "Station4". The initial queue which the Source feeds into, labelled "HOME" and the sink are both attached to channel 5 on the robot - the source to the receiving part and the sink to the sending part of channel 5). Hope I've still got you!

In order to prevent the system becoming blocked, I have made the capacity of the queue (being fed by the source) to only three products. This stops the robot from filling all four stations and thus not then being able to move them about between stations.

Using your 4DS, I assume I want to assign each station (Station1 through to Station4) with a Trigger on exit, so that products build a record of each station it has visited);

Here's your code;

Label([VisitedStations], atmProduct) := Concat(Label([VisitedStations], atmProduct), [*], String(Label([StationNr], atmStation) ) )

And here's my code, which I put into StationNr1, in "Trigger on exit";

Label([VisitedStations], c) := Concat(Label([VisitedStations], c), [*], String(Label([StationNr], 1) ) )

I substituted "atmProduct" for "c" (the current product), and substituted "atmStation" for "1". For the other stations I just changed the atmStation part to the corresponding station name (i.e. 1 for StationNr1, 2 for StationNr2, etc.).

I'm pretty sure I got this part wrong, as I was just guessing that this is what you meant.

Moving on,

The second script you wrote, which I assumed was meant for the Robot;

StringPos(String(Label([StationNr], atmStation)), Label([VisitedStations], atmProduct)) > 0

I'm not entirely sure how to use this script, or if I'm even right in assuming it goes into the robot if I'm honest..

I assume this script needs to be put into the robot, in the "Send to" part, commanding the robot that if the product has accumulated visits to all four stations, then it can go to the sink. If it hasn't visited all four stations, then the robot needs to send that product to one of the remaining stations that the product hasn't yet visited (whichever one is free).

I'm basically pretty lost here. Obviously I don't understand 4DS as well as I thought, because this all feels well above my head! I know exactly what I'm trying to achieve, I just don't know enough about 4DS to be able to execute it...

I really hope you understand this, as I'm pretty lost right now. If someone is available in real-time so I can go through this step-by-step, that would be great.

Any other help mucho gracias!

Rabi
MarvinH
Posts: 93
Joined: Tuesday 25 January, 2011 - 11:07
Contact:

Re: Robot pick-and-place

Post by MarvinH »

Hello Rabi!

The idea of your model is clear to me, the channel connections seem right!

Unfortunately you did not implement the labelling part correctly. Let's start with the source. The "inter-arrival time" field should not be used for setting labels, only to determine the time after which the next product arrives. Instead, move your code to the ExitTrigger of the source and replace "c" by "i", as we want to set the label of the involved atom (i.e. product) and not the current atom (i.e. source).

ExitTrigger Source:

Code: Select all

{ * Initialize the label with an empty string * }
Label([VisitedStations], i) := []
On the ExitTrigger of the stations, your code alters labels of the stations, as "c" (reference to the current atom) refers to the station. You can solve this by using "i" (reference to the involved atom) instead of where I used "atmProduct".

ExitTrigger StationNr1:

Code: Select all

Label([VisitedStations], i) := Concat(Label([VisitedStations], i), [*], String(1) )
In order to use the code on other stations, replace the "1" in the String function by the corresponding StationNr (i.e. just replace 1 by 2, 3 and 4 respectively).

You are right that the second script should be used on the SendTo statement of the Robot! What you need to do, is check which stations the product still has to go to and determine whether this station is available. Below, you can find the script that should work for you.

Code: Select all

Do(
  { * Determine the output channel * }
  Var([valChannel], vbValue, 0),
  
  LoopUntil(
    { * Loop over output channels until we have found a station to send the product to * }
    valChannel > 0,
    { * Check the station * }
    If(
      And(
        { * Check whether station is ready to receive a product * }
        ICOpen(OcIcNo(Count, c), Out(Count, c)),
        { * Check whether the product has not visited Station yet * }
        StringPos(String(Count), Label([VisitedStations], First(c))) = 0
      ),
      { * Both station is available and product should still visit it * }
      valChannel := Count
    ),
    { * Only loop over the first 4 output channels * }
    4
  ),
  
  If(
    valChannel = 0,
    { * Not found a station, check whether it can be sent to the sink * }
    If(
      { * In case all stations are visited, the string should count 8 characters * }
      StringLength(Label([VisitedStations], First(c))) = 8,
      { * All stations are visited, send product to sink * }
      valChannel := 5,
      { * Not all stations are visited, but none is available, display message to user * }
      Msg([Product cannot be sent to a station, although it has not visited all yet!], 3)
    )
  ),
  
  { * Return the channel we have found * }
  valChannel
)
In case you need some help with some of the functions used above, please refer to the Enterprise Dynamics Help File. Note that although you already figured out that deadlocks can occur, limiting the number of products to three does not prevent the system from deadlocks!

Kind regards,

Marvin
raguthri
Posts: 7
Joined: Wednesday 25 May, 2011 - 10:22

Re: Robot pick-and-place

Post by raguthri »

Marvin,

Your a genius! Thank you so much for working out all that code. Having looked at it I'm 110% I never would have figured that out myself. Thanks for putting the comments into the code so I can work out what each part means. That's a real help.

You right about the deadlocks. Once I started running the simulation I realised that limiting the source to 3 doesn't do anything, as the robot still keeps picking more up! I guess I have to introduce a limiter on the source so that 1 new product is only created once 1 product enters the sink (i.e. leaves the system), that way there are no more than 3 products in the 4 stations at any one time, thus preventing a deadlock. This would mean that the queue atom is not needed at all right?

I found an atom called Condition Control which I think is the one I'm looking for. I've attached the input ("listening") channel to the sink, and attached the output ("controlling") channel to the source. I guess I want to create command which only opens the output channel and omits one products, for every one product which enters the sink.

This is where it gets complicated. I need the source to initially produce 3 products (which the robot will pick up and put into 3 of the fours stations), but then only produce any additional products once a product enters the sink. Basically a drip-feed effect (one-in-one-out system). This should stop the deadlock effect I'm getting...

I tried using the help section of ED to work out how to use it but don't know the language needed to execute this.

The sink is set to only produce 60 products (that's my limit), so essentially I only want this 'drip-feed' command to take effect once the first 3 products have left the source (57 remaining).

Can I create a code which only takes effect once the source has created and pushed out 3 products?

Rabi
MarvinH
Posts: 93
Joined: Tuesday 25 January, 2011 - 11:07
Contact:

Re: Robot pick-and-place

Post by MarvinH »

Hello Rabi!

The "drip-feed-effect", as you called it, is easy to implement, even without Condition Control. I would keep the queue behind the source, and put the following code OnExit of the source:

Code: Select all

If(
  Output(c) >= 3,
  CloseOutput(c)
)
This stops the source from creating more than three products. Now, you want to create (or release) one product as soon as a product enters the sink. This can be done by connecting the second input channel of the sink to the central channel of the source, and putting the following code OnEntry of the sink:

Code: Select all

OpenOutput(In(2, c))
This way one product is release from the source, which will trigger the exit trigger of the source. The output of the source will be greater than three, so the output is closed until the next product enters the sink again.

With the code above there will never be more than three products in the system simultaneously. However, I still think there can be deadlocks, even with two products in the system, so maybe you can think of another solution. ;)

Good luck!

Kind regards,

Marvin
raguthri
Posts: 7
Joined: Wednesday 25 May, 2011 - 10:22

Re: Robot pick-and-place

Post by raguthri »

Simples!

How do I put your first piece of code into the source. I already have the following code in the "trigger on exit" part;

Label([VisitedStations], i) := []

I thought I could just add a comma and place your code on the end but that doesn't work..
MarvinH
Posts: 93
Joined: Tuesday 25 January, 2011 - 11:07
Contact:

Re: Robot pick-and-place

Post by MarvinH »

Hello Rabi,

The function to execute multiple 4DScript statements successively is the "Do" function... This and other functions can be found in the Basic category of the Enterprise Dynamics Help File.

In this case, put a "Do" function (with brackets) around your two statements and it will work.

Regards,

Marvin
Post Reply