办法1:从2016版本里面复制相应的代码
具体代码如下:
[code]treenode agv = param(1);
treenode currentCP = param(2);
{ //************* PickOption Start *************\\
/***popup:AGV_DivertToElevator*/
/***tag:Description*//**Divert to Elevator*/
int operation = param(3);
#define AGV_LABEL_NAME "fs_AGV_Elev_State"
if (operation == 0 && !objectexists(label(agv, AGV_LABEL_NAME))
&& (/** \nCondition: *//***tag:Condition*//**/fabs(zloc(currentCP) - zloc(agvinfo(agv, AGV_DEST_CP))) > zsize(agv)/**/)) { // if it's a pointer, then do the initial case
// initial trigger execution
#define ON_ELEVATOR_START 1
#define ON_ELEVATOR_PICKUP_ARRIVAL 2
#define ON_ELEVATOR_DROPOFF_ARRIVAL 3
#define ON_AGV_AT_CP 4
#define ON_BOTH_AT_PICKUP 5
#define ON_OPEN_DOOR 6
#define ON_CLOSE_DOOR 7
#define ON_PICKUP_DOOR_OPENED 8
#define ON_PICKUP_DOOR_CLOSED 9
#define ON_DROPOFF_DOOR_OPENED 10
#define ON_DROPOFF_DOOR_CLOSED 11
#define AGV_STATE_START 0
#define AGV_STATE_AT_ENTRY_CP 1
#define AGV_STATE_AT_ELEV_CP 2
#define AGV_STATE_AT_EXIT_CP 3
#define ELEV_STATE_NONE 0
#define ELEV_STATE_AT_PICKUP_FLOOR 1
#define ELEV_STATE_OPENING_DOOR 2
#define ELEV_STATE_DOOR_OPENED 3
treenode elevDisp = /** \nDispatcher: *//***tag:Dispatcher*//**/cpconnection(currentCP, "Elevators", 1)/**/;
#define elevator outobject(elevDisp, $iter(1))
if (!objectexists(elevDisp))
return 0;
if (/** \nDo Search: *//***tag:DoSearch*//**/1/**/) {
query(
/** \nFull Query: */
/***tag:FullQuery*//**/"SELECT $2 AS Elevator FROM $1 Elevators WHERE $3 ORDER BY $4 ASC LIMIT 1"/**/,
nrop(elevDisp),
elevator
/** \nWhere*/
/***tagex:WhereParams*/,/** \n*/ /**AND*/ /** */ /**/getstatenum(elevator) == STATE_IDLE /**/
/***/
/** \nOrderBy*/
/***tagex:OrderByParams*/,/** \n*/ /**/fabs(zloc(elevator) - zloc(agv))/**/ /**ASC*/
/***/);
if (getquerymatchcount() > 0)
elevDisp = getqueryvalue(1, 1);
}
if (!objectexists(elevDisp))
return 0;
treenode destCP = agvinfo(agv, AGV_DEST_CP);
agvredirect(agv, /** \nDivert Point When None Available: *//***tag:WaitDivertPoint*//**/currentCP/**/, REDIRECT_AND_WAIT);
// Create the task sequence for the elevator
double destZ = zloc(destCP);
treenode ts = createemptytasksequence(elevDisp, 0, 0);
inserttask(ts, TASKTYPE_TAG, agv, destCP);
// immediately when the elevator starts the task sequence, I call ON_ELEVATOR_START
inserttask(ts, TASKTYPE_NODEFUNCTION, c, 0, 0, ON_ELEVATOR_START, destZ);
// travel to the z location of the current control point
inserttask(ts, TASKTYPE_TRAVELTOLOC, 0, 0, 0, 0, zloc(currentCP));
// then call ON_ELEVATOR_PICKUP_ARRIVAL
inserttask(ts, TASKTYPE_NODEFUNCTION, c, 0, 0, ON_ELEVATOR_PICKUP_ARRIVAL);
// then wait for the agv to get on
inserttask(ts, TASKTYPE_UTILIZE, agv);
// then travel to the destination z location
inserttask(ts, TASKTYPE_TRAVELTOLOC, 0, 0, 0, 0, destZ);
// then call ON_ELEVATOR_DROPOFF_ARRIVAL
inserttask(ts, TASKTYPE_NODEFUNCTION, c, 0, 0, ON_ELEVATOR_DROPOFF_ARRIVAL);
inserttask(ts, TASKTYPE_UTILIZE, agv);
dispatchtasksequence(ts);
} else switch (operation) {
case ON_ELEVATOR_START: {
// this is fired when I get a valid elevator
treenode elev = param(1);
treenode agv = gettaskinvolved(gettasksequence(elev, 0), 1, 1);
// find the closest floor control point
int floorCPCon = cpconnection(0, /** \nFloor Control Point Connection:*//***tag:FloorCPs*//**/"Destination"/**/, 0);
treenode curFloorCP = findmin(cpnumconnections(elev, floorCPCon),
fabs(zloc(agv) - zloc(cpconnection(elev, floorCPCon, count))),
cpconnection(elev, floorCPCon, count));
// return if there is none
if (!objectexists(curFloorCP))
return 0;
// get the entry control point
treenode floorCP = curFloorCP;
treenode curFloorEntryCP = /** \nEntry Control Point: *//***tag:EntryCP*//**/cpconnection(floorCP, "EntryCP", 1)/**/;
if (!objectexists(curFloorEntryCP))
return 0;
treenode floorEntryCP = curFloorEntryCP;
treenode curFloorElevCP = /** \nElevator Control Point: *//***tag:ElevCP*//**/floorCP/**/;
if (!objectexists(curFloorElevCP))
return 0;
double destZ = param(4);
// find the floor control point closest to the destination floor
treenode destFloorCP = findmin(cpnumconnections(elev, floorCPCon),
fabs(destZ - zloc(cpconnection(elev, floorCPCon, count))),
cpconnection(elev, floorCPCon, count));
floorCP = destFloorCP;
treenode destFloorElevCP = /** \nDest Elevator Control Point: *//***tag:DestElevCP*//**/floorCP/**/;
if (!objectexists(destFloorElevCP))
return 0;
// get the destination exit control point
treenode destExitCP = /** \nExit Control Point: *//***tag:ExitCP*//**/cpconnection(floorCP, "ExitCP", 1)/**/;
if (!objectexists(destExitCP))
return 0;
// add a listener for the agv. This will call this nodefunction in the ON_AGV_AT_CP section whenever the
// agv arrives at a node. I keep a state on the agv's state label, and then increment it each time
// the listener is called so I know which control point he's at, i.e. entry, elev, or exit.
agvaddlistener(agv, c, AGV_LISTEN_ARRIVAL | AGV_LISTEN_INTERMEDIATE_DEST,
agv, elev, ON_AGV_AT_CP, AGV_LISTENER_PARAM_NODE);
// set the data on the state label
treenode stateLabel = assertlabel(agv, AGV_LABEL_NAME, DATATYPE_NUMBER);
switch_destroyonreset(stateLabel, 1);
set(stateLabel, AGV_STATE_START);
set(assertsubnode(stateLabel, "ElevState", DATATYPE_NUMBER), 0);
nodepoint(assertsubnode(stateLabel, "ElevCP", DATATYPE_COUPLING), curFloorElevCP);
nodepoint(assertsubnode(stateLabel, "DestElevCP", DATATYPE_COUPLING), destFloorElevCP);
nodepoint(assertsubnode(stateLabel, "ExitCP", DATATYPE_COUPLING), destExitCP);
agvredirect(agv, curFloorEntryCP, REDIRECT_AND_WAIT);
return 0;
}
case ON_AGV_AT_CP: {
// this is fired by the agv listener every time the agv arrives at a node.
treenode agv = param(1);
treenode elev = param(2);
treenode stateLabel = label(agv, AGV_LABEL_NAME);
// I increment the state label, and then switch on it
inc(stateLabel, 1);
switch (get(stateLabel)) {
case AGV_STATE_AT_ENTRY_CP: {
// the agv just arrived at the entry cp
// so, figure out where the elevator is.
int elevState = get(node("ElevState", stateLabel));
// if he's at the pickup floor with his door closed then open the door.
if (elevState == ELEV_STATE_AT_PICKUP_FLOOR)
nodefunction(c, agv, elev, ON_OPEN_DOOR, ON_PICKUP_DOOR_OPENED);
else if (elevState == ELEV_STATE_DOOR_OPENED) {
// if his door is alread opened, then move the agv onto the elevator, i.e. to
// the elevator cp
treenode elevatorCP = tonode(get(node("ElevCP", stateLabel)));
agvredirect(agv, elevatorCP, REDIRECT_AND_WAIT);
}
break;
}
case AGV_STATE_AT_ELEV_CP: {
// once the agv is at the elevator cp, close the door
nodefunction(c, agv, elev, ON_CLOSE_DOOR, ON_PICKUP_DOOR_CLOSED);
break;
}
case AGV_STATE_AT_EXIT_CP: {
// the agv is at the exit cp
// destroy the listener node because I'm finished listening
treenode listenerNode = param(4);
destroyobject(listenerNode);
int agvWait = /** \nWait On Door Close: *//***tag:WaitFinalDoorClose*//**/0/**/;
if (!agvWait) {
// if the agv is supposed to continue on, then tell him to go to his final destination
treenode destCP = gettaskinvolved(gettasksequence(elev, 0), 1, 2);
agvredirect(agv, destCP, REDIRECT_AS_FINAL);
}
// close the door
nodefunction(c, agv, elev, ON_CLOSE_DOOR, ON_DROPOFF_DOOR_CLOSED, agvWait);
// and I'm finished with the state label so I can destroy it.
destroyobject(stateLabel);
break;
}
}
return 0;
}
case ON_ELEVATOR_PICKUP_ARRIVAL: {
// the elevator has arrived at the pick floor
treenode elev = param(1);
treenode agv = gettaskinvolved(gettasksequence(elev, 0), 1, 1);
treenode stateLabel = label(agv, AGV_LABEL_NAME);
treenode elevState = node("ElevState", stateLabel);
// set the elevator state to at-pickup-floor
set(elevState, ELEV_STATE_AT_PICKUP_FLOOR);
int openDoorImmediately = /** \nOpen Elevator Door Immediately: *//***tag:OpenDoorImmediate*//**/0/**/;
// if the agv is at the entry control point or I open the door immediately, then open it
if (get(stateLabel) == AGV_STATE_AT_ENTRY_CP || openDoorImmediately) {
set(elevState, ELEV_STATE_OPENING_DOOR);
nodefunction(c, agv, elev, ON_OPEN_DOOR, ON_PICKUP_DOOR_OPENED);
}
return 0;
}
case ON_OPEN_DOOR: {
treenode agv = param(1);
treenode elev = param(2);
int nextStep = param(4);
// open the door based on the time to open the door
double openDoorTime = /** \nDoor Open Delay:*//***tag:DoorOpenTime*//**/5/**/;
delayednodefunction(c, openDoorTime, elev, agv, nextStep);
return 0;
}
case ON_CLOSE_DOOR: {
treenode agv = param(1);
treenode elev = param(2);
int nextStep = param(4);
// close the door base on the time to close the door
double delayTime = /** \nDoor Close Delay:*//***tag:DoorCloseTime*//**/5/**/;
delayednodefunction(c, delayTime, elev, agv, nextStep, param(5));
return 0;
}
case ON_PICKUP_DOOR_OPENED: {
// the elevator door has been opened on the pickup floor
treenode elev = param(1);
treenode agv = gettaskinvolved(gettasksequence(elev, 0), 1, 1);
treenode entryCP = cp(agv);
treenode stateLabel = label(agv, AGV_LABEL_NAME);
treenode elevatorCP = tonode(get(node("ElevCP", stateLabel)));
treenode elevState = node("ElevState", stateLabel);
// set the elevator state
set(elevState, ELEV_STATE_DOOR_OPENED);
// if the agv is at the entry control point, move him to the elevator control point
if (get(stateLabel) == AGV_STATE_AT_ENTRY_CP)
agvredirect(agv, elevatorCP, REDIRECT_AND_WAIT);
return 0;
}
case ON_PICKUP_DOOR_CLOSED: {
treenode elev = param(1);
treenode agv = gettaskinvolved(gettasksequence(elev, 0), 1, 1);
// assign the agv to "no control point"
agvreassigncp(agv, 0);
// move the agv into the elevator
moveobject(agv, elev);
setrot(agv, 0, 0, 0);
// release the elevator to continue to the destination floor
freeoperators(elev, agv);
return 0;
}
case ON_ELEVATOR_DROPOFF_ARRIVAL: {
treenode elev = param(1);
treenode agv = gettaskinvolved(gettasksequence(elev, 0), 1, 1);
// when the elevator arrives at the destination floor
// move the agv back into the model
moveobject(agv, model());
// reassign it to the destination floor control point
agvreassigncp(agv, tonode(get(node("DestElevCP", label(agv, AGV_LABEL_NAME)))));
// open the elevator door
nodefunction(c, agv, elev, ON_OPEN_DOOR, ON_DROPOFF_DOOR_OPENED);
return 0;
}
case ON_DROPOFF_DOOR_OPENED: {
treenode elev = param(1);
treenode agv = param(2);
treenode agvLabel = label(agv, AGV_LABEL_NAME);
// once the elevator door is opened on the destination floor,
// redirect the agv to the exit control point
agvredirect(agv, tonode(get(node("ExitCP", agvLabel))), REDIRECT_AND_WAIT);
return 0;
}
case ON_DROPOFF_DOOR_CLOSED: {
treenode elev = param(1);
treenode agv = param(2);
int isAGVWaiting = param(4);
// once the door is closed at the destination floor,
// if the agv is waiting, then send him to the final destination
if (isAGVWaiting)
agvredirect(agv, gettaskinvolved(gettasksequence(elev, 0), 1, 2), REDIRECT_AS_FINAL);
// release the elevator to finish his task sequence
freeoperators(elev, agv);
return 0;
}
}
} //******* PickOption End *******\\
[/code]
办法2:使用工艺流程模块完成 |