In a pedwait entity, I want each element that enters to have my own specified coordinates. I use the method: ped.setXY(100,100), but it has no effect. What should I do?
First you need to read the Java doc when using a new function.
The setXY function states "Sets the coordinates of the agent location. Should only be used to initialize the agent location. Assumes the agent is not moving."
The other options that I would have suggested if you were using normal agents would be to use jumpto() or moveTo() but if you try these in a pedestrian model you will get an UnsupportedOperationException error.
Pedestrians are special kind of agents so you can use all the normal agent functions on them.
The correct way to do this is to use the waiting location inside the Wait block
Related
This model simulates cars pulling up to pumps at a gas/petrol station. I have a custom car agent 'MyCar' that passes through an upstream stopline. At this stopline it calls the agent's function which checks the availability of the two pump stations in the roadNetwork in Main. This function returns a RoadNetworkConstant 'PASS_THROUGH_STOP_LINE' or 'STOP_BEFORE_STOP_LINE'.
I'm unable to pass this constant value back into the 'Stop line behavior' property in a CarMoveTo block (for a different stop line further downstream but before the car reaches the pumps) in Main even when I start typing the name of my agent 'MyCar'.
Is it possible to change the Stop Line Behavior dynamically? If so, is this a resonable approach? If not, what would you suggest?
You need to use 'car', not 'MyCar'. Check out the magic light bulb and how keywords work for you: https://www.google.com/url?q=https://www.benjamin-schumann.com/blog/2016/2/4/the-magic-lightbulb-and-how-it-can-help-your-anylogic-modelling&sa=U&ved=2ahUKEwiuz-ytq9D8AhWsSvEDHZccDTUQFnoECAkQAg&usg=AOvVaw3XapUwKyi_Bi9_2JjGrN0b
In my model I am transporting (path guided) several types of products (motors) by an agv trough a manufacturing line with 27 cycles. It´s a flowing manufacturing line. That means the product gets manufactured while the agv is constantly running.
To model that I created an agent population called "motors" with parameter "axelType" (string) which is loaded from column "axel_type" in database "manufacturing_sequence" (local excelsheet) and is placed on Main.
Each motor is placed on an transporter "agvAssembly" (in Flowchart as: Transporter) and runs from node "locationCycle1" all the way to "locationCycle27".
Now I want to change the transporters speed at each of the 27 cycle nodes dependent on the currently loaded motor. To do that I got another database called "speeds_axel" which includes all the needed speeds for the cycles and respective parameter name for axelType (column axel_type).
So now, when the transporter enters a node I have to check first the nodes name. Than I want to read out the parameter "axelType" of the currently in that node entered agent "Motor" and search in the database for the respective speed.
In the block "transporter Fleet" - "On enter node:" I wrote as an example for cycle 1 the following:
if (node == locationCycle1) {
unit.setMaximumSpeed(
selectFrom(speeds_axel)
.where(speeds_axel.axel_type.eq(motor.axelType))
.firstResult(false, speeds_axel.cycle1)/60.0,MPS);
}
When running the model I get the following error:
"motor cannot be resolved to a variable"
(location: TransporterFleet)
I think that error accures because my approach doesn't specify which motor I mean. How can I clarify to AnyLogic that I always mean the current motor which enters the node?
I need something like this:
if (node == locationCycle1) {
unit.setMaximumSpeed(
selectFrom(speeds_axel)
.where(speeds_axel.axel_type.eq("get motor which is currently in locationCycle1".axelType))
.firstResult(false, speeds_axel.cycle1)/60.0,MPS);
}
the biggest problem in your model is that you don't follow conventions. An agent type should be named with an uppercase first letter
Why is this important? Because you want to make the difference between Motor, motor, and motors
Motor is the class (or Agent Type)
motor is an instance of that class (or agent type)
motors is a population.
Since you don't follow this convention, you make mistakes of this kind since motor is a class
in your case when you do motor.cycle1
if you followed the conventions, you would be doing
Motor.cycle1 (which is obvioulsy wrong)
Note that Motor is the Agent Type name, and what you really want is to know for a particular motor what the value of cycle1 is
The first thing you need to do with this model, is get back to using the conventions, and this will probably solve this problem and many problems in the future.
Just because you have a population called motors (which the agents within your flow 'come from' --- though it looks like they don't actually; see later), this does not mean that you can 'magically' refer to the current agent via the singular form motor at any point in the code. (And, similarly, your agent type being Motor does not mean you can use the lower-case form to refer to 'the current one'.)
In Transporter Fleet block "On enter node" actions, you refer to the current transporter via the unit keyword; see the help page. The motor is not the transporter; it's the thing being transported.
So, just use the "On exit" (or, better, "On at exit") actions of your MoveByTransporter blocks (which trigger on arrival at the destination node), where you can refer to the current motor (the agent in the flow) via the agent keyword; again, see the block help.
But, from a quick glance, there appear to be a few important changes/simplifications you should also make (though hard to definitively tell without details of all your code):
You are using a Source block to add agents (motors) to the flow when you have already created the motors in your population. You should be using an Enter block instead to add the (already-existing) Motor agents to the flow at the appropriate time (triggered by code: I imagine you want one to start at model start time, requiring code in Main's "On startup" action, and then others added either at certain simulation times or when earlier motors reach a certain stage in the process...). If your population was actually just for 'templates' of data for each motor axle type (and you would then potentially create multiple instances of motors for a given axle type) then your current logic might make sense, but your screenshot of your manufacturing_sequence table makes clear that isn't the case. (If you did go that route, you would want to rename your population so that its purpose was clear.)
It looks like you have a 'looping' process (with the same process behaviour for all your in-sequence nodes), so you should look to make your process generic with an explicit loop (so you don't have near-copies of blocks for every node in your sequence). There is a fair amount of detail in terms of how you do this but roughly:
Track the node the motor is currently in (or its sequence number) via a variable in the Motor agent.
Use a collection (List) which contains the nodes-in-order to determine where it has to go to next.
Your process would have a MoveByTransporter --> Delay --> SelectOutput sequence (plus TimeMeasureStart/End if you're using them), where SelectOutput loops back to the MoveByTransporter if the motor is not yet at the last node.
I don't know why the resources don't follow the path in order to arrive the pallet rack. I thought it was because of the path (maybe not linked) but with a moveto block the problem disappears.What's the reason?
All the paths are bidirectional.
The problem that you have is the issue of teleportation... you move your boxes teleporting them from one node to the next by using the agent location parameter of the rackstore... This has the effect that the agents do not belong to the network as you expect.
instead you need to use a moveTo block instead as you see in the following image
Notice that I removed the agent location from the rackStore and also in the moveTo block i use JumpTo option instead of moveTo so you maintain the teleportation as you did...
Anyways, teleporting is not very good
Is it possible to modify agent's variable by tracing it's position whether it's inside or outside a certain node?
I have a string variable position inside pedestrian which I want to define depending if agent is outside, inside green or red node (ex. "Green", "Red" or "None".).
I digged up the following code that works fine where it comes to tracing if agents are inside a given node or not, but I don't know how to use it so it actually modifies a variable inside an agent.
nodeGreen.getPeds(),p->node.contains(p.getX(),p.getY())
my simple model with green and red node
new agent - "pedestrian" with string variable
Many thanks for help,
Peter
Well, you need to periodically check within the Pedestrian agent and adjust the variable accordingly.
Best set a cyclic event that executes:
if (main.nodeGreen.contains(getX(), getY()) {
position = "Green"
} else if // ... do for the other types
Side note: using Strings here is very error-prone and not scalable. Maybe create a function instead in your Pedestrian agent type such as f_getCurrentNode that returns a Node using the (adjusted) code above. Make it return null if the ped is in no node. Now, you can dynamically check for each agent where it is.
I plan to use two types of agents in my simulation.
For one agent type I plan to use set the position explicitly by the setXYZ() method called in the "On startup" action of that agent type.
Fort the second agent type I plan to use one of the predefined layout patterns (random or ring) as described in:
https://help.anylogic.com/index.jsp?topic=%2Fcom.anylogic.help%2Fhtml%2Fagentbased%2FContinuous_Layouts.html
The problem is the following code placed in in the "On startup" action of the Main agent type doesn't differentiante between my two agent types (and places all the agents in a circle e.g.):
setLayoutType(Agent.LAYOUT_RING);
applyLayout();
Shall I somehow modify the code above (as I've tried already) or is there another way?
I think the layout type has to be the same for all agents present in the space... nevertheless... you can do this:
//first you apply the ring layout to everything
setLayoutType(Agent.LAYOUT_RING);
applyLayout();
//then you define the type of agent you don't want to follow the ring layout separately
for(int i=0;i<100;i++){//assuming you will create 100 agents initially
MyAgent p=add_myAgents();//you need to create your agents after the ring layout is applied though..
p.setXY(uniform(0,500), uniform(0,500));//assuming your agents are in a 500x500 square in main
}
I don't know if there is a better way... but this is what I know is possible