1 %module libsumo 2 #pragma SWIG nowarn=511 3 4 #ifdef SWIGPYTHON 5 %rename(edge) Edge; 6 %rename(inductionloop) InductionLoop; 7 %rename(junction) Junction; 8 %rename(lane) Lane; 9 %rename(lanearea) LaneArea; 10 %rename(multientryexit) MultiEntryExit; 11 %rename(person) Person; 12 %rename(poi) POI; 13 %rename(polygon) Polygon; 14 %rename(route) Route; 15 %rename(simulation) Simulation; 16 %rename(trafficlight) TrafficLight; 17 %rename(vehicle) Vehicle; 18 %rename(vehicletype) VehicleType; 19 20 // adding dummy init and close for easier traci -> libsumo transfer 21 %pythoncode %{ 22 from traci import constants, exceptions, _vehicle, _person, _trafficlight 23 24 def isLibsumo(): 25 return True 26 27 def init(port): 28 print("Warning! To make your code usable with traci and libsumo, please use traci.start instead of traci.init.") 29 30 def close(): 31 simulation.close() 32 33 def start(args): 34 simulation.load(args[1:]) 35 36 def simulationStep(step=0): 37 simulation.step(step) 38 %} 39 40 /* There is currently no TraCIPosition used as input so this is only for future usage 41 %typemap(in) const libsumo::TraCIPosition& (libsumo::TraCIPosition pos) { 42 const Py_ssize_t size = PySequence_Size($input); 43 if (size == 2 || size == 3) { 44 pos.x = PyFloat_AsDouble(PySequence_GetItem($input, 0)); 45 pos.y = PyFloat_AsDouble(PySequence_GetItem($input, 1)); 46 pos.z = (size == 3 ? PyFloat_AsDouble(PySequence_GetItem($input, 2)) : 0.); 47 } else { 48 // TODO error handling 49 } 50 $1 = &pos; 51 } 52 */ 53 54 %typemap(in) const libsumo::TraCIPositionVector& (libsumo::TraCIPositionVector shape) { 55 const Py_ssize_t size = PySequence_Size($input); 56 for (Py_ssize_t i = 0; i < size; i++) { 57 PyObject* posTuple = PySequence_GetItem($input, i); 58 const Py_ssize_t posSize = PySequence_Size(posTuple); 59 libsumo::TraCIPosition pos; 60 if (posSize == 2 || posSize == 3) { 61 PyObject* item = PySequence_GetItem(posTuple, 0); 62 pos.x = PyFloat_Check(item) ? PyFloat_AsDouble(item) : PyLong_AsDouble(item); 63 item = PySequence_GetItem(posTuple, 1); 64 pos.y = PyFloat_Check(item) ? PyFloat_AsDouble(item) : PyLong_AsDouble(item); 65 pos.z = 0.; 66 if (posSize == 3) { 67 item = PySequence_GetItem(posTuple, 2); 68 pos.z = PyFloat_Check(item) ? PyFloat_AsDouble(item) : PyLong_AsDouble(item); 69 } 70 } else { 71 // TODO error handling 72 } 73 shape.push_back(pos); 74 } 75 $1 = &shape; 76 } 77 78 %typemap(in) const libsumo::TraCIColor& (libsumo::TraCIColor col) { 79 const Py_ssize_t size = PySequence_Size($input); 80 if (size == 3 || size == 4) { 81 col.r = (unsigned char)PyLong_AsLong(PySequence_GetItem($input, 0)); 82 col.g = (unsigned char)PyLong_AsLong(PySequence_GetItem($input, 1)); 83 col.b = (unsigned char)PyLong_AsLong(PySequence_GetItem($input, 2)); 84 col.a = (unsigned char)(size == 4 ? PyLong_AsLong(PySequence_GetItem($input, 3)) : 255); 85 } else { 86 // TODO error handling 87 } 88 $1 = &col; 89 } 90 91 %typemap(in) const std::vector<int>& (std::vector<int> vars) { 92 const Py_ssize_t size = PySequence_Size($input); 93 for (Py_ssize_t i = 0; i < size; i++) { 94 vars.push_back(PyLong_AsLong(PySequence_GetItem($input, i))); 95 } 96 $1 = &vars; 97 } 98 99 %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) const std::vector<int>& { 100 $1 = PySequence_Check($input) ? 1 : 0; 101 } 102 103 104 %typemap(out) std::map<int, std::shared_ptr<libsumo::TraCIResult> > { 105 $result = PyDict_New(); 106 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 107 const int theKey = iter->first; 108 const libsumo::TraCIResult* const theVal = iter->second.get(); 109 const libsumo::TraCIDouble* const theDouble = dynamic_cast<const libsumo::TraCIDouble*>(theVal); 110 if (theDouble != nullptr) { 111 PyDict_SetItem($result, PyInt_FromLong(theKey), PyFloat_FromDouble(theDouble->value)); 112 continue; 113 } 114 const libsumo::TraCIInt* const theInt = dynamic_cast<const libsumo::TraCIInt*>(theVal); 115 if (theInt != nullptr) { 116 PyDict_SetItem($result, PyInt_FromLong(theKey), PyInt_FromLong(theInt->value)); 117 continue; 118 } 119 const libsumo::TraCIString* const theString = dynamic_cast<const libsumo::TraCIString*>(theVal); 120 if (theString != nullptr) { 121 PyDict_SetItem($result, PyInt_FromLong(theKey), PyUnicode_FromString(theString->value.c_str())); 122 continue; 123 } 124 const libsumo::TraCIStringList* const theStringList = dynamic_cast<const libsumo::TraCIStringList*>(theVal); 125 if (theStringList != nullptr) { 126 const Py_ssize_t size = theStringList->value.size(); 127 PyObject* tuple = PyTuple_New(size); 128 for (Py_ssize_t i = 0; i < size; i++) { 129 PyTuple_SetItem(tuple, i, PyUnicode_FromString(theStringList->value[i].c_str())); 130 } 131 PyDict_SetItem($result, PyInt_FromLong(theKey), tuple); 132 continue; 133 } 134 const libsumo::TraCIPosition* const thePosition = dynamic_cast<const libsumo::TraCIPosition*>(theVal); 135 if (thePosition != nullptr) { 136 PyObject* tuple; 137 if (thePosition->z != libsumo::INVALID_DOUBLE_VALUE) { 138 tuple = PyTuple_Pack(3, PyFloat_FromDouble(thePosition->x), PyFloat_FromDouble(thePosition->y), PyFloat_FromDouble(thePosition->z)); 139 } else { 140 tuple = PyTuple_Pack(2, PyFloat_FromDouble(thePosition->x), PyFloat_FromDouble(thePosition->y)); 141 } 142 PyDict_SetItem($result, PyInt_FromLong(theKey), tuple); 143 continue; 144 } 145 const libsumo::TraCIRoadPosition* const theRoadPosition = dynamic_cast<const libsumo::TraCIRoadPosition*>(theVal); 146 if (theRoadPosition != nullptr) { 147 PyObject* tuple; 148 if (theRoadPosition->laneIndex != libsumo::INVALID_INT_VALUE) { 149 tuple = PyTuple_Pack(3, PyUnicode_FromString(theRoadPosition->edgeID.c_str()), PyFloat_FromDouble(theRoadPosition->pos), PyInt_FromLong(theRoadPosition->laneIndex)); 150 } else { 151 tuple = PyTuple_Pack(2, PyUnicode_FromString(theRoadPosition->edgeID.c_str()), PyFloat_FromDouble(theRoadPosition->pos)); 152 } 153 PyDict_SetItem($result, PyInt_FromLong(theKey), tuple); 154 continue; 155 } 156 PyObject *value = SWIG_NewPointerObj(SWIG_as_voidptr(theVal), SWIGTYPE_p_libsumo__TraCIResult, 0); 157 PyDict_SetItem($result, PyInt_FromLong(theKey), value); 158 } 159 }; 160 161 %typemap(out) libsumo::TraCIPosition { 162 if ($1.z != libsumo::INVALID_DOUBLE_VALUE) { 163 $result = PyTuple_Pack(3, PyFloat_FromDouble($1.x), PyFloat_FromDouble($1.y), PyFloat_FromDouble($1.z)); 164 } else { 165 $result = PyTuple_Pack(2, PyFloat_FromDouble($1.x), PyFloat_FromDouble($1.y)); 166 } 167 }; 168 169 %typemap(out) libsumo::TraCIPositionVector { 170 $result = PyTuple_New($1.size()); 171 int index = 0; 172 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 173 PyTuple_SetItem($result, index++, PyTuple_Pack(2, PyFloat_FromDouble(iter->x), PyFloat_FromDouble(iter->y))); 174 } 175 }; 176 177 %typemap(out) libsumo::TraCIColor { 178 $result = PyTuple_Pack(4, PyLong_FromLong($1.r), PyLong_FromLong($1.g), PyLong_FromLong($1.b), PyLong_FromLong($1.a)); 179 }; 180 181 %typemap(out) libsumo::TraCIRoadPosition { 182 $result = PyTuple_Pack(3, PyUnicode_FromString($1.edgeID.c_str()), PyFloat_FromDouble($1.pos), PyLong_FromLong($1.laneIndex)); 183 }; 184 185 %typemap(out) std::vector<libsumo::TraCIConnection> { 186 $result = PyList_New($1.size()); 187 int index = 0; 188 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 189 PyList_SetItem($result, index++, PyTuple_Pack(8, PyUnicode_FromString(iter->approachedLane.c_str()), 190 PyBool_FromLong(iter->hasPrio), 191 PyBool_FromLong(iter->isOpen), 192 PyBool_FromLong(iter->hasFoe), 193 PyUnicode_FromString(iter->approachedInternal.c_str()), 194 PyUnicode_FromString(iter->state.c_str()), 195 PyUnicode_FromString(iter->direction.c_str()), 196 PyFloat_FromDouble(iter->length))); 197 } 198 }; 199 200 %typemap(out) std::vector<libsumo::TraCIVehicleData> { 201 $result = PyList_New($1.size()); 202 int index = 0; 203 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 204 PyList_SetItem($result, index++, PyTuple_Pack(5, PyUnicode_FromString(iter->id.c_str()), 205 PyFloat_FromDouble(iter->length), 206 PyFloat_FromDouble(iter->entryTime), 207 PyFloat_FromDouble(iter->leaveTime), 208 PyUnicode_FromString(iter->typeID.c_str()))); 209 } 210 }; 211 212 %typemap(out) std::vector<libsumo::TraCIBestLanesData> { 213 $result = PyTuple_New($1.size()); 214 int index = 0; 215 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 216 const int size = (int)iter->continuationLanes.size(); 217 auto nextLanes = PyTuple_New(size); 218 for (int i = 0; i < size; i++) { 219 PyTuple_SetItem(nextLanes, i, PyUnicode_FromString(iter->continuationLanes[i].c_str())); 220 } 221 PyTuple_SetItem($result, index++, PyTuple_Pack(6, PyUnicode_FromString(iter->laneID.c_str()), 222 PyFloat_FromDouble(iter->length), 223 PyFloat_FromDouble(iter->occupation), 224 PyFloat_FromDouble(iter->bestLaneOffset), 225 PyBool_FromLong(iter->allowsContinuation), 226 nextLanes)); 227 } 228 }; 229 230 %typemap(out) std::vector<libsumo::TraCINextTLSData> { 231 $result = PyTuple_New($1.size()); 232 int index = 0; 233 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 234 PyTuple_SetItem($result, index++, PyTuple_Pack(4, PyUnicode_FromString(iter->id.c_str()), 235 PyLong_FromLong(iter->tlIndex), 236 PyFloat_FromDouble(iter->dist), 237 PyUnicode_FromStringAndSize(&iter->state, 1))); 238 } 239 }; 240 241 %typemap(out) std::vector<libsumo::TraCINextStopData> { 242 $result = PyTuple_New($1.size()); 243 int index = 0; 244 for (auto iter = $1.begin(); iter != $1.end(); ++iter) { 245 PyTuple_SetItem($result, index++, PyTuple_Pack(6, PyUnicode_FromString(iter->lane.c_str()), 246 PyFloat_FromDouble(iter->endPos), 247 PyUnicode_FromString(iter->stoppingPlaceID.c_str()), 248 PyLong_FromLong(iter->stopFlags), 249 PyFloat_FromDouble(iter->duration), 250 PyFloat_FromDouble(iter->until))); 251 } 252 }; 253 254 %typemap(out) std::pair<int, int> { 255 $result = PyTuple_Pack(2, PyLong_FromLong($1.first), PyLong_FromLong($1.second)); 256 }; 257 258 %typemap(out) std::pair<std::string, double> { 259 $result = PyTuple_Pack(2, PyUnicode_FromString($1.first.c_str()), PyFloat_FromDouble($1.second)); 260 }; 261 262 %extend libsumo::TraCIStage { 263 %pythoncode %{ 264 def __repr__(self): 265 return "Stage(%s)" % (", ".join(["%s=%s" % (attr, repr(getter(self))) for attr, getter in self.__swig_getmethods__.items()])) 266 %} 267 }; 268 269 %exceptionclass libsumo::TraCIException; 270 271 #endif 272 273 %begin %{ 274 #ifdef _MSC_VER 275 // ignore constant conditional expression and unreachable code warnings 276 #pragma warning(disable:4127 4702) 277 #endif 278 %} 279 280 281 // replacing vector instances of standard types, see https://stackoverflow.com/questions/8469138 282 %include "std_string.i" 283 %include "std_vector.i" 284 %template(StringVector) std::vector<std::string>; 285 286 // exception handling 287 %include "exception.i" 288 289 // taken from here https://stackoverflow.com/questions/1394484/how-do-i-propagate-c-exceptions-to-python-in-a-swig-wrapper-library 290 %exception { 291 try { 292 $action 293 } catch (libsumo::TraCIException &e) { 294 const std::string s = std::string("Error: ") + e.what(); 295 #ifdef SWIGPYTHON 296 PyErr_SetObject(SWIG_Python_ExceptionType(SWIGTYPE_p_libsumo__TraCIException), PyUnicode_FromString(s.c_str())); 297 SWIG_fail; 298 #else 299 SWIG_exception(SWIG_ValueError, s.c_str()); 300 #endif 301 } catch (std::runtime_error &e) { 302 const std::string s = std::string("SUMO error: ") + e.what(); 303 SWIG_exception(SWIG_RuntimeError, s.c_str()); 304 } catch (...) { 305 SWIG_exception(SWIG_UnknownError, "unknown exception"); 306 } 307 } 308 309 // %feature("compactdefaultargs") libsumo::Simulation::findRoute; 310 311 // Add necessary symbols to generated header 312 %{ 313 #include <libsumo/TraCIDefs.h> 314 #include <libsumo/Edge.h> 315 #include <libsumo/InductionLoop.h> 316 #include <libsumo/Junction.h> 317 #include <libsumo/LaneArea.h> 318 #include <libsumo/Lane.h> 319 #include <libsumo/MultiEntryExit.h> 320 #include <libsumo/POI.h> 321 #include <libsumo/Polygon.h> 322 #include <libsumo/Route.h> 323 #include <libsumo/Simulation.h> 324 #include <libsumo/TrafficLight.h> 325 #include <libsumo/VehicleType.h> 326 #include <libsumo/Vehicle.h> 327 #include <libsumo/Person.h> 328 %} 329 330 // Process symbols in header 331 %include "TraCIDefs.h" 332 %template(TraCIConnectionVector) std::vector<libsumo::TraCIConnection>; 333 %template(TraCILogicVector) std::vector<libsumo::TraCILogic>; 334 %template(TraCIStageVector) std::vector<libsumo::TraCIStage>; 335 %include "Edge.h" 336 %include "InductionLoop.h" 337 %include "Junction.h" 338 %include "LaneArea.h" 339 %include "Lane.h" 340 %include "MultiEntryExit.h" 341 %include "POI.h" 342 %include "Polygon.h" 343 %include "Route.h" 344 %include "Simulation.h" 345 %include "TraCIConstants.h" 346 %include "TrafficLight.h" 347 %include "VehicleType.h" 348 %include "Vehicle.h" 349 %include "Person.h" 350 351 #ifdef SWIGPYTHON 352 %pythoncode %{ 353 def wrapAsClassMethod(func, module): 354 def wrapper(*args, **kwargs): 355 return func(module, *args, **kwargs) 356 return wrapper 357 358 exceptions.TraCIException = TraCIException 359 trafficlight.Phase = TraCIPhase 360 trafficlight.Logic = TraCILogic 361 vehicle.addFull = vehicle.add 362 vehicle.addLegacy = wrapAsClassMethod(_vehicle.VehicleDomain.addLegacy, vehicle) 363 vehicle.couldChangeLane = wrapAsClassMethod(_vehicle.VehicleDomain.couldChangeLane, vehicle) 364 vehicle.wantsAndCouldChangeLane = wrapAsClassMethod(_vehicle.VehicleDomain.wantsAndCouldChangeLane, vehicle) 365 vehicle.isStopped = wrapAsClassMethod(_vehicle.VehicleDomain.isStopped, vehicle) 366 vehicle.setBusStop = wrapAsClassMethod(_vehicle.VehicleDomain.setBusStop, vehicle) 367 vehicle.setParkingAreaStop = wrapAsClassMethod(_vehicle.VehicleDomain.setParkingAreaStop, vehicle) 368 person.removeStages = wrapAsClassMethod(_person.PersonDomain.removeStages, person) 369 trafficlight.setLinkState = wrapAsClassMethod(_trafficlight.TrafficLightDomain.setLinkState, trafficlight) 370 %} 371 #endif 372