Path: blob/main/src/utils/vehicle/SUMOVehicleParameter.cpp
193967 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file SUMOVehicleParameter.cpp14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @date Tue, 31.03.200918///19// Structure representing possible vehicle parameter20/****************************************************************************/21#include <config.h>22#include <utils/common/MsgHandler.h>23#include <utils/common/StringTokenizer.h>24#include <utils/common/StringUtils.h>25#include <utils/common/ToString.h>26#include <utils/common/RandHelper.h>27#include <utils/iodevices/OutputDevice.h>28#include <utils/options/OptionsCont.h>2930#include "SUMOVehicleParameter.h"3132// ===========================================================================33// member method definitions34// ===========================================================================3536SUMOVehicleParameter::SUMOVehicleParameter()37: tag(SUMO_TAG_NOTHING), vtypeid(DEFAULT_VTYPE_ID), color(RGBColor::DEFAULT_COLOR),38depart(-1), departProcedure(DepartDefinition::GIVEN),39departLane(0), departLaneProcedure(DepartLaneDefinition::DEFAULT),40departPos(0), departPosProcedure(DepartPosDefinition::DEFAULT),41departPosLat(0), departPosLatProcedure(DepartPosLatDefinition::DEFAULT),42departSpeed(-1), departSpeedProcedure(DepartSpeedDefinition::DEFAULT),43departEdge(0), departEdgeProcedure(RouteIndexDefinition::DEFAULT),44arrivalLane(0), arrivalLaneProcedure(ArrivalLaneDefinition::DEFAULT),45arrivalPos(0), arrivalPosProcedure(ArrivalPosDefinition::DEFAULT),46arrivalPosLat(0), arrivalPosLatProcedure(ArrivalPosLatDefinition::DEFAULT),47arrivalSpeed(-1), arrivalSpeedProcedure(ArrivalSpeedDefinition::DEFAULT),48arrivalEdge(-1), arrivalEdgeProcedure(RouteIndexDefinition::DEFAULT),49repetitionNumber(-1),50repetitionsDone(-1),51repetitionOffset(-1),52repetitionTotalOffset(0),53repetitionProbability(-1),54poissonRate(0),55repetitionEnd(-1),56line(), fromTaz(), toTaz(), personNumber(0), containerNumber(0),57speedFactor(-1),58calibratorSpeed(-1),59insertionChecks((int)InsertionCheck::ALL),60parametersSet(0)61{ }626364SUMOVehicleParameter::~SUMOVehicleParameter() {65}666768bool69SUMOVehicleParameter::defaultOptionOverrides(const OptionsCont& oc, const std::string& optionName) const {70return oc.exists(optionName) && oc.isSet(optionName) && oc.getBool("defaults-override");71}727374void75SUMOVehicleParameter::write(OutputDevice& dev, const OptionsCont& oc, const SumoXMLTag altTag, const std::string& typeID) const {76if (!id.empty()) {77// only used by calibrator flows78dev.openTag(altTag).writeAttr(SUMO_ATTR_ID, id);79}80if (typeID == "") {81if (wasSet(VEHPARS_VTYPE_SET)) {82dev.writeAttr(SUMO_ATTR_TYPE, vtypeid);83}84} else {85dev.writeAttr(SUMO_ATTR_TYPE, typeID);86}87// write depart depending of tag88if (altTag == SUMO_TAG_FLOW89|| altTag == SUMO_TAG_PERSONFLOW90|| altTag == SUMO_TAG_CONTAINERFLOW91|| altTag == GNE_TAG_FLOW_ROUTE92|| altTag == GNE_TAG_FLOW_WITHROUTE93|| altTag == SUMO_TAG_FLOWSTATE) {94dev.writeAttr(SUMO_ATTR_BEGIN, getDepart());9596if (wasSet(VEHPARS_END_SET)) {97dev.writeAttr(SUMO_ATTR_END, time2string(repetitionEnd));98}99if (wasSet(VEHPARS_NUMBER_SET)) {100dev.writeAttr(SUMO_ATTR_NUMBER, repetitionNumber);101}102if (wasSet(VEHPARS_VPH_SET)) {103dev.writeAttr(SUMO_ATTR_PERHOUR, 3600 / STEPS2TIME(repetitionOffset));104}105// netedit uses VEHPARS_POISSON_SET106if (wasSet(VEHPARS_PERIOD_SET) || wasSet(VEHPARS_POISSON_SET)) {107if (repetitionOffset >= 0 && !wasSet(VEHPARS_POISSON_SET)) {108dev.writeAttr(SUMO_ATTR_PERIOD, StringUtils::adjustDecimalValue(STEPS2TIME(repetitionOffset), 20));109} else {110dev.writeAttr(SUMO_ATTR_PERIOD, "exp(" + StringUtils::adjustDecimalValue(poissonRate, 20) + ")");111}112}113if (wasSet(VEHPARS_PROB_SET) && repetitionProbability > 0) {114dev.writeAttr(SUMO_ATTR_PROB, StringUtils::adjustDecimalValue(repetitionProbability, 20));115}116} else {117dev.writeAttr(SUMO_ATTR_DEPART, getDepart());118}119// optional parameter120// departlane121if (wasSet(VEHPARS_DEPARTLANE_SET) && !defaultOptionOverrides(oc, "departlane")) {122dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, getDepartLane());123} else if (oc.exists("departlane") && oc.isSet("departlane")) {124dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTLANE, oc.getString("departlane"));125}126// departpos127if (wasSet(VEHPARS_DEPARTPOS_SET) && !defaultOptionOverrides(oc, "departpos")) {128dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, getDepartPos());129} else if (oc.exists("departpos") && oc.isSet("departpos")) {130dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS, oc.getString("departpos"));131}132// departPosLat133if (wasSet(VEHPARS_DEPARTPOSLAT_SET)) {134dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTPOS_LAT, getDepartPosLat());135}136// departspeed137if (wasSet(VEHPARS_DEPARTSPEED_SET) && !defaultOptionOverrides(oc, "departspeed")) {138dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, getDepartSpeed());139} else if (oc.exists("departspeed") && oc.isSet("departspeed")) {140dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTSPEED, oc.getString("departspeed"));141}142// departedge143if (wasSet(VEHPARS_DEPARTEDGE_SET) && !defaultOptionOverrides(oc, "departedge")) {144dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTEDGE, getDepartEdge());145} else if (oc.exists("departedge") && oc.isSet("departedge")) {146dev.writeNonEmptyAttr(SUMO_ATTR_DEPARTEDGE, oc.getString("departedge"));147}148// arrivallane149if (wasSet(VEHPARS_ARRIVALLANE_SET) && !defaultOptionOverrides(oc, "arrivallane")) {150dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, getArrivalLane());151} else if (oc.exists("arrivallane") && oc.isSet("arrivallane")) {152dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALLANE, oc.getString("arrivallane"));153}154// arrivalpos155if (wasSet(VEHPARS_ARRIVALPOS_SET) && !defaultOptionOverrides(oc, "arrivalpos")) {156dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, getArrivalPos());157} else if (oc.exists("arrivalpos") && oc.isSet("arrivalpos")) {158dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS, oc.getString("arrivalpos"));159}160// arrivalPosLat161if (wasSet(VEHPARS_ARRIVALPOSLAT_SET)) {162dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALPOS_LAT, getArrivalPosLat());163}164// arrivalspeed165if (wasSet(VEHPARS_ARRIVALSPEED_SET) && !defaultOptionOverrides(oc, "arrivalspeed")) {166dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, getArrivalSpeed());167} else if (oc.exists("arrivalspeed") && oc.isSet("arrivalspeed")) {168dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALSPEED, oc.getString("arrivalspeed"));169}170// arrivalEdge171if (wasSet(VEHPARS_ARRIVALEDGE_SET) && !defaultOptionOverrides(oc, "arrivaledge") && arrivalEdge >= 0) {172dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALEDGE, getArrivalEdge());173} else if (oc.exists("arrivaledge") && oc.isSet("arrivaledge")) {174dev.writeNonEmptyAttr(SUMO_ATTR_ARRIVALEDGE, oc.getString("arrivaledge"));175}176// color177if (wasSet(VEHPARS_COLOR_SET)) {178dev.writeAttr(SUMO_ATTR_COLOR, color);179}180// line181if (wasSet(VEHPARS_LINE_SET)) {182dev.writeAttr(SUMO_ATTR_LINE, line);183}184// from TAZ185if (wasSet(VEHPARS_FROM_TAZ_SET)) {186dev.writeAttr(SUMO_ATTR_FROM_TAZ, fromTaz);187}188// to TAZ189if (wasSet(VEHPARS_TO_TAZ_SET)) {190dev.writeAttr(SUMO_ATTR_TO_TAZ, toTaz);191}192// person number193if (wasSet(VEHPARS_PERSON_NUMBER_SET)) {194dev.writeAttr(SUMO_ATTR_PERSON_NUMBER, personNumber);195}196// container number197if (wasSet(VEHPARS_CONTAINER_NUMBER_SET)) {198dev.writeAttr(SUMO_ATTR_CONTAINER_NUMBER, containerNumber);199}200// individual speedFactor201if (wasSet(VEHPARS_SPEEDFACTOR_SET)) {202// might be saving state with custom precision203const int precision = dev.getPrecision();204dev.setPrecision(MAX2(gPrecisionRandom, precision));205dev.writeAttr(SUMO_ATTR_SPEEDFACTOR, speedFactor);206dev.setPrecision(precision);207}208// speed (only used by calibrators)209if (wasSet(VEHPARS_CALIBRATORSPEED_SET)) {210dev.writeAttr(SUMO_ATTR_SPEED, calibratorSpeed);211}212// insertionChecks213if (wasSet(VEHPARS_INSERTION_CHECKS_SET) && insertionChecks != (int)InsertionCheck::ALL) {214std::vector<std::string> checks;215if (insertionChecks == (int)InsertionCheck::NONE) {216checks.push_back(toString(InsertionCheck::NONE));217} else {218for (auto it : SUMOXMLDefinitions::InsertionChecks.getValues()) {219if (((int)it & insertionChecks) != 0) {220checks.push_back(toString(it));221}222}223}224dev.writeAttr(SUMO_ATTR_INSERTIONCHECKS, checks);225}226// parking access rights227if (wasSet(VEHPARS_PARKING_BADGES_SET)) {228dev.writeNonEmptyAttr(SUMO_ATTR_PARKING_BADGES, joinToString(parkingBadges, " "));229}230}231232233void234SUMOVehicleParameter::Stop::write(OutputDevice& dev, const bool close, const bool writeTagAndParents) const {235if (writeTagAndParents) {236dev.openTag(SUMO_TAG_STOP);237if (busstop != "") {238dev.writeAttr(SUMO_ATTR_BUS_STOP, busstop);239}240if (containerstop != "") {241dev.writeAttr(SUMO_ATTR_CONTAINER_STOP, containerstop);242}243if (chargingStation != "") {244dev.writeAttr(SUMO_ATTR_CHARGING_STATION, chargingStation);245}246if (parkingarea != "") {247dev.writeAttr(SUMO_ATTR_PARKING_AREA, parkingarea);248}249if ((busstop == "") && (containerstop == "") && (parkingarea == "") && (chargingStation == "")) {250if (lane != "") {251dev.writeAttr(SUMO_ATTR_LANE, lane);252} else {253dev.writeAttr(SUMO_ATTR_EDGE, edge);254}255if ((parametersSet & STOP_START_SET) != 0) {256dev.writeAttr(SUMO_ATTR_STARTPOS, startPos);257}258if ((parametersSet & STOP_END_SET) != 0) {259dev.writeAttr(SUMO_ATTR_ENDPOS, endPos);260}261}262}263if (index > 0) {264dev.writeAttr(SUMO_ATTR_INDEX, index);265}266if ((parametersSet & STOP_POSLAT_SET) != 0 && posLat != INVALID_DOUBLE) {267dev.writeAttr(SUMO_ATTR_POSITION_LAT, posLat);268}269if ((parametersSet & STOP_ARRIVAL_SET) && (arrival >= 0)) {270dev.writeAttr(SUMO_ATTR_ARRIVAL, time2string(arrival));271}272if ((parametersSet & STOP_DURATION_SET) && (duration >= 0)) {273dev.writeAttr(SUMO_ATTR_DURATION, time2string(duration));274}275if ((parametersSet & STOP_UNTIL_SET) && (until >= 0)) {276dev.writeAttr(SUMO_ATTR_UNTIL, time2string(until));277}278if ((parametersSet & STOP_STARTED_SET) && (started >= 0)) {279dev.writeAttr(SUMO_ATTR_STARTED, time2string(started));280}281if ((parametersSet & STOP_ENDED_SET) && (ended >= 0)) {282dev.writeAttr(SUMO_ATTR_ENDED, time2string(ended));283}284if ((parametersSet & STOP_EXTENSION_SET) && (extension >= 0)) {285dev.writeAttr(SUMO_ATTR_EXTENSION, time2string(extension));286}287if ((parametersSet & STOP_TRIGGER_SET) != 0) {288const std::vector<std::string> triggers = getTriggers();289if (triggers.size() > 0) {290dev.writeAttr(SUMO_ATTR_TRIGGERED, triggers);291}292}293if ((parametersSet & STOP_PARKING_SET) != 0) {294dev.writeAttr(SUMO_ATTR_PARKING, parking);295}296if ((parametersSet & STOP_EXPECTED_SET) != 0 && awaitedPersons.size() > 0) {297dev.writeAttr(SUMO_ATTR_EXPECTED, awaitedPersons);298}299if ((parametersSet & STOP_PERMITTED_SET) != 0 && permitted.size() > 0) {300dev.writeAttr(SUMO_ATTR_PERMITTED, permitted);301}302if ((parametersSet & STOP_EXPECTED_CONTAINERS_SET) != 0 && awaitedContainers.size() > 0) {303dev.writeAttr(SUMO_ATTR_EXPECTED_CONTAINERS, awaitedContainers);304}305if ((parametersSet & STOP_TRIP_ID_SET) != 0) {306dev.writeAttr(SUMO_ATTR_TRIP_ID, tripId);307}308if ((parametersSet & STOP_LINE_SET) != 0) {309dev.writeAttr(SUMO_ATTR_LINE, line);310}311if ((parametersSet & STOP_SPLIT_SET) != 0) {312dev.writeAttr(SUMO_ATTR_SPLIT, split);313}314if ((parametersSet & STOP_JOIN_SET) != 0) {315dev.writeAttr(SUMO_ATTR_JOIN, join);316}317if ((parametersSet & STOP_SPEED_SET) != 0) {318dev.writeAttr(SUMO_ATTR_SPEED, speed);319}320if ((parametersSet & STOP_ONDEMAND_SET) != 0) {321dev.writeAttr(SUMO_ATTR_ONDEMAND, onDemand);322}323if ((parametersSet & STOP_JUMP_SET) != 0 && jump >= 0) {324dev.writeAttr(SUMO_ATTR_JUMP, time2string(jump));325}326if ((parametersSet & STOP_JUMP_UNTIL_SET) != 0 && jumpUntil >= 0) {327dev.writeAttr(SUMO_ATTR_JUMP_UNTIL, time2string(jumpUntil));328}329if ((parametersSet & STOP_PRIORITY_SET) != 0 && priority >= 0) {330dev.writeAttr(SUMO_ATTR_PRIORITY, priority);331}332if (collision) {333dev.writeAttr(SUMO_ATTR_COLLISION, collision);334}335// only write friendly position if is true336if (friendlyPos) {337dev.writeAttr(SUMO_ATTR_FRIENDLY_POS, friendlyPos);338}339// only write act type if isn't empty340if (!actType.empty()) {341dev.writeAttr(SUMO_ATTR_ACTTYPE, actType);342}343if (close) {344// the user is closing the stop it is responsible for writing params345writeParams(dev);346dev.closeTag();347}348}349350std::vector<std::string>351SUMOVehicleParameter::Stop::getStoppingPlaceIDs() const {352std::vector<std::string> result;353if (busstop != "") {354result.push_back(busstop);355}356if (containerstop != "") {357result.push_back(containerstop);358}359if (chargingStation != "") {360result.push_back(chargingStation);361}362if (parkingarea != "") {363result.push_back(parkingarea);364}365return result;366}367368bool369SUMOVehicleParameter::parseDepart(const std::string& val, const std::string& element, const std::string& id,370SUMOTime& depart, DepartDefinition& dd, std::string& error, const std::string& attr) {371if (val == "triggered") {372dd = DepartDefinition::TRIGGERED;373} else if (val == "containerTriggered") {374dd = DepartDefinition::CONTAINER_TRIGGERED;375} else if (val == "now") {376// only used via TraCI. depart must be set by the calling code377dd = DepartDefinition::NOW;378} else if (val == "split") {379dd = DepartDefinition::SPLIT;380} else if (val == "begin") {381dd = DepartDefinition::BEGIN;382} else {383try {384depart = string2time(val);385dd = DepartDefinition::GIVEN;386if (depart < 0) {387error = "Negative " + attr + " time in the definition of " + element + " '" + id + "'.";388return false;389}390} catch (...) {391if (id.empty()) {392error = "Invalid " + attr + " time for " + element + ". Must be one of (\"triggered\", \"containerTriggered\", \"now\", or a float >= 0)";393} else {394error = "Invalid " + attr + " time for " + element + " '" + id + "';\n must be one of (\"triggered\", \"containerTriggered\", \"now\", or a float >= 0)";395}396return false;397}398}399return true;400}401402403bool404SUMOVehicleParameter::parseDepartLane(const std::string& val, const std::string& element, const std::string& id,405int& lane, DepartLaneDefinition& dld, std::string& error) {406bool ok = true;407lane = 0;408dld = DepartLaneDefinition::GIVEN;409if (val == "random") {410dld = DepartLaneDefinition::RANDOM;411} else if (val == "free") {412dld = DepartLaneDefinition::FREE;413} else if (val == "allowed") {414dld = DepartLaneDefinition::ALLOWED_FREE;415} else if (val == "best") {416dld = DepartLaneDefinition::BEST_FREE;417} else if (val == "best_prob") {418dld = DepartLaneDefinition::BEST_PROB;419} else if (val == "first") {420dld = DepartLaneDefinition::FIRST_ALLOWED;421} else {422try {423lane = StringUtils::toInt(val);424if (lane < 0) {425ok = false;426}427} catch (...) {428ok = false;429}430}431if (!ok) {432if (id.empty()) {433error = "Invalid departLane definition for " + element + ". Must be one of (\"random\", \"free\", \"allowed\", \"best\", \"best_prob\", \"first\", or an int>=0)";434} else {435error = "Invalid departLane definition for " + element + " '" + id + "';\n must be one of (\"random\", \"free\", \"allowed\", \"best\", \"best_prob\", \"first\", or an int>=0)";436}437}438return ok;439}440441442bool443SUMOVehicleParameter::parseDepartPos(const std::string& val, const std::string& element, const std::string& id,444double& pos, DepartPosDefinition& dpd, std::string& error) {445bool ok = true;446pos = 0.;447dpd = DepartPosDefinition::GIVEN;448if (val == "random") {449dpd = DepartPosDefinition::RANDOM;450} else if (val == "random_free") {451dpd = DepartPosDefinition::RANDOM_FREE;452} else if (val == "random_location") {453dpd = DepartPosDefinition::RANDOM_LOCATION;454} else if (val == "free") {455dpd = DepartPosDefinition::FREE;456} else if (val == "base") {457dpd = DepartPosDefinition::BASE;458} else if (val == "last") {459dpd = DepartPosDefinition::LAST;460} else if (val == "splitFront") {461dpd = DepartPosDefinition::SPLIT_FRONT;462} else if (val == "stop") {463dpd = DepartPosDefinition::STOP;464} else {465try {466pos = StringUtils::toDouble(val);467} catch (...) {468ok = false;469}470}471if (!ok) {472if (id.empty()) {473error = "Invalid departPos definition for " + element + ". Must be one of (\"random\", \"random_free\", \"free\", \"base\", \"last\" or a float)";474} else {475error = "Invalid departPos definition for " + element + " '" + id + "';\n must be one of (\"random\", \"random_free\", \"free\", \"base\", \"last\" or a float)";476}477}478return ok;479}480481482bool483SUMOVehicleParameter::parseDepartPosLat(const std::string& val, const std::string& element, const std::string& id,484double& pos, DepartPosLatDefinition& dpd, std::string& error) {485bool ok = true;486pos = 0.;487dpd = DepartPosLatDefinition::GIVEN;488if (val == "random") {489dpd = DepartPosLatDefinition::RANDOM;490} else if (val == "random_free") {491dpd = DepartPosLatDefinition::RANDOM_FREE;492} else if (val == "free") {493dpd = DepartPosLatDefinition::FREE;494} else if (val == "right") {495dpd = DepartPosLatDefinition::RIGHT;496} else if (val == "center") {497dpd = DepartPosLatDefinition::CENTER;498} else if (val == "left") {499dpd = DepartPosLatDefinition::LEFT;500} else {501try {502pos = StringUtils::toDouble(val);503} catch (...) {504ok = false;505}506}507if (!ok) {508if (id.empty()) {509error = "Invalid departPosLat definition for " + element + ". Must be one of (\"random\", \"random_free\", \"free\", \"right\", \"center\", \"left\", or a float)";510} else {511error = "Invalid departPosLat definition for " + element + " '" + id + "';\n must be one of (\"random\", \"random_free\", \"free\", \"right\", \"center\", \"left\", or a float)";512}513}514return ok;515}516517518bool519SUMOVehicleParameter::parseDepartSpeed(const std::string& val, const std::string& element, const std::string& id,520double& speed, DepartSpeedDefinition& dsd, std::string& error) {521bool ok = true;522speed = -1.;523dsd = DepartSpeedDefinition::GIVEN;524if (val == "random") {525dsd = DepartSpeedDefinition::RANDOM;526} else if (val == "max") {527dsd = DepartSpeedDefinition::MAX;528} else if (val == "desired") {529dsd = DepartSpeedDefinition::DESIRED;530} else if (val == "speedLimit") {531dsd = DepartSpeedDefinition::LIMIT;532} else if (val == "last") {533dsd = DepartSpeedDefinition::LAST;534} else if (val == "avg") {535dsd = DepartSpeedDefinition::AVG;536} else {537try {538speed = StringUtils::toDouble(val);539if (speed < 0) {540ok = false;541}542} catch (...) {543ok = false;544}545}546if (!ok) {547if (id.empty()) {548error = "Invalid departSpeed definition for " + element + ". Must be one of (\"random\", \"max\", or a float>=0)";549} else {550error = "Invalid departSpeed definition for " + element + " '" + id + "';\n must be one of (\"random\", \"max\", or a float>=0)";551}552}553return ok;554}555556557bool558SUMOVehicleParameter::parseRouteIndex(const std::string& val, const std::string& element, const std::string& id,559const SumoXMLAttr attr, int& edgeIndex, RouteIndexDefinition& rid, std::string& error) {560bool ok = true;561edgeIndex = -1;562rid = RouteIndexDefinition::GIVEN;563if (val == "random") {564rid = RouteIndexDefinition::RANDOM;565} else {566try {567edgeIndex = StringUtils::toInt(val);568if (edgeIndex < 0) {569ok = false;570}571} catch (...) {572ok = false;573}574}575if (!ok) {576if (id.empty()) {577error = "Invalid " + toString(attr) + " definition for " + element + ". Must be one of (\"random\", \"free\", or an int>=0)";578} else {579error = "Invalid " + toString(attr) + " definition for " + element + " '" + id + "';\n must be one of (\"random\", \"free\", or an int>=0)";580}581}582return ok;583}584585586bool587SUMOVehicleParameter::parseArrivalLane(const std::string& val, const std::string& element, const std::string& id,588int& lane, ArrivalLaneDefinition& ald, std::string& error) {589bool ok = true;590lane = 0;591ald = ArrivalLaneDefinition::GIVEN;592if (val == "current") {593ald = ArrivalLaneDefinition::CURRENT;594} else if (val == "random") {595ald = ArrivalLaneDefinition::RANDOM;596} else if (val == "first") {597ald = ArrivalLaneDefinition::FIRST_ALLOWED;598} else {599try {600lane = StringUtils::toInt(val);601if (lane < 0) {602ok = false;603}604} catch (...) {605ok = false;606}607}608if (!ok) {609if (id.empty()) {610error = "Invalid arrivalLane definition for " + element + ". Must be one of (\"current\", or an int>=0)";611} else {612error = "Invalid arrivalLane definition for " + element + " '" + id + "';\n must be one of (\"current\", or an int>=0)";613}614}615return ok;616}617618619bool620SUMOVehicleParameter::parseArrivalPos(const std::string& val, const std::string& element, const std::string& id,621double& pos, ArrivalPosDefinition& apd, std::string& error) {622bool ok = true;623pos = 0.;624apd = ArrivalPosDefinition::GIVEN;625if (val == "random") {626apd = ArrivalPosDefinition::RANDOM;627} else if (val == "center") {628apd = ArrivalPosDefinition::CENTER;629} else if (val == "max") {630apd = ArrivalPosDefinition::MAX;631} else {632try {633pos = StringUtils::toDouble(val);634} catch (...) {635ok = false;636}637}638if (!ok) {639if (id.empty()) {640error = "Invalid arrivalPos definition for " + element + ". Must be one of (\"random\", \"max\", or a float)";641} else {642error = "Invalid arrivalPos definition for " + element + " '" + id + "';\n must be one of (\"random\", \"max\", or a float)";643}644}645return ok;646}647648649bool650SUMOVehicleParameter::parseArrivalPosLat(const std::string& val, const std::string& element, const std::string& id,651double& pos, ArrivalPosLatDefinition& apd, std::string& error) {652bool ok = true;653pos = 0.;654apd = ArrivalPosLatDefinition::GIVEN;655if (val == "right") {656apd = ArrivalPosLatDefinition::RIGHT;657} else if (val == "center") {658apd = ArrivalPosLatDefinition::CENTER;659} else if (val == "left") {660apd = ArrivalPosLatDefinition::LEFT;661} else {662try {663pos = StringUtils::toDouble(val);664} catch (...) {665ok = false;666}667}668if (!ok) {669if (id.empty()) {670error = "Invalid arrivalPosLat definition for " + element + ". Must be one of (\"right\", \"center\", \"left\", or a float)";671} else {672error = "Invalid arrivalPosLat definition for " + element + " '" + id + "';\n must be one of (\"right\", \"center\", \"left\", or a float)";673}674}675return ok;676}677678679bool680SUMOVehicleParameter::parseArrivalSpeed(const std::string& val, const std::string& element, const std::string& id,681double& speed, ArrivalSpeedDefinition& asd, std::string& error) {682bool ok = true;683speed = -1.;684asd = ArrivalSpeedDefinition::GIVEN;685if (val == "current") {686asd = ArrivalSpeedDefinition::CURRENT;687} else {688try {689speed = StringUtils::toDouble(val);690if (speed < 0) {691ok = false;692}693} catch (...) {694ok = false;695}696}697if (!ok) {698if (id.empty()) {699error = "Invalid arrivalSpeed definition for " + element + ". Must be one of (\"current\", or a float>=0)";700} else {701error = "Invalid arrivalSpeed definition for " + element + " '" + id + "';\n must be one of (\"current\", or a float>=0)";702}703}704return ok;705}706707708double709SUMOVehicleParameter::interpretEdgePos(double pos, double maximumValue, SumoXMLAttr attr, const std::string& id, bool silent) {710if (pos < 0) {711pos = maximumValue + pos;712}713if (pos > maximumValue && pos != std::numeric_limits<double>::infinity()) {714if (!silent) {715WRITE_WARNINGF(TL("Invalid % % given for %. Using edge end instead."), toString(attr), toString(pos), id);716}717pos = maximumValue;718}719return pos;720}721722723bool724SUMOVehicleParameter::parsePersonModes(const std::string& modes, const std::string& element, const std::string& id, SVCPermissions& modeSet, std::string& error) {725// separte modes in different strings, and check if modes are valid726for (StringTokenizer st(modes); st.hasNext();) {727const std::string mode = st.next();728if (mode == "car") {729modeSet |= SVC_PASSENGER;730} else if (mode == "taxi") {731modeSet |= SVC_TAXI;732} else if (mode == "bicycle") {733modeSet |= SVC_BICYCLE;734} else if (mode == "public") {735modeSet |= SVC_BUS;736} else {737if (id.empty()) {738error = "Unknown person mode '" + mode + "'. Must be a combination of (\"car\", \"taxi\", \"bicycle\" or \"public\")";739} else {740error = "Unknown person mode '" + mode + "' for " + element + " '" + id + "';\n must be a combination of (\"car\", \"taxi\", \"bicycle\" or \"public\")";741}742return false;743}744}745return true;746}747748749void750SUMOVehicleParameter::parseStopTriggers(const std::vector<std::string>& triggers, bool expectTrigger, Stop& stop) {751if (triggers.size() == 0 && expectTrigger) {752stop.triggered = true;753}754for (std::string val : triggers) {755if (val == toString(SUMO_TAG_PERSON)) {756stop.triggered = true;757} else if (val == toString(SUMO_TAG_CONTAINER)) {758stop.containerTriggered = true;759} else if (val == toString(SUMO_ATTR_JOIN)) {760stop.joinTriggered = true;761} else {762try {763stop.triggered = StringUtils::toBool(val);764} catch (BoolFormatException&) {765WRITE_ERROR(TL("Value of stop attribute 'trigger' must be 'person', 'container', 'join' or a boolean"));766}767}768}769}770771772ParkingType773SUMOVehicleParameter::parseParkingType(const std::string& value) {774if (value == toString(ParkingType::OPPORTUNISTIC)) {775return ParkingType::OPPORTUNISTIC;776} else {777return StringUtils::toBool(value) ? ParkingType::OFFROAD : ParkingType::ONROAD;778}779}780781782std::vector<std::string>783SUMOVehicleParameter::Stop::getTriggers() const {784std::vector<std::string> triggers;785if (triggered) {786triggers.push_back(toString(SUMO_TAG_PERSON));787}788if (containerTriggered) {789triggers.push_back(toString(SUMO_TAG_CONTAINER));790}791if (joinTriggered) {792triggers.push_back(toString(SUMO_ATTR_JOIN));793}794return triggers;795}796797int798SUMOVehicleParameter::Stop::getFlags() const {799return (((parking == ParkingType::OFFROAD) ? 1 : 0) +800(triggered ? 2 : 0) +801(containerTriggered ? 4 : 0) +802(busstop != "" ? 8 : 0) +803(containerstop != "" ? 16 : 0) +804(chargingStation != "" ? 32 : 0) +805(parkingarea != "" ? 64 : 0) +806(overheadWireSegment != "" ? 128 : 0));807}808809810std::string811SUMOVehicleParameter::getDepart() const {812if (departProcedure == DepartDefinition::TRIGGERED) {813return "triggered";814} else if (departProcedure == DepartDefinition::CONTAINER_TRIGGERED) {815return "containerTriggered";816// } else if (departProcedure == DepartDefinition::NOW) { // TODO check whether this is useful in XML input (currently TraCI only)817// return "now";818} else if (departProcedure == DepartDefinition::SPLIT) {819return "split";820} else if (departProcedure == DepartDefinition::BEGIN) {821return "begin";822} else {823return time2string(depart);824}825}826827828std::string829SUMOVehicleParameter::getDepartLane() const {830std::string val;831switch (departLaneProcedure) {832case DepartLaneDefinition::GIVEN:833val = toString(departLane);834break;835case DepartLaneDefinition::RANDOM:836val = "random";837break;838case DepartLaneDefinition::FREE:839val = "free";840break;841case DepartLaneDefinition::ALLOWED_FREE:842val = "allowed";843break;844case DepartLaneDefinition::BEST_FREE:845val = "best";846break;847case DepartLaneDefinition::BEST_PROB:848val = "best_prob";849break;850case DepartLaneDefinition::FIRST_ALLOWED:851val = "first";852break;853case DepartLaneDefinition::DEFAULT:854default:855break;856}857return val;858}859860861std::string862SUMOVehicleParameter::getDepartPos() const {863std::string val;864switch (departPosProcedure) {865case DepartPosDefinition::GIVEN:866val = toString(departPos);867break;868case DepartPosDefinition::GIVEN_VEHROUTE:869val = StringUtils::pruneZeros(toString(departPos, MAX2(gPrecisionRandom, gPrecision)), 2);870break;871case DepartPosDefinition::RANDOM:872val = "random";873break;874case DepartPosDefinition::RANDOM_FREE:875val = "random_free";876break;877case DepartPosDefinition::RANDOM_LOCATION:878val = "random_location";879break;880case DepartPosDefinition::FREE:881val = "free";882break;883case DepartPosDefinition::LAST:884val = "last";885break;886case DepartPosDefinition::BASE:887val = "base";888break;889case DepartPosDefinition::SPLIT_FRONT:890val = "splitFront";891break;892case DepartPosDefinition::STOP:893val = "stop";894break;895case DepartPosDefinition::DEFAULT:896default:897break;898}899return val;900}901902903std::string904SUMOVehicleParameter::getDepartPosLat() const {905std::string val;906switch (departPosLatProcedure) {907case DepartPosLatDefinition::GIVEN:908val = toString(departPosLat);909break;910case DepartPosLatDefinition::GIVEN_VEHROUTE:911val = StringUtils::pruneZeros(toString(departPosLat, MAX2(gPrecisionRandom, gPrecision)), 2);912break;913case DepartPosLatDefinition::RANDOM:914val = "random";915break;916case DepartPosLatDefinition::RANDOM_FREE:917val = "random_free";918break;919case DepartPosLatDefinition::FREE:920val = "free";921break;922case DepartPosLatDefinition::RIGHT:923val = "right";924break;925case DepartPosLatDefinition::CENTER:926val = "center";927break;928case DepartPosLatDefinition::LEFT:929val = "left";930break;931case DepartPosLatDefinition::DEFAULT:932default:933break;934}935return val;936}937938939std::string940SUMOVehicleParameter::getDepartSpeed() const {941std::string val;942switch (departSpeedProcedure) {943case DepartSpeedDefinition::GIVEN:944val = toString(departSpeed);945break;946case DepartSpeedDefinition::GIVEN_VEHROUTE:947val = StringUtils::pruneZeros(toString(departSpeed, MAX2(gPrecisionRandom, gPrecision)), 2);948break;949case DepartSpeedDefinition::RANDOM:950val = "random";951break;952case DepartSpeedDefinition::MAX:953val = "max";954break;955case DepartSpeedDefinition::DESIRED:956val = "desired";957break;958case DepartSpeedDefinition::LIMIT:959val = "speedLimit";960break;961case DepartSpeedDefinition::LAST:962val = "last";963break;964case DepartSpeedDefinition::AVG:965val = "avg";966break;967case DepartSpeedDefinition::DEFAULT:968default:969break;970}971return val;972}973974975std::string976SUMOVehicleParameter::getDepartEdge() const {977std::string val;978switch (departEdgeProcedure) {979case RouteIndexDefinition::GIVEN:980val = toString(departEdge);981break;982case RouteIndexDefinition::RANDOM:983val = "random";984break;985case RouteIndexDefinition::DEFAULT:986default:987break;988}989return val;990}991992std::string993SUMOVehicleParameter::getArrivalEdge() const {994std::string val;995switch (arrivalEdgeProcedure) {996case RouteIndexDefinition::GIVEN:997val = toString(arrivalEdge);998break;999case RouteIndexDefinition::RANDOM:1000val = "random";1001break;1002case RouteIndexDefinition::DEFAULT:1003default:1004break;1005}1006return val;1007}10081009101010111012std::string1013SUMOVehicleParameter::getArrivalLane() const {1014std::string val;1015switch (arrivalLaneProcedure) {1016case ArrivalLaneDefinition::GIVEN:1017val = toString(arrivalLane);1018break;1019case ArrivalLaneDefinition::CURRENT:1020val = "current";1021break;1022case ArrivalLaneDefinition::RANDOM:1023val = "random";1024break;1025case ArrivalLaneDefinition::FIRST_ALLOWED:1026val = "first";1027break;1028case ArrivalLaneDefinition::DEFAULT:1029default:1030break;1031}1032return val;1033}103410351036std::string1037SUMOVehicleParameter::getArrivalPos() const {1038std::string val;1039switch (arrivalPosProcedure) {1040case ArrivalPosDefinition::GIVEN:1041val = toString(arrivalPos);1042break;1043case ArrivalPosDefinition::RANDOM:1044val = "random";1045break;1046case ArrivalPosDefinition::CENTER:1047val = "center";1048break;1049case ArrivalPosDefinition::MAX:1050val = "max";1051break;1052case ArrivalPosDefinition::DEFAULT:1053default:1054break;1055}1056return val;1057}105810591060std::string1061SUMOVehicleParameter::getArrivalPosLat() const {1062std::string val;1063switch (arrivalPosLatProcedure) {1064case ArrivalPosLatDefinition::GIVEN:1065val = toString(arrivalPosLat);1066break;1067case ArrivalPosLatDefinition::RIGHT:1068val = "right";1069break;1070case ArrivalPosLatDefinition::CENTER:1071val = "center";1072break;1073case ArrivalPosLatDefinition::LEFT:1074val = "left";1075break;1076case ArrivalPosLatDefinition::DEFAULT:1077default:1078break;1079}1080return val;1081}108210831084std::string1085SUMOVehicleParameter::getArrivalSpeed() const {1086std::string val;1087switch (arrivalSpeedProcedure) {1088case ArrivalSpeedDefinition::GIVEN:1089val = toString(arrivalSpeed);1090break;1091case ArrivalSpeedDefinition::CURRENT:1092val = "current";1093break;1094case ArrivalSpeedDefinition::DEFAULT:1095default:1096break;1097}1098return val;1099}110011011102void1103SUMOVehicleParameter::incrementFlow(double scale, SumoRNG* rng) {1104repetitionsDone++;1105// equidistant or exponential offset (for poisson distributed arrivals)1106if (repetitionProbability < 0) {1107if (repetitionOffset >= 0) {1108repetitionTotalOffset += (SUMOTime)((double)repetitionOffset / scale);1109} else {1110assert(poissonRate > 0);1111// we need to cache this do avoid double generation of the rng in the TIME2STEPS macro1112const double r = RandHelper::randExp(poissonRate, rng);1113repetitionTotalOffset += TIME2STEPS(r / scale);1114}1115}1116}111711181119std::string1120SUMOVehicleParameter::getInsertionChecks() const {1121if ((insertionChecks == 0) || (insertionChecks == (int)InsertionCheck::ALL)) {1122return SUMOXMLDefinitions::InsertionChecks.getString(InsertionCheck::ALL);1123} else {1124std::vector<std::string> insertionChecksStrs;1125const auto insertionCheckValues = SUMOXMLDefinitions::InsertionChecks.getValues();1126// iterate over values1127for (const auto insertionCheckValue : insertionCheckValues) {1128if ((insertionCheckValue != InsertionCheck::ALL) && (insertionChecks & (int)insertionCheckValue) != 0) {1129insertionChecksStrs.push_back(SUMOXMLDefinitions::InsertionChecks.getString(insertionCheckValue));1130}1131}1132return toString(insertionChecksStrs);1133}1134}113511361137bool1138SUMOVehicleParameter::areInsertionChecksValid(const std::string& value) const {1139if (value.empty()) {1140return true;1141} else {1142// split value in substrinsg1143StringTokenizer valueStrs(value, " ");1144// iterate over values1145while (valueStrs.hasNext()) {1146if (!SUMOXMLDefinitions::InsertionChecks.hasString(valueStrs.next())) {1147return false;1148}1149}1150return true;1151}1152}115311541155int1156SUMOVehicleParameter::parseInsertionChecks(const std::string& value) {1157// first reset insertionChecks1158int result = 0;1159if (value.empty()) {1160return (int)InsertionCheck::ALL;1161} else {1162// split value in substrinsg1163StringTokenizer insertionCheckStrs(value, " ");1164while (insertionCheckStrs.hasNext()) {1165std::string val = insertionCheckStrs.next();1166if (SUMOXMLDefinitions::InsertionChecks.hasString(val)) {1167result |= (int)SUMOXMLDefinitions::InsertionChecks.get(val);1168} else {1169throw InvalidArgument("Unknown value '" + val + "' in " + toString(SUMO_ATTR_INSERTIONCHECKS) + ".");1170}1171}1172}1173return result;1174}11751176/****************************************************************************/117711781179