Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merged TraCI module taken from https://github.com/sommer/inet-sommer @

  • Loading branch information...
commit cd7fd58041a8986938ce8197a3ac3d3b87e9b524 1 parent ba9d76e
@rhornig rhornig authored
Showing with 100,134 additions and 219 deletions.
  1. +677 −0 etc/sumo-launchd.py
  2. +96 −0 examples/traci/Car.ned
  3. +37 −0 examples/traci/Highway.ned
  4. +5 −0 examples/traci/README
  5. +2 −0  examples/traci/debug
  6. +2 −0  examples/traci/memcheck
  7. +48,199 −0 examples/traci/net.net.xml
  8. +65 −0 examples/traci/omnetpp.ini
  9. +15 −0 examples/traci/routes.rou.xml
  10. +2 −0  examples/traci/run
  11. +25 −0 examples/traci/scenario.ned
  12. +18 −0 examples/traci/sumo.sumo.cfg
  13. +96 −0 examples/traci_launchd/Car.ned
  14. +37 −0 examples/traci_launchd/Highway.ned
  15. +6 −0 examples/traci_launchd/README
  16. +2 −0  examples/traci_launchd/debug
  17. +2 −0  examples/traci_launchd/memcheck
  18. +48,199 −0 examples/traci_launchd/net.net.xml
  19. +66 −0 examples/traci_launchd/omnetpp.ini
  20. +15 −0 examples/traci_launchd/routes.rou.xml
  21. +2 −0  examples/traci_launchd/run
  22. +25 −0 examples/traci_launchd/scenario.ned
  23. +8 −0 examples/traci_launchd/sumo-launchd.launch.xml
  24. +14 −0 examples/traci_launchd/sumo.sumo.cfg
  25. +85 −0 src/applications/traci/TraCIDemo.cc
  26. +58 −0 src/applications/traci/TraCIDemo.h
  27. +34 −0 src/applications/traci/TraCIDemo.ned
  28. +213 −0 src/applications/traci/TraCITestApp.cc
  29. +59 −0 src/applications/traci/TraCITestApp.h
  30. +33 −0 src/applications/traci/TraCITestApp.ned
  31. +173 −172 src/mobility/models/TraCIMobility.cc
  32. +28 −7 src/mobility/models/TraCIMobility.h
  33. +12 −4 src/mobility/models/TraCIMobility.ned
  34. +56 −11 src/world/traci/TraCIScenarioManager.cc
  35. +41 −8 src/world/traci/TraCIScenarioManager.h
  36. +18 −5 src/world/traci/TraCIScenarioManager.ned
  37. +1 −1  src/world/traci/TraCIScenarioManagerLaunchd.cc
  38. +15 −3 src/world/traci/TraCIScenarioManagerLaunchd.h
  39. +21 −8 src/world/traci/TraCIScenarioManagerLaunchd.ned
  40. +89 −0 tests/traci/Car.ned
  41. +41 −0 tests/traci/Highway.ned
  42. +71 −0 tests/traci/net.edg.xml
  43. +1,298 −0 tests/traci/net.net.xml
  44. +17 −0 tests/traci/net.netconvert.cfg
  45. +38 −0 tests/traci/net.nod.xml
  46. +63 −0 tests/traci/omnetpp.ini
  47. +1 −0  tests/traci/package.ned
  48. +3 −0  tests/traci/polys.poly.xml
  49. +5 −0 tests/traci/routes.rou.xml
  50. +3 −0  tests/traci/runTest.sh
  51. +10 −0 tests/traci/sumo-launchd.launch.xml
  52. +15 −0 tests/traci/sumo.sumo.cfg
  53. +18 −0 tests/traci/tls.tls.xml
View
677 etc/sumo-launchd.py
@@ -0,0 +1,677 @@
+#!/usr/bin/env python
+
+#
+# sumo-launchd.py -- SUMO launcher daemon for use with TraCI clients
+# Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+#
+# Documentation for these modules is at http://veins.car2x.org/
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+For each incoming TCP connection the daemon receives a launch configuration.
+It starts SUMO accordingly, then proxies all TraCI Messages.
+
+The launch configuration must be sent in the very first TraCI message.
+This message must contain a single command, CMD_FILE_SEND and be used to
+send a file named "sumo-launchd.launch.xml", which has the following
+structure:
+
+<?xml version="1.0"?>
+<launch>
+ <basedir path="/home/sommer/src/inet/examples/erlangen6" />
+ <seed value="1234" />
+ <copy file="net.net.xml" />
+ <copy file="routes.rou.xml" />
+ <copy file="sumo.sumo.cfg" type="config" />
+</launch>
+"""
+
+import os
+import sys
+import tempfile
+import shutil
+import socket
+import struct
+import subprocess
+import time
+import signal
+import exceptions
+import thread
+import xml.dom.minidom
+import select
+import logging
+import atexit
+from optparse import OptionParser
+
+_API_VERSION = 1
+_LAUNCHD_VERSION = 'sumo-launchd.py 1.00'
+_CMD_GET_VERSION = 0x00
+_CMD_FILE_SEND = 0x75
+
+class UnusedPortLock:
+ lock = thread.allocate_lock()
+
+ def __init__(self):
+ self.acquired = False
+
+ def __enter__(self):
+ self.acquire()
+
+ def __exit__(self):
+ self.release()
+
+ def acquire(self):
+ if not self.acquired:
+ logging.debug("Claiming lock on port")
+ UnusedPortLock.lock.acquire()
+ self.acquired = True
+
+ def release(self):
+ if self.acquired:
+ logging.debug("Releasing lock on port")
+ UnusedPortLock.lock.release()
+ self.acquired = False
+
+def find_unused_port():
+ """
+ Return an unused port number.
+ """
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+ sock.bind(('127.0.0.1', 0))
+ sock.listen(socket.SOMAXCONN)
+ ipaddr, port = sock.getsockname()
+ sock.close()
+ return port
+
+
+def forward_connection(client_socket, server_socket, process):
+ """
+ Proxy connections until either socket runs out of data or process terminates.
+ """
+
+ logging.debug("Starting proxy mode")
+
+ client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+
+ do_exit = False
+ while not do_exit:
+
+ (r, w, e) = select.select([client_socket, server_socket], [], [client_socket, server_socket], 1)
+ if client_socket in e:
+ do_exit = True
+ break
+ if server_socket in e:
+ do_exit = True
+ break
+ if client_socket in r:
+ try:
+ data = client_socket.recv(65535)
+ if data == "":
+ do_exit = True
+ except:
+ do_exit = True
+ finally:
+ server_socket.send(data)
+ if server_socket in r:
+ try:
+ data = server_socket.recv(65535)
+ if data == "":
+ do_exit = True
+ except:
+ do_exit = True
+ finally:
+ client_socket.send(data)
+
+ rc = process.poll()
+ if (rc != None):
+ do_exit = True
+ break
+
+ logging.debug("Done with proxy mode")
+
+
+def parse_launch_configuration(launch_xml_string):
+ """
+ Returns tuple of options set in launch configuration
+ """
+
+ p = xml.dom.minidom.parseString(launch_xml_string)
+
+ # get root node "launch"
+ launch_node = p.documentElement
+ if (launch_node.tagName != "launch"):
+ raise RuntimeError("launch config root element not <launch>, but <%s>" % launch_node.tagName)
+
+ # get "launch.basedir"
+ basedir = ""
+ basedir_nodes = [x for x in launch_node.getElementsByTagName("basedir") if x.parentNode==launch_node]
+ if len(basedir_nodes) > 1:
+ raise RuntimeError('launch config contains %d <basedir> nodes, expected at most 1' % (len(basedir_nodes)))
+ elif len(basedir_nodes) == 1:
+ basedir = basedir_nodes[0].getAttribute("path")
+ logging.debug("Base dir is %s" % basedir)
+
+ # get "launch.seed"
+ seed = 23423
+ seed_nodes = [x for x in launch_node.getElementsByTagName("seed") if x.parentNode==launch_node]
+ if len(seed_nodes) > 1:
+ raise RuntimeError('launch config contains %d <seed> nodes, expected at most 1' % (len(seed_nodes)))
+ elif len(seed_nodes) == 1:
+ seed = int(seed_nodes[0].getAttribute("value"))
+ logging.debug("Seed is %d" % seed)
+
+ # get list of "launch.copy" entries
+ copy_nodes = [x for x in launch_node.getElementsByTagName("copy") if x.parentNode==launch_node]
+
+ return (basedir, copy_nodes, seed)
+
+
+def run_sumo(runpath, sumo_command, shlex, config_file_name, remote_port, seed, client_socket, unused_port_lock, keep_temp):
+ """
+ Actually run SUMO.
+ """
+
+ # create log files
+ sumoLogOut = open(os.path.join(runpath, 'sumo-launchd.out.log'), 'w')
+ sumoLogErr = open(os.path.join(runpath, 'sumo-launchd.err.log'), 'w')
+
+ # start SUMO
+ sumo_start = int(time.time())
+ sumo_end = None
+ sumo_returncode = -1
+ sumo_status = None
+ try:
+ cmd = []
+ if shlex:
+ import shlex
+ cmd = shlex.split(sumo_command.replace('{}', '-c ' + unicode(config_file_name).encode()))
+ else:
+ cmd = [sumo_command, "-c", config_file_name]
+ logging.info("Starting SUMO (%s) on port %d, seed %d" % (" ".join(cmd), remote_port, seed))
+ sumo = subprocess.Popen(cmd, cwd=runpath, stdin=None, stdout=sumoLogOut, stderr=sumoLogErr)
+
+ sumo_socket = None
+
+ connected = False
+ tries = 1
+ while not connected:
+ try:
+ logging.debug("Connecting to SUMO (%s) on port %d (try %d)" % (" ".join(cmd), remote_port, tries))
+ sumo_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sumo_socket.connect(('127.0.0.1', remote_port))
+ break
+ except socket.error, e:
+ logging.debug("Error (%s)" % e)
+ if tries >= 10:
+ raise
+ time.sleep(tries * 0.25)
+ tries += 1
+
+ unused_port_lock.release()
+ forward_connection(client_socket, sumo_socket, sumo)
+
+ client_socket.close()
+ sumo_socket.close()
+
+ logging.debug("Done with proxy mode, killing SUMO")
+
+ thread.start_new_thread(subprocess.Popen.wait, (sumo, ))
+ time.sleep(0.5)
+ if sumo.returncode == None:
+ logging.debug("SIGTERM")
+ os.kill(sumo.pid, signal.SIGTERM)
+ time.sleep(0.5)
+ if sumo.returncode == None:
+ logging.debug("SIGKILL")
+ os.kill(sumo.pid, signal.SIGKILL)
+ time.sleep(1)
+ if sumo.returncode == None:
+ logging.debug("Warning: SUMO still not dead. Waiting 10 more seconds...")
+ time.sleep(10)
+
+ logging.info("Done running SUMO")
+ sumo_returncode = sumo.returncode
+ if sumo_returncode == 0:
+ sumo_status = "Done."
+ elif sumo_returncode != None:
+ sumo_status = "Exited with error code %d" % sumo_returncode
+ else:
+ sumo_returncode = -1
+ sumo_status = "Undef"
+
+ except OSError, e:
+ sumo_status = "Could not start SUMO (%s): %s" % (" ".join(cmd), e)
+
+ except exceptions.SystemExit:
+ sumo_status = "Premature launch script exit"
+
+ except exceptions.KeyboardInterrupt:
+ sumo_status = "Keyboard interrupt."
+
+ except socket.error, e:
+ sumo_status = "Could not connect to SUMO (%s). Might be protected by a personal firewall or crashed before a connection could be established." % e
+
+ except:
+ raise
+
+ # statistics
+ sumo_end = int(time.time())
+
+ # close log files
+ sumoLogOut.close()
+ sumoLogErr.close()
+
+ # read log files
+ sumoLogOut = open(os.path.join(runpath, 'sumo-launchd.out.log'), 'r')
+ sumoLogErr = open(os.path.join(runpath, 'sumo-launchd.err.log'), 'r')
+ sumo_stdout = sumoLogOut.read()
+ sumo_stderr = sumoLogErr.read()
+ sumoLogOut.close()
+ sumoLogErr.close()
+
+ # prepare result XML
+ CDATA_START = '<![CDATA['
+ CDATA_END = ']]>'
+ result_xml = '<?xml version="1.0"?>\n'
+ result_xml += '<status>\n'
+ result_xml += '\t<%s>%s</%s>\n' % ("exit-code", sumo_returncode, "exit-code")
+ if sumo_start:
+ result_xml += '\t<%s>%s</%s>\n' % ("start", sumo_start, "start")
+ if sumo_end:
+ result_xml += '\t<%s>%s</%s>\n' % ("end", sumo_end, "end")
+ if sumo_status:
+ result_xml += '\t<%s>%s</%s>\n' % ("status", sumo_status, "status")
+ result_xml += '\t<%s>%s</%s>\n' % ("stdout", CDATA_START + sumo_stdout.replace(CDATA_END, CDATA_END + CDATA_END + CDATA_START) + CDATA_END, "stdout")
+ result_xml += '\t<%s>%s</%s>\n' % ("stderr", CDATA_START + sumo_stderr.replace(CDATA_END, CDATA_END + CDATA_END + CDATA_START) + CDATA_END, "stderr")
+ result_xml += '</status>\n'
+
+ return result_xml
+
+
+def set_sumoconfig_option(config_parser, config_xml, section, key, value):
+ """
+ Add or replace named config option (currently ignores given section)
+ """
+
+ key_nodes = config_xml.getElementsByTagName(key)
+ if len(key_nodes) > 1:
+ raise RuntimeError('config file "%s" contains %d <%s> nodes, expected at most 1' % (file_dst_name, key, len(key_nodes)))
+ elif len(key_nodes) < 1:
+ key_node = config_parser.createElement(key)
+ key_node.setAttribute("value", str(value))
+ config_xml.appendChild(key_node)
+ else:
+ key_node = key_nodes[0]
+ for n in key_node.childNodes:
+ key_node.removeChild(n)
+ key_node.setAttribute("value", str(value))
+
+
+def copy_and_modify_files(basedir, copy_nodes, runpath, remote_port, seed):
+ """
+ Copy (and modify) files, return config file name
+ """
+
+ config_file_name = None
+ for copy_node in copy_nodes:
+
+ file_src_name = None
+ file_dst_name = None
+ file_contents = None
+
+ # Read from disk?
+ if copy_node.hasAttribute("file"):
+ file_src_name = copy_node.getAttribute("file")
+ file_src_path = os.path.join(basedir, file_src_name)
+
+ # Sanity check
+ if file_src_name.find("/") != -1:
+ raise RuntimeError('name of file to copy "%s" contains a "/"' % file_src_name)
+ if not os.path.exists(file_src_path):
+ raise RuntimeError('file "%s" does not exist' % file_src_path)
+
+ # Read contents
+ file_handle = open(file_src_path, 'rb')
+ file_contents = file_handle.read()
+ file_handle.close()
+
+ # By now we need a destination name and contents
+ if copy_node.hasAttribute("name"):
+ file_dst_name = copy_node.getAttribute("name")
+ elif file_src_name:
+ file_dst_name = file_src_name
+ else:
+ raise RuntimeError('<copy> node with no destination name: %s' % copy_node.toxml())
+ if file_contents == None:
+ raise RuntimeError('<copy> node with no contents: %s' % copy_node.toxml())
+
+ # Is this our config file?
+ if copy_node.getAttribute("type") == "config":
+ config_file_name = file_dst_name
+
+ config_parser = xml.dom.minidom.parseString(file_contents)
+ config_xml = config_parser.documentElement
+
+ set_sumoconfig_option(config_parser, config_xml, "traci_server", "remote-port", remote_port)
+ set_sumoconfig_option(config_parser, config_xml, "random_number", "seed", seed)
+ set_sumoconfig_option(config_parser, config_xml, "random_number", "random", "false")
+
+ file_contents = config_xml.toxml()
+
+ # Write file into rundir
+ file_dst_path = os.path.join(runpath, file_dst_name)
+ file_handle = open(file_dst_path, "wb")
+ file_handle.write(file_contents)
+ file_handle.close()
+
+ # make sure that we copied a config file
+ if not config_file_name:
+ raise RuntimeError('launch config contained no <copy> node with type="config"')
+
+ return config_file_name
+
+
+def handle_launch_configuration(sumo_command, shlex, launch_xml_string, client_socket, keep_temp):
+ """
+ Process launch configuration in launch_xml_string.
+ """
+
+ # create temporary directory
+ logging.debug("Creating temporary directory...")
+ runpath = tempfile.mkdtemp(prefix="sumo-launchd-tmp-")
+ if not runpath:
+ raise RuntimeError("Could not create temporary directory")
+ if not os.path.exists(runpath):
+ raise RuntimeError('Temporary directory "%s" does not exist, even though it should have been created' % runpath)
+ logging.debug("Temporary dir is %s" % runpath)
+
+ result_xml = None
+ unused_port_lock = UnusedPortLock()
+ try:
+ # parse launch configuration
+ (basedir, copy_nodes, seed) = parse_launch_configuration(launch_xml_string)
+
+ # find remote_port
+ logging.debug("Finding free port number...")
+ unused_port_lock.__enter__()
+ remote_port = find_unused_port()
+ logging.debug("...found port %d" % remote_port)
+
+ # copy (and modify) files
+ config_file_name = copy_and_modify_files(basedir, copy_nodes, runpath, remote_port, seed)
+
+ # run SUMO
+ result_xml = run_sumo(runpath, sumo_command, shlex, config_file_name, remote_port, seed, client_socket, unused_port_lock, keep_temp)
+
+ finally:
+ unused_port_lock.__exit__()
+
+ # clean up
+ if not keep_temp:
+ logging.debug("Cleaning up")
+ shutil.rmtree(runpath)
+ else:
+ logging.debug("Not cleaning up %s" % runpath)
+
+ logging.debug('Result: "%s"' % result_xml)
+
+ return result_xml
+
+def handle_get_version(conn):
+ """
+ process a "get version" command received on the connection
+ """
+
+ logging.debug('Got CMD_GETVERSION')
+
+ # Send OK response and version info
+ response = struct.pack("!iBBBiBBii", 4+1+1+1+4 + 1+1+4+4+len(_LAUNCHD_VERSION), 1+1+1+4, _CMD_GET_VERSION, 0x00, 0x00, 1+4+4+len(_LAUNCHD_VERSION), _CMD_GET_VERSION, _API_VERSION, len(_LAUNCHD_VERSION)) + _LAUNCHD_VERSION
+ conn.send(response)
+
+
+def read_launch_config(conn):
+ """
+ Read (and return) launch configuration from socket
+ """
+
+ # Get TraCI message length
+ msg_len_buf = ""
+ while len(msg_len_buf) < 4:
+ msg_len_buf += conn.recv(4 - len(msg_len_buf))
+ msg_len = struct.unpack("!i", msg_len_buf)[0] - 4
+
+ logging.debug("Got TraCI message of length %d" % msg_len)
+
+ # Get TraCI command length
+ cmd_len_buf = ""
+ cmd_len_buf += conn.recv(1)
+ cmd_len = struct.unpack("!B", cmd_len_buf)[0] - 1
+ if cmd_len == -1:
+ cmd_len_buf = ""
+ while len(cmd_len_buf) < 4:
+ cmd_len_buf += conn.recv(4 - len(cmd_len_buf))
+ cmd_len = struct.unpack("!i", cmd_len_buf)[0] - 5
+
+ logging.debug("Got TraCI command of length %d" % cmd_len)
+
+ # Get TraCI command ID
+ cmd_id_buf = ""
+ cmd_id_buf += conn.recv(1)
+ cmd_id = struct.unpack("!B", cmd_id_buf)[0]
+
+ logging.debug("Got TraCI command 0x%x" % cmd_id)
+
+ if cmd_id == _CMD_GET_VERSION:
+ # handle get version command
+ handle_get_version(conn)
+ # ...and try reading the launch config again
+ return read_launch_config(conn)
+ elif cmd_id != _CMD_FILE_SEND:
+ raise RuntimeError("Expected CMD_FILE_SEND (0x%x), but got 0x%x" % (_CMD_FILE_SEND, cmd_id))
+
+ # Get File name
+ fname_len_buf = ""
+ while len(fname_len_buf) < 4:
+ fname_len_buf += conn.recv(4 - len(fname_len_buf))
+ fname_len = struct.unpack("!i", fname_len_buf)[0]
+ fname = conn.recv(fname_len)
+ if fname != "sumo-launchd.launch.xml":
+ raise RuntimeError('Launch configuration must be named "sumo-launchd.launch.xml", got "%s" instead.' % fname)
+
+ logging.debug('Got CMD_FILE_SEND for "%s"' % fname)
+
+ # Get File contents
+ data_len_buf = ""
+ while len(data_len_buf) < 4:
+ data_len_buf += conn.recv(4 - len(data_len_buf))
+ data_len = struct.unpack("!i", data_len_buf)[0]
+ data = conn.recv(data_len)
+
+ logging.debug('Got CMD_FILE_SEND with data "%s"' % data)
+
+ # Send OK response
+ response = struct.pack("!iBBBi", 4+1+1+1+4, 1+1+1+4, _CMD_FILE_SEND, 0x00, 0x00)
+ conn.send(response)
+
+ return data
+
+
+def handle_connection(sumo_command, shlex, conn, addr, keep_temp):
+ """
+ Handle incoming connection.
+ """
+
+ logging.debug("Handling connection from %s on port %d" % addr)
+
+ try:
+ data = read_launch_config(conn)
+ handle_launch_configuration(sumo_command, shlex, data, conn, keep_temp)
+
+ except Exception, e:
+ logging.error("Aborting on error: %s" % e)
+
+ finally:
+ logging.debug("Closing connection from %s on port %d" % addr)
+ conn.close()
+
+
+def wait_for_connections(sumo_command, shlex, sumo_port, bind_address, do_daemonize, do_kill, pidfile, keep_temp):
+ """
+ Open TCP socket, wait for connections, call handle_connection for each
+ """
+
+ if do_kill:
+ check_kill_daemon(pidfile)
+
+ listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ listener.bind((bind_address, sumo_port))
+ listener.listen(5)
+ logging.info("Listening on port %d" % sumo_port)
+
+ if do_daemonize:
+ logging.info("Detaching to run as daemon")
+ daemonize(pidfile)
+
+ try:
+ while True:
+ conn, addr = listener.accept()
+ logging.debug("Connection from %s on port %d" % addr)
+ thread.start_new_thread(handle_connection, (sumo_command, shlex, conn, addr, keep_temp))
+
+ except exceptions.SystemExit:
+ logging.warning("Killed.")
+
+ except exceptions.KeyboardInterrupt:
+ logging.warning("Keyboard interrupt.")
+
+ except:
+ raise
+
+ finally:
+ # clean up
+ logging.info("Shutting down.")
+ listener.close()
+
+
+def check_kill_daemon(pidfile):
+ # check pidfile, see if the daemon is still running
+ try:
+ pidfileh = open(pidfile, 'r')
+ old_pid = int(pidfileh.readline())
+ if old_pid:
+ logging.info("There might already be a daemon running with PID %d. Sending SIGTERM." % old_pid)
+ try:
+ os.kill(old_pid, signal.SIGTERM)
+ time.sleep(1)
+ except OSError, e:
+ pass
+
+ pidfileh.close()
+ except IOError, e:
+ pass
+
+
+def daemonize(pidfile):
+ """
+ detach process, keep it running in the background
+ """
+
+ # fork and exit parent process
+ try:
+ child_pid = os.fork()
+ if child_pid > 0:
+ # parent can exit
+ sys.exit(0)
+ elif child_pid == 0:
+ # child does nothing
+ pass
+ else:
+ logging.error("Aborting. Failed to fork: %s" % e.strerror)
+ sys.exit(1);
+ except OSError, e:
+ logging.error("Aborting. Failed to fork: %s" % e.strerror)
+ sys.exit(1)
+
+ # get rid of any outside influence
+ os.setsid()
+
+ # fork again to prevent zombies
+ try:
+ child_pid = os.fork()
+ if child_pid > 0:
+ # parent can exit
+ sys.exit(0)
+ elif child_pid == 0:
+ # child creates PIDFILE
+ logging.info("Fork successful. PID is %d" % os.getpid())
+ if pidfile:
+ pidfileh = open(pidfile, 'w')
+ pidfileh.write('%d\n' % os.getpid())
+ pidfileh.close()
+ atexit.register(os.remove, pidfile)
+ else:
+ logging.error("Aborting. Failed to fork: %s" % e.strerror)
+ sys.exit(1);
+
+ except OSError, e:
+ logging.error("Aborting. Failed to fork: %s" % e.strerror)
+ sys.exit(1)
+
+
+def main():
+ """
+ Program entry point when run interactively.
+ """
+
+ # Option handling
+ parser = OptionParser()
+ parser.add_option("-c", "--command", dest="command", default="sumo", help="run SUMO as COMMAND [default: %default]", metavar="COMMAND")
+ parser.add_option("-s", "--shlex", dest="shlex", default=False, action="store_true", help="treat command as shell string to execute, replace {} with command line parameters [default: no]")
+ parser.add_option("-p", "--port", dest="port", type="int", default=9999, action="store", help="listen for connections on PORT [default: %default]", metavar="PORT")
+ parser.add_option("-b", "--bind", dest="bind", default="127.0.0.1", help="bind to ADDRESS [default: %default]", metavar="ADDRESS")
+ parser.add_option("-L", "--logfile", dest="logfile", default=os.path.join(tempfile.gettempdir(), "sumo-launchd.log"), help="log messages to LOGFILE [default: %default]", metavar="LOGFILE")
+ parser.add_option("-v", "--verbose", dest="count_verbose", default=0, action="count", help="increase verbosity [default: don't log infos, debug]")
+ parser.add_option("-q", "--quiet", dest="count_quiet", default=0, action="count", help="decrease verbosity [default: log warnings, errors]")
+ parser.add_option("-d", "--daemon", dest="daemonize", default=False, action="store_true", help="detach and run as daemon [default: no]")
+ parser.add_option("-k", "--kill", dest="kill", default=False, action="store_true", help="send SIGTERM to running daemon first [default: no]")
+ parser.add_option("-P", "--pidfile", dest="pidfile", default=os.path.join(tempfile.gettempdir(), "sumo-launchd.pid"), help="if running as a daemon, write pid to PIDFILE [default: %default]", metavar="PIDFILE")
+ parser.add_option("-t", "--keep-temp", dest="keep_temp", default=False, action="store_true", help="keep all temporary files [default: no]")
+ (options, args) = parser.parse_args()
+ _LOGLEVELS = (logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG)
+ loglevel = _LOGLEVELS[max(0, min(1 + options.count_verbose - options.count_quiet, len(_LOGLEVELS)-1))]
+
+ # catch SIGTERM to exit cleanly when we're kill-ed
+ signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1))
+
+ # configure logging
+ logging.basicConfig(filename=options.logfile, level=loglevel)
+ if not options.daemonize:
+ logging.getLogger().addHandler(logging.StreamHandler())
+ logging.debug("Logging to %s" % options.logfile)
+
+ if args:
+ logging.warning("Superfluous command line arguments: \"%s\"" % " ".join(args))
+
+ # this is where we'll spend our time
+ wait_for_connections(options.command, options.shlex, options.port, options.bind, options.daemonize, options.kill, options.pidfile, options.keep_temp)
+
+
+# Start main() when run interactively
+if __name__ == '__main__':
+ main()
View
96 examples/traci/Car.ned
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci;
+
+import inet.base.NotificationBoard;
+import inet.networklayer.autorouting.HostAutoConfigurator;
+import inet.networklayer.common.InterfaceTable;
+import inet.applications.traci.TraCIDemo;
+import inet.mobility.models.TraCIMobility;
+import inet.networklayer.ipv4.RoutingTable;
+import inet.transport.udp.UDP;
+import inet.nodes.inet.NetworkLayer;
+import inet.linklayer.ieee80211.Ieee80211Nic;
+
+module Car
+{
+ parameters:
+ @node();
+
+ gates:
+ input radioIn @directIn;
+
+ submodules:
+ notificationBoard: NotificationBoard {
+ parameters:
+ @display("p=140,462");
+ }
+ ac_wlan: HostAutoConfigurator {
+ @display("p=296,402");
+ }
+ interfaceTable: InterfaceTable {
+ parameters:
+ @display("p=140,326");
+ }
+ app: TraCIDemo {
+ parameters:
+ @display("p=384,46");
+ }
+ mobility: TraCIMobility {
+ parameters:
+ @display("p=60,459");
+ }
+ routingTable: RoutingTable {
+ parameters:
+ IPForward = true;
+ routerId = "";
+ routingFile = "";
+ @display("p=60,326");
+ }
+ udp: UDP {
+ parameters:
+ @display("p=384,146");
+ }
+ networkLayer: NetworkLayer {
+ parameters:
+ proxyARP = false;
+ @display("p=304,327;q=queue");
+ gates:
+ ifIn[1];
+ ifOut[1];
+ }
+ wlan: Ieee80211Nic {
+ parameters:
+ @display("p=304,461;q=queue");
+ }
+ connections allowunconnected:
+ udp.appOut++ --> app.udp$i;
+ udp.appIn++ <-- app.udp$o;
+
+ udp.ipOut --> networkLayer.udpIn;
+ udp.ipIn <-- networkLayer.udpOut;
+
+ wlan.upperLayerOut --> networkLayer.ifIn[0];
+ wlan.upperLayerIn <-- networkLayer.ifOut[0];
+
+ radioIn --> wlan.radioIn;
+}
+
View
37 examples/traci/Highway.ned
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci;
+
+import inet.world.radio.ChannelControl;
+import inet.world.traci.TraCIScenarioManager;
+
+module Highway
+{
+ submodules:
+ channelControl: ChannelControl {
+ parameters:
+ @display("p=256,128");
+ }
+ manager: TraCIScenarioManager {
+ parameters:
+ @display("p=512,128");
+ }
+}
View
5 examples/traci/README
@@ -0,0 +1,5 @@
+TraCI client modules to connect OMNeT++ and the SUMO road traffic simulator.
+
+This simulation requires SUMO to be started and listening for TraCI commands
+on a TCP socket, e.g. using "sumo-guisim -c sumo.sumo.cfg".
+
View
2  examples/traci/debug
@@ -0,0 +1,2 @@
+#!/bin/sh
+gdb --args opp_run -l../../src/inet -n"../../src;.." "$@"
View
2  examples/traci/memcheck
@@ -0,0 +1,2 @@
+#!/bin/sh
+valgrind --tool=memcheck --leak-check=full --dsymutil=yes --log-file=valgrind.out -- opp_run -l../../src/inet -n"../../src;.." "$@"
View
48,199 examples/traci/net.net.xml
48,199 additions, 0 deletions not shown
View
65 examples/traci/omnetpp.ini
@@ -0,0 +1,65 @@
+[General]
+network = scenario
+debug-on-errors = true
+
+cmdenv-express-mode = true
+cmdenv-autoflush = true
+cmdenv-status-frequency = 10000000s
+tkenv-plugin-path = ../../../etc/plugins
+tkenv-image-path = bitmaps
+
+sim-time-limit = 6000s
+
+**.vector-recording = true
+
+**.constraintAreaMinX = 0m
+**.constraintAreaMinY = 0m
+**.constraintAreaMinZ = 0m
+**.constraintAreaMaxX = 10699m
+**.constraintAreaMaxY = 7131m
+**.constraintAreaMaxZ = 0m
+
+**.debug = true
+**.coreDebug = false
+**.host*.**.channelNumber = 0
+
+# channel physical parameters
+*.channelControl.carrierFrequency = 2.4GHz
+*.channelControl.pMax = 2.0mW
+*.channelControl.sat = -110dBm
+*.channelControl.alpha = 2
+*.channelControl.numChannels = 1
+
+# TraCIScenarioManager
+*.manager.updateInterval = 1s
+*.manager.host = "localhost"
+*.manager.port = 8888
+*.manager.moduleType = "inet.examples.traci.Car"
+*.manager.moduleName = "host"
+*.manager.moduleDisplayString = ""
+*.manager.autoShutdown = true
+*.manager.margin = 25
+
+# nic settings
+**.wlan.mgmt.frameCapacity = 10
+**.wlan.mgmtType = "Ieee80211MgmtAdhoc"
+**.wlan.mac.address = "auto"
+**.wlan.mac.maxQueueSize = 14
+**.wlan.mac.rtsThresholdBytes = 3000B
+**.wlan.mac.bitrate = 2Mbps
+**.wlan.mac.retryLimit = 7
+**.wlan.mac.cwMinData = 7
+**.wlan.mac.cwMinBroadcast = 31
+
+**.wlan.radio.bitrate = 2Mbps
+**.wlan.radio.transmitterPower = 2mW
+**.wlan.radio.thermalNoise = -110dBm
+**.wlan.radio.sensitivity = -85dBm
+**.wlan.radio.pathLossAlpha = 2
+**.wlan.radio.snirThreshold = 4dB
+
+[Config accident]
+*.host[10].mobility.accidentCount = 1
+*.host[10].mobility.accidentStart = 115s
+*.host[10].mobility.accidentDuration = 30s
+
View
15 examples/traci/routes.rou.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!--
+194 Cars leaving the Computer Science Building and campus of the University of Erlangen-Nuremberg
+Copyright (C) 2008 Christoph Sommer <christoph.sommer@informatik.uni-erlangen.de>
+Licensed under the Creative Commons Attribution-ShareAlike 2.0 license <http://creativecommons.org/licenses/by-sa/2.0/>
+-->
+<routes>
+ <vType id="vtype0" accel="2.6" decel="4.5" sigma="0.5" length="2.5" minGap="2.5" maxSpeed="14" color="1,1,0"/>
+ <route id="route0" edges="23360303 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <route id="route1" edges="23360301 -54452042 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <route id="route2" edges="23360302 -54452043 -54452042 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <flow id="flow0" type="vtype0" route="route0" begin="0" period="9" number="65"/>
+ <flow id="flow1" type="vtype0" route="route1" begin="3" period="9" number="65"/>
+ <flow id="flow2" type="vtype0" route="route2" begin="6" period="9" number="65"/>
+</routes>
View
2  examples/traci/run
@@ -0,0 +1,2 @@
+#!/bin/sh
+opp_run -l../../src/inet -n"../../src;.." "$@"
View
25 examples/traci/scenario.ned
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci;
+
+network scenario extends Highway
+{
+}
View
18 examples/traci/sumo.sumo.cfg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/sumoConfiguration.xsd">
+
+ <input>
+ <net-file value="net.net.xml"/>
+ <route-files value="routes.rou.xml"/>
+ </input>
+
+ <time>
+ <begin value="0"/>
+ <end value="86400"/>
+ </time>
+
+ <traci_server>
+ <remote-port value="8888"/>
+ </traci_server>
+</configuration>
View
96 examples/traci_launchd/Car.ned
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci_launchd;
+
+import inet.base.NotificationBoard;
+import inet.networklayer.autorouting.HostAutoConfigurator;
+import inet.networklayer.common.InterfaceTable;
+import inet.applications.traci.TraCIDemo;
+import inet.mobility.models.TraCIMobility;
+import inet.networklayer.ipv4.RoutingTable;
+import inet.transport.udp.UDP;
+import inet.nodes.inet.NetworkLayer;
+import inet.linklayer.ieee80211.Ieee80211Nic;
+
+module Car
+{
+ parameters:
+ @node();
+
+ gates:
+ input radioIn @directIn;
+
+ submodules:
+ notificationBoard: NotificationBoard {
+ parameters:
+ @display("p=140,462");
+ }
+ ac_wlan: HostAutoConfigurator {
+ @display("p=296,402");
+ }
+ interfaceTable: InterfaceTable {
+ parameters:
+ @display("p=140,326");
+ }
+ app: TraCIDemo {
+ parameters:
+ @display("p=384,46");
+ }
+ mobility: TraCIMobility {
+ parameters:
+ @display("p=60,459");
+ }
+ routingTable: RoutingTable {
+ parameters:
+ IPForward = true;
+ routerId = "";
+ routingFile = "";
+ @display("p=60,326");
+ }
+ udp: UDP {
+ parameters:
+ @display("p=384,146");
+ }
+ networkLayer: NetworkLayer {
+ parameters:
+ proxyARP = false;
+ @display("p=304,327;q=queue");
+ gates:
+ ifIn[1];
+ ifOut[1];
+ }
+ wlan: Ieee80211Nic {
+ parameters:
+ @display("p=304,461;q=queue");
+ }
+ connections allowunconnected:
+ udp.appOut++ --> app.udp$i;
+ udp.appIn++ <-- app.udp$o;
+
+ udp.ipOut --> networkLayer.udpIn;
+ udp.ipIn <-- networkLayer.udpOut;
+
+ wlan.upperLayerOut --> networkLayer.ifIn[0];
+ wlan.upperLayerIn <-- networkLayer.ifOut[0];
+
+ radioIn --> wlan.radioIn;
+}
+
View
37 examples/traci_launchd/Highway.ned
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci_launchd;
+
+import inet.world.radio.ChannelControl;
+import inet.world.traci.TraCIScenarioManagerLaunchd;
+
+module Highway
+{
+ submodules:
+ channelControl: ChannelControl {
+ parameters:
+ @display("p=256,128");
+ }
+ manager: TraCIScenarioManagerLaunchd {
+ parameters:
+ @display("p=512,128");
+ }
+}
View
6 examples/traci_launchd/README
@@ -0,0 +1,6 @@
+TraCI client modules to connect OMNeT++ and the SUMO road traffic simulator
+via sumo-launchd.
+
+This simulation requires sumo-launchd to be started and listening for
+connections on a TCP socket, e.g. using "~/src/inet/etc/sumo-launchd.py -vv".
+
View
2  examples/traci_launchd/debug
@@ -0,0 +1,2 @@
+#!/bin/sh
+gdb --args opp_run -l../../src/inet -n"../../src;.." "$@"
View
2  examples/traci_launchd/memcheck
@@ -0,0 +1,2 @@
+#!/bin/sh
+valgrind --tool=memcheck --leak-check=full --dsymutil=yes --log-file=valgrind.out -- opp_run -l../../src/inet -n"../../src;.." "$@"
View
48,199 examples/traci_launchd/net.net.xml
48,199 additions, 0 deletions not shown
View
66 examples/traci_launchd/omnetpp.ini
@@ -0,0 +1,66 @@
+[General]
+network = scenario
+debug-on-errors = true
+
+cmdenv-express-mode = true
+cmdenv-autoflush = true
+cmdenv-status-frequency = 10000000s
+tkenv-plugin-path = ../../../etc/plugins
+tkenv-image-path = bitmaps
+
+sim-time-limit = 6000s
+
+**.vector-recording = true
+
+**.constraintAreaMinX = 0m
+**.constraintAreaMinY = 0m
+**.constraintAreaMinZ = 0m
+**.constraintAreaMaxX = 10699m
+**.constraintAreaMaxY = 7131m
+**.constraintAreaMaxZ = 0m
+
+**.debug = true
+**.coreDebug = false
+**.host*.**.channelNumber = 0
+
+# channel physical parameters
+*.channelControl.carrierFrequency = 2.4GHz
+*.channelControl.pMax = 2.0mW
+*.channelControl.sat = -110dBm
+*.channelControl.alpha = 2
+*.channelControl.numChannels = 1
+
+# TraCIScenarioManagerLaunchd
+*.manager.updateInterval = 1s
+*.manager.host = "localhost"
+*.manager.port = 9999
+*.manager.moduleType = "inet.examples.traci_launchd.Car"
+*.manager.moduleName = "host"
+*.manager.moduleDisplayString = ""
+*.manager.autoShutdown = true
+*.manager.margin = 25
+*.manager.launchConfig = xmldoc("sumo-launchd.launch.xml")
+
+# nic settings
+**.wlan.mgmt.frameCapacity = 10
+**.wlan.mgmtType = "Ieee80211MgmtAdhoc"
+**.wlan.mac.address = "auto"
+**.wlan.mac.maxQueueSize = 14
+**.wlan.mac.rtsThresholdBytes = 3000B
+**.wlan.mac.bitrate = 2Mbps
+**.wlan.mac.retryLimit = 7
+**.wlan.mac.cwMinData = 7
+**.wlan.mac.cwMinBroadcast = 31
+
+**.wlan.radio.bitrate = 2Mbps
+**.wlan.radio.transmitterPower = 2mW
+**.wlan.radio.thermalNoise = -110dBm
+**.wlan.radio.sensitivity = -85dBm
+**.wlan.radio.pathLossAlpha = 2
+**.wlan.radio.snirThreshold = 4dB
+
+[Config accident]
+*.host[10].mobility.accidentCount = 1
+*.host[10].mobility.accidentStart = 115s
+*.host[10].mobility.accidentDuration = 30s
+
View
15 examples/traci_launchd/routes.rou.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!--
+194 Cars leaving the Computer Science Building and campus of the University of Erlangen-Nuremberg
+Copyright (C) 2008 Christoph Sommer <christoph.sommer@informatik.uni-erlangen.de>
+Licensed under the Creative Commons Attribution-ShareAlike 2.0 license <http://creativecommons.org/licenses/by-sa/2.0/>
+-->
+<routes>
+ <vType id="vtype0" accel="2.6" decel="4.5" sigma="0.5" length="2.5" minGap="2.5" maxSpeed="14" color="1,1,0"/>
+ <route id="route0" edges="23360303 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <route id="route1" edges="23360301 -54452042 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <route id="route2" edges="23360302 -54452043 -54452042 -54452041 -54452040 -40066681 23339459 44009481 49007313 59316120 59316121 59316122 59316123 -4047343 40067020 49000430 4900044"/>
+ <flow id="flow0" type="vtype0" route="route0" begin="0" period="9" number="65"/>
+ <flow id="flow1" type="vtype0" route="route1" begin="3" period="9" number="65"/>
+ <flow id="flow2" type="vtype0" route="route2" begin="6" period="9" number="65"/>
+</routes>
View
2  examples/traci_launchd/run
@@ -0,0 +1,2 @@
+#!/bin/sh
+opp_run -l../../src/inet -n"../../src;.." "$@"
View
25 examples/traci_launchd/scenario.ned
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.examples.traci_launchd;
+
+network scenario extends Highway
+{
+}
View
8 examples/traci_launchd/sumo-launchd.launch.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- debug config -->
+<launch>
+ <copy file="net.net.xml" />
+ <copy file="routes.rou.xml" />
+ <copy file="sumo.sumo.cfg" type="config" />
+</launch>
+
View
14 examples/traci_launchd/sumo.sumo.cfg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/sumoConfiguration.xsd">
+
+ <input>
+ <net-file value="net.net.xml"/>
+ <route-files value="routes.rou.xml"/>
+ </input>
+
+ <time>
+ <begin value="0"/>
+ <end value="86400"/>
+ </time>
+</configuration>
View
85 src/applications/traci/TraCIDemo.cc
@@ -0,0 +1,85 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include "applications/traci/TraCIDemo.h"
+
+#include "NotificationBoard.h"
+#include "UDPSocket.h"
+
+Define_Module(TraCIDemo);
+
+void TraCIDemo::initialize(int stage) {
+ cSimpleModule::initialize(stage);
+ if (stage == 3) {
+ debug = par("debug");
+
+ mobilityStateChangedSignal = registerSignal("mobilityStateChanged");
+ traci = TraCIMobilityAccess().get();
+ traci->subscribe(mobilityStateChangedSignal, this);
+
+ sentMessage = false;
+
+ setupLowerLayer();
+ }
+}
+
+void TraCIDemo::setupLowerLayer() {
+ socket.setOutputGate(gate("udp$o"));
+ socket.joinLocalMulticastGroups();
+ socket.bind(12345);
+ socket.setBroadcast(true);
+}
+
+void TraCIDemo::handleMessage(cMessage* msg) {
+ if (msg->isSelfMessage()) {
+ handleSelfMsg(msg);
+ } else {
+ handleLowerMsg(msg);
+ }
+}
+
+void TraCIDemo::handleSelfMsg(cMessage* msg) {
+}
+
+void TraCIDemo::handleLowerMsg(cMessage* msg) {
+ if (!sentMessage) sendMessage();
+ delete msg;
+}
+
+void TraCIDemo::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj) {
+ Enter_Method_Silent();
+ if (signalID == mobilityStateChangedSignal) {
+ handlePositionUpdate();
+ }
+}
+
+void TraCIDemo::sendMessage() {
+ sentMessage = true;
+
+ cPacket* newMessage = new cPacket();
+
+ socket.sendTo(newMessage, IPv4Address::ALL_HOSTS_MCAST, 12345);
+}
+
+void TraCIDemo::handlePositionUpdate() {
+ if (traci->getPosition().x < 7350) {
+ if (!sentMessage) sendMessage();
+ }
+}
View
58 src/applications/traci/TraCIDemo.h
@@ -0,0 +1,58 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef TraCIDemo_H
+#define TraCIDemo_H
+
+#include <omnetpp.h>
+#include "UDPSocket.h"
+
+#include "mobility/models/TraCIMobility.h"
+
+/**
+ * Small IVC Demo
+ */
+class TraCIDemo : public cSimpleModule, protected cListener {
+ public:
+ virtual int numInitStages() const {
+ return std::max(4, cSimpleModule::numInitStages());
+ }
+ virtual void initialize(int);
+ virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj);
+ virtual void handleMessage(cMessage* msg);
+
+ protected:
+ bool debug;
+ TraCIMobility* traci;
+ bool sentMessage;
+ UDPSocket socket;
+ simsignal_t mobilityStateChangedSignal;
+
+ protected:
+ void setupLowerLayer();
+ virtual void handleSelfMsg(cMessage* apMsg);
+ virtual void handleLowerMsg(cMessage* apMsg);
+
+ virtual void sendMessage();
+ virtual void handlePositionUpdate();
+};
+
+#endif
+
View
34 src/applications/traci/TraCIDemo.ned
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.applications.traci;
+
+//
+// TraCI IVC Demo
+//
+simple TraCIDemo
+{
+ parameters:
+ bool debug = default(false); // output debugging information
+
+ @display("i=block/app2");
+ gates:
+ inout udp;
+}
View
213 src/applications/traci/TraCITestApp.cc
@@ -0,0 +1,213 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include "applications/traci/TraCITestApp.h"
+#include "NotificationBoard.h"
+#include <cmath>
+
+Define_Module(TraCITestApp);
+
+void TraCITestApp::initialize(int stage) {
+ cSimpleModule::initialize(stage);
+ if (stage == 0) {
+ debug = par("debug");
+ testNumber = par("testNumber");
+
+ mobilityStateChangedSignal = registerSignal("mobilityStateChanged");
+ traci = TraCIMobilityAccess().get();
+ traci->subscribe(mobilityStateChangedSignal, this);
+
+ visitedEdges.clear();
+ hasStopped = false;
+
+ if (debug) std::cout << "TraCITestApp initialized with testNumber=" << testNumber << std::endl;
+ }
+}
+
+void TraCITestApp::finish() {
+}
+
+void TraCITestApp::handleSelfMsg(cMessage *msg) {
+}
+
+void TraCITestApp::handleLowerMsg(cMessage* msg) {
+ delete msg;
+}
+
+void TraCITestApp::handleMessage(cMessage* msg) {
+ if (msg->isSelfMessage()) {
+ handleSelfMsg(msg);
+ } else {
+ handleLowerMsg(msg);
+ }
+}
+
+
+void TraCITestApp::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj) {
+ if (signalID == mobilityStateChangedSignal) {
+ handlePositionUpdate();
+ }
+}
+
+namespace {
+ void assertTrue(std::string msg, bool b) {
+ std::cout << (b?"Passed":"FAILED") << ": " << msg << std::endl;
+ }
+
+ template<class T> void assertClose(std::string msg, T target, T actual) {
+ assertTrue(msg, std::fabs(target - actual) <= 0.0000001);
+ }
+ template<class T> void assertEqual(std::string msg, T target, T actual) {
+ assertTrue(msg, target == actual);
+ }
+ void assertEqual(std::string msg, std::string target, std::string actual) {
+ assertTrue(msg, target == actual);
+ }
+}
+
+void TraCITestApp::handlePositionUpdate() {
+ const simtime_t t = simTime();
+ const std::string roadId = traci->getRoadId();
+ visitedEdges.insert(roadId);
+
+ int testCounter = 0;
+
+ if (testNumber == testCounter++) {
+ if (t == 9) {
+ assertTrue("(commandSetSpeed) vehicle is driving", traci->getSpeed() > 25);
+ }
+ if (t == 10) {
+ traci->commandSetSpeedMode(0x00);
+ traci->commandSetSpeed(0);
+ }
+ if (t == 11) {
+ assertClose("(commandSetSpeed) vehicle has stopped", 0.0, traci->getSpeed());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ traci->commandChangeRoute("42", 9999);
+ traci->commandChangeRoute("43", 9999);
+ }
+ if (t == 30) {
+ assertTrue("(commandChangeRoute, 9999) vehicle avoided 42", visitedEdges.find("42") == visitedEdges.end());
+ assertTrue("(commandChangeRoute, 9999) vehicle avoided 43", visitedEdges.find("43") == visitedEdges.end());
+ assertTrue("(commandChangeRoute, 9999) vehicle took 44", visitedEdges.find("44") != visitedEdges.end());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ traci->commandChangeRoute("42", 9999);
+ traci->commandChangeRoute("43", 9999);
+ }
+ if (t == 3) {
+ traci->commandChangeRoute("42", -1);
+ traci->commandChangeRoute("44", 9999);
+ }
+ if (t == 30) {
+ assertTrue("(commandChangeRoute, -1) vehicle took 42", visitedEdges.find("42") != visitedEdges.end());
+ assertTrue("(commandChangeRoute, -1) vehicle avoided 43", visitedEdges.find("43") == visitedEdges.end());
+ assertTrue("(commandChangeRoute, -1) vehicle avoided 44", visitedEdges.find("44") == visitedEdges.end());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ assertClose("(commandDistanceRequest, air)", 859.4556417, traci->commandDistanceRequest(Coord(25,7030), Coord(883,6980), false));
+ assertClose("(commandDistanceRequest, driving)", 845.93, traci->commandDistanceRequest(Coord(25,7030), Coord(883,6980), true));
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ traci->commandStopNode("43", 20, 0, 10, 30);
+ }
+ if (t == 30) {
+ assertTrue("(commandStopNode) vehicle is at 43", roadId == "43");
+ assertClose("(commandStopNode) vehicle is stopped", 0.0, traci->getSpeed());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ traci->getManager()->commandSetTrafficLightProgram("10", "myProgramRed");
+ }
+ if (t == 30) {
+ assertTrue("(commandSetTrafficLightProgram) vehicle is at 31", roadId == "31");
+ assertClose("(commandSetTrafficLightProgram) vehicle is stopped", 0.0, traci->getSpeed());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ traci->getManager()->commandSetTrafficLightPhaseIndex("10", 4);
+ }
+ if (t == 30) {
+ assertTrue("(commandSetTrafficLightPhaseIndex) vehicle is at 31", roadId == "31");
+ assertClose("(commandSetTrafficLightPhaseIndex) vehicle is stopped", 0.0, traci->getSpeed());
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ std::list<std::string> polys = traci->commandGetPolygonIds();
+ assertEqual("(commandGetPolygonIds) number is 1", polys.size(), (size_t)1);
+ assertEqual("(commandGetPolygonIds) id is correct", *polys.begin(), "poly0");
+ std::string typeId = traci->commandGetPolygonTypeId("poly0");
+ assertEqual("(commandGetPolygonTypeId) typeId is correct", typeId, "type0");
+ std::list<Coord> shape = traci->commandGetPolygonShape("poly0");
+ assertClose("(commandGetPolygonShape) shape x coordinate is correct", 130.0, shape.begin()->x);
+ assertClose("(commandGetPolygonShape) shape y coordinate is correct", 81.65, shape.begin()->y);
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 1) {
+ std::list<Coord> shape1 = traci->commandGetPolygonShape("poly0");
+ assertClose("(commandGetPolygonShape) shape x coordinate is correct", 130.0, shape1.begin()->x);
+ assertClose("(commandGetPolygonShape) shape y coordinate is correct", 81.65, shape1.begin()->y);
+ std::list<Coord> shape2 = shape1;
+ shape2.begin()->x = 135;
+ shape2.begin()->y = 85;
+ traci->commandSetPolygonShape("poly0", shape2);
+ std::list<Coord> shape3 = traci->commandGetPolygonShape("poly0");
+ assertClose("(commandSetPolygonShape) shape x coordinate was changed", 135.0, shape3.begin()->x);
+ assertClose("(commandSetPolygonShape) shape y coordinate was changed", 85.0, shape3.begin()->y);
+ }
+ }
+
+ if (testNumber == testCounter++) {
+ if (t == 30) {
+ bool r = traci->getManager()->commandAddVehicle("testVehicle0", "vtype0", "route0", "25_0", 0, 70);
+ assertTrue("(commandAddVehicle) command reports success", r);
+ }
+ if (t == 31) {
+ std::map<std::string, cModule*>::const_iterator i = traci->getManager()->getManagedHosts().find("testVehicle0");
+ bool r = (i != traci->getManager()->getManagedHosts().end());
+ assertTrue("(commandAddVehicle) vehicle now driving", r);
+ cModule* mod = i->second;
+ TraCIMobility* traci2 = check_and_cast<TraCIMobility*>(findModuleWhereverInNode("mobility", mod));
+ assertTrue("(commandAddVehicle) vehicle driving at speed", traci2->getSpeed() > 25);
+ }
+ }
+}
+
View
59 src/applications/traci/TraCITestApp.h
@@ -0,0 +1,59 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#ifndef TraCITestApp_H
+#define TraCITestApp_H
+
+#include <set>
+#include <list>
+
+#include <omnetpp.h>
+
+#include "mobility/models/TraCIMobility.h"
+
+/**
+ * FIXME
+ */
+class TraCITestApp : public cSimpleModule, protected cListener {
+ public:
+ int numInitStages() const {return std::max(cSimpleModule::numInitStages(), 1);}
+ void initialize(int stage);
+ void finish();
+
+ protected:
+ // module parameters
+ bool debug;
+ int testNumber;
+
+ TraCIMobility* traci;
+ std::set<std::string> visitedEdges; /**< set of edges this vehicle visited */
+ bool hasStopped; /**< true if at some point in time this vehicle travelled at negligible speed */
+ simsignal_t mobilityStateChangedSignal;
+
+ protected:
+ void handleSelfMsg(cMessage* msg);
+ void handleLowerMsg(cMessage* msg);
+ void handleMessage(cMessage* msg);
+ void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj);
+
+ void handlePositionUpdate();
+};
+
+#endif
View
33 src/applications/traci/TraCITestApp.ned
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+//
+// Documentation for these modules is at http://veins.car2x.org/
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+package inet.applications.traci;
+
+
+simple TraCITestApp
+{
+ parameters:
+ bool debug = default(false); // output debugging information
+ int testNumber; // number of test to run (-1: no test)
+
+ @display("i=block/app2");
+ gates:
+
+}
View
345 src/mobility/models/TraCIMobility.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
//
// Documentation for these modules is at http://veins.car2x.org/
//
@@ -30,80 +30,80 @@ namespace {
const double MY_INFINITY = (std::numeric_limits<double>::has_infinity ? std::numeric_limits<double>::infinity() : std::numeric_limits<double>::max());
double roadIdAsDouble(std::string road_id) {
- std::istringstream iss(road_id);
- double d;
- if (!(iss >> d)) return MY_INFINITY;
- return d;
+ std::istringstream iss(road_id);
+ double d;
+ if (!(iss >> d)) return MY_INFINITY;
+ return d;
}
}
void TraCIMobility::Statistics::initialize()
{
- firstRoadNumber = MY_INFINITY;
- startTime = simTime();
- totalTime = 0;
- stopTime = 0;
- minSpeed = MY_INFINITY;
- maxSpeed = -MY_INFINITY;
- totalDistance = 0;
- totalCO2Emission = 0;
+ firstRoadNumber = MY_INFINITY;
+ startTime = simTime();
+ totalTime = 0;
+ stopTime = 0;
+ minSpeed = MY_INFINITY;
+ maxSpeed = -MY_INFINITY;
+ totalDistance = 0;
+ totalCO2Emission = 0;
}
void TraCIMobility::Statistics::watch(cSimpleModule& )
{
- WATCH(totalTime);
- WATCH(minSpeed);
- WATCH(maxSpeed);
- WATCH(totalDistance);
+ WATCH(totalTime);
+ WATCH(minSpeed);
+ WATCH(maxSpeed);
+ WATCH(totalDistance);
}
void TraCIMobility::Statistics::recordScalars(cSimpleModule& module)
{
- if (firstRoadNumber != MY_INFINITY) module.recordScalar("firstRoadNumber", firstRoadNumber);
- module.recordScalar("startTime", startTime);
- module.recordScalar("totalTime", totalTime);
- module.recordScalar("stopTime", stopTime);
- if (minSpeed != MY_INFINITY) module.recordScalar("minSpeed", minSpeed);
- if (maxSpeed != -MY_INFINITY) module.recordScalar("maxSpeed", maxSpeed);
- module.recordScalar("totalDistance", totalDistance);
- module.recordScalar("totalCO2Emission", totalCO2Emission);
+ if (firstRoadNumber != MY_INFINITY) module.recordScalar("firstRoadNumber", firstRoadNumber);
+ module.recordScalar("startTime", startTime);
+ module.recordScalar("totalTime", totalTime);
+ module.recordScalar("stopTime", stopTime);
+ if (minSpeed != MY_INFINITY) module.recordScalar("minSpeed", minSpeed);
+ if (maxSpeed != -MY_INFINITY) module.recordScalar("maxSpeed", maxSpeed);
+ module.recordScalar("totalDistance", totalDistance);
+ module.recordScalar("totalCO2Emission", totalCO2Emission);
}
void TraCIMobility::initialize(int stage)
{
if (stage == 0) {
- debug = par("debug");
- accidentCount = par("accidentCount");
+ debug = par("debug");
+ accidentCount = par("accidentCount");
- currentPosXVec.setName("posx");
- currentPosYVec.setName("posy");
- currentSpeedVec.setName("speed");
- currentAccelerationVec.setName("acceleration");
- currentCO2EmissionVec.setName("co2emission");
+ currentPosXVec.setName("posx");
+ currentPosYVec.setName("posy");
+ currentSpeedVec.setName("speed");
+ currentAccelerationVec.setName("acceleration");
+ currentCO2EmissionVec.setName("co2emission");
- statistics.initialize();
- statistics.watch(*this);
+ statistics.initialize();
+ statistics.watch(*this);
- WATCH(road_id);
- WATCH(speed);
- WATCH(angle);
- WATCH(lastPosition.x);
- WATCH(lastPosition.y);
+ WATCH(road_id);
+ WATCH(speed);
+ WATCH(angle);
+ WATCH(lastPosition.x);
+ WATCH(lastPosition.y);
- startAccidentMsg = 0;
- stopAccidentMsg = 0;
- manager = 0;
- last_speed = -1;
+ startAccidentMsg = 0;
+ stopAccidentMsg = 0;
+ manager = 0;
+ last_speed = -1;
if (accidentCount > 0) {
- simtime_t accidentStart = par("accidentStart");
- startAccidentMsg = new cMessage("scheduledAccident");
- stopAccidentMsg = new cMessage("scheduledAccidentResolved");
- scheduleAt(simTime() + accidentStart, startAccidentMsg);
- }
+ simtime_t accidentStart = par("accidentStart");
+ startAccidentMsg = new cMessage("scheduledAccident");
+ stopAccidentMsg = new cMessage("scheduledAccidentResolved");
+ scheduleAt(simTime() + accidentStart, startAccidentMsg);
+ }
if (ev.isGUI()) updateDisplayString();
- }
+ }
MobilityBase::initialize(stage);
}
@@ -115,187 +115,188 @@ void TraCIMobility::initializePosition() {
void TraCIMobility::finish()
{
- statistics.stopTime = simTime();
+ statistics.stopTime = simTime();
- statistics.recordScalars(*this);
+ statistics.recordScalars(*this);
- cancelAndDelete(startAccidentMsg);
- cancelAndDelete(stopAccidentMsg);
+ cancelAndDelete(startAccidentMsg);
+ cancelAndDelete(stopAccidentMsg);
- isPreInitialized = false;
+ isPreInitialized = false;
}
void TraCIMobility::handleSelfMessage(cMessage *msg)
{
if (msg == startAccidentMsg) {
- commandSetSpeed(0);
- simtime_t accidentDuration = par("accidentDuration");
- scheduleAt(simTime() + accidentDuration, stopAccidentMsg);
- accidentCount--;
- }
+ commandSetSpeed(0);
+ simtime_t accidentDuration = par("accidentDuration");
+ scheduleAt(simTime() + accidentDuration, stopAccidentMsg);
+ accidentCount--;
+ }
else if (msg == stopAccidentMsg) {
- commandSetSpeed(-1);
+ commandSetSpeed(-1);
if (accidentCount > 0) {
- simtime_t accidentInterval = par("accidentInterval");
- scheduleAt(simTime() + accidentInterval, startAccidentMsg);
- }
- }
+ simtime_t accidentInterval = par("accidentInterval");
+ scheduleAt(simTime() + accidentInterval, startAccidentMsg);
+ }
+ }
}
void TraCIMobility::preInitialize(std::string external_id, const Coord& position, std::string road_id, double speed, double angle)
{
- this->external_id = external_id;
- this->lastUpdate = 0;
- nextPos = position;
- lastPosition = position;
- this->road_id = road_id;
- this->speed = speed;
- this->angle = angle;
-
- isPreInitialized = true;
+ this->external_id = external_id;
+ this->lastUpdate = 0;
+ nextPos = position;
+ lastPosition = position;
+ this->road_id = road_id;
+ this->speed = speed;
+ this->angle = angle;
+
+ isPreInitialized = true;
}
-void TraCIMobility::nextPosition(const Coord& position, std::string road_id, double speed, double angle)
+void TraCIMobility::nextPosition(const Coord& position, std::string road_id, double speed, double angle, TraCIScenarioManager::VehicleSignal signals)
{
- if (debug) EV << "nextPosition " << position.x << " " << position.y << " " << road_id << " " << speed << " " << angle << std::endl;
- isPreInitialized = false;
- nextPos = position;
- this->road_id = road_id;
- this->speed = speed;
- this->angle = angle;
+ if (debug) EV << "nextPosition " << position.x << " " << position.y << " " << road_id << " " << speed << " " << angle << std::endl;
+ isPreInitialized = false;
+ nextPos = position;
+ this->road_id = road_id;
+ this->speed = speed;
+ this->angle = angle;
+ this->signals = signals;
move();
}
void TraCIMobility::move()
{
- // ensure we're not called twice in one time step
- ASSERT(lastUpdate != simTime());
+ // ensure we're not called twice in one time step
+ ASSERT(lastUpdate != simTime());
- // keep statistics (for current step)
- currentPosXVec.record(lastPosition.x);
- currentPosYVec.record(lastPosition.y);
+ // keep statistics (for current step)
+ currentPosXVec.record(lastPosition.x);
+ currentPosYVec.record(lastPosition.y);
- // keep statistics (relative to last step)
+ // keep statistics (relative to last step)
if (statistics.startTime != simTime()) {
- simtime_t updateInterval = simTime() - this->lastUpdate;
- this->lastUpdate = simTime();
+ simtime_t updateInterval = simTime() - this->lastUpdate;
+ this->lastUpdate = simTime();
- double distance = lastPosition.distance(nextPos);
- statistics.totalDistance += distance;
- statistics.totalTime += updateInterval;
+ double distance = lastPosition.distance(nextPos);
+ statistics.totalDistance += distance;
+ statistics.totalTime += updateInterval;
if (speed != -1) {
- statistics.minSpeed = std::min(statistics.minSpeed, speed);
- statistics.maxSpeed = std::max(statistics.maxSpeed, speed);
- currentSpeedVec.record(speed);
+ statistics.minSpeed = std::min(statistics.minSpeed, speed);
+ statistics.maxSpeed = std::max(statistics.maxSpeed, speed);
+ currentSpeedVec.record(speed);
if (last_speed != -1) {
- double acceleration = (speed - last_speed) / updateInterval;
- double co2emission = calculateCO2emission(speed, acceleration);
- currentAccelerationVec.record(acceleration);
- currentCO2EmissionVec.record(co2emission);
+ double acceleration = (speed - last_speed) / updateInterval;
+ double co2emission = calculateCO2emission(speed, acceleration);
+ currentAccelerationVec.record(acceleration);
+ currentCO2EmissionVec.record(co2emission);
statistics.totalCO2Emission+=co2emission * updateInterval.dbl();
- }
- last_speed = speed;
+ }
+ last_speed = speed;
} else {
- last_speed = -1;
- speed = -1;
- }
- }
+ last_speed = -1;
+ speed = -1;
+ }
+ }
- lastPosition = nextPos;
+ lastPosition = nextPos;
if (ev.isGUI()) updateDisplayString();
- fixIfHostGetsOutside();
+ fixIfHostGetsOutside();
emitMobilityStateChangedSignal();
- updateVisualRepresentation();
+ updateVisualRepresentation();
}
void TraCIMobility::updateDisplayString() {
- ASSERT(-M_PI <= angle);
- ASSERT(angle < M_PI);
+ ASSERT(-M_PI <= angle);
+ ASSERT(angle < M_PI);
- getParentModule()->getDisplayString().setTagArg("b", 2, "rect");
- getParentModule()->getDisplayString().setTagArg("b", 3, "red");
- getParentModule()->getDisplayString().setTagArg("b", 4, "red");
- getParentModule()->getDisplayString().setTagArg("b", 5, "0");
+ getParentModule()->getDisplayString().setTagArg("b", 2, "rect");
+ getParentModule()->getDisplayString().setTagArg("b", 3, "red");
+ getParentModule()->getDisplayString().setTagArg("b", 4, "red");
+ getParentModule()->getDisplayString().setTagArg("b", 5, "0");
if (angle < -M_PI + 0.5 * M_PI_4 * 1) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2190");
- getParentModule()->getDisplayString().setTagArg("b", 0, "4");
- getParentModule()->getDisplayString().setTagArg("b", 1, "2");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2190");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "4");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "2");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 3) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2199");
- getParentModule()->getDisplayString().setTagArg("b", 0, "3");
- getParentModule()->getDisplayString().setTagArg("b", 1, "3");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2199");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "3");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "3");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 5) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2193");
- getParentModule()->getDisplayString().setTagArg("b", 0, "2");
- getParentModule()->getDisplayString().setTagArg("b", 1, "4");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2193");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "2");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "4");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 7) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2198");
- getParentModule()->getDisplayString().setTagArg("b", 0, "3");
- getParentModule()->getDisplayString().setTagArg("b", 1, "3");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2198");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "3");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "3");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 9) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2192");
- getParentModule()->getDisplayString().setTagArg("b", 0, "4");
- getParentModule()->getDisplayString().setTagArg("b", 1, "2");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2192");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "4");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "2");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 11) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2197");
- getParentModule()->getDisplayString().setTagArg("b", 0, "3");
- getParentModule()->getDisplayString().setTagArg("b", 1, "3");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2197");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "3");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "3");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 13) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2191");
- getParentModule()->getDisplayString().setTagArg("b", 0, "2");
- getParentModule()->getDisplayString().setTagArg("b", 1, "4");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2191");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "2");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "4");
+ }
else if (angle < -M_PI + 0.5 * M_PI_4 * 15) {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2196");
- getParentModule()->getDisplayString().setTagArg("b", 0, "3");
- getParentModule()->getDisplayString().setTagArg("b", 1, "3");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2196");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "3");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "3");
+ }
else {
- getParentModule()->getDisplayString().setTagArg("t", 0, "\u2190");
- getParentModule()->getDisplayString().setTagArg("b", 0, "4");
- getParentModule()->getDisplayString().setTagArg("b", 1, "2");
- }
+ getParentModule()->getDisplayString().setTagArg("t", 0, "\u2190");
+ getParentModule()->getDisplayString().setTagArg("b", 0, "4");
+ getParentModule()->getDisplayString().setTagArg("b", 1, "2");
+ }
}
void TraCIMobility::fixIfHostGetsOutside()
{
- raiseErrorIfOutside();
+ raiseErrorIfOutside();
}
double TraCIMobility::calculateCO2emission(double v, double a) const {
- // Calculate CO2 emission parameters according to:
- // Cappiello, A. and Chabini, I. and Nam, E.K. and Lue, A. and Abou Zeid, M., "A statistical model of vehicle emissions and fuel consumption," IEEE 5th International Conference on Intelligent Transportation Systems (IEEE ITSC), pp. 801-809, 2002
+ // Calculate CO2 emission parameters according to:
+ // Cappiello, A. and Chabini, I. and Nam, E.K. and Lue, A. and Abou Zeid, M., "A statistical model of vehicle emissions and fuel consumption," IEEE 5th International Conference on Intelligent Transportation Systems (IEEE ITSC), pp. 801-809, 2002
- double A = 1000 * 0.1326; // W/m/s
- double B = 1000 * 2.7384e-03; // W/(m/s)^2
- double C = 1000 * 1.0843e-03; // W/(m/s)^3
- double M = 1325.0; // kg
+ double A = 1000 * 0.1326; // W/m/s
+ double B = 1000 * 2.7384e-03; // W/(m/s)^2
+ double C = 1000 * 1.0843e-03; // W/(m/s)^3
+ double M = 1325.0; // kg
- // power in W
+ // power in W
double P_tract = A*v + B*v*v + C*v*v*v + M*a*v; // for sloped roads: +M*g*sin_theta*v
- /*
- // "Category 7 vehicle" (e.g. a '92 Suzuki Swift)
- double alpha = 1.01;
- double beta = 0.0162;
- double delta = 1.90e-06;
- double zeta = 0.252;
- double alpha1 = 0.985;
- */
-
- // "Category 9 vehicle" (e.g. a '94 Dodge Spirit)
- double alpha = 1.11;
- double beta = 0.0134;
- double delta = 1.98e-06;
- double zeta = 0.241;
- double alpha1 = 0.973;
+ /*
+ // "Category 7 vehicle" (e.g. a '92 Suzuki Swift)
+ double alpha = 1.01;
+ double beta = 0.0162;
+ double delta = 1.90e-06;
+ double zeta = 0.252;
+ double alpha1 = 0.985;
+ */
+
+ // "Category 9 vehicle" (e.g. a '94 Dodge Spirit)
+ double alpha = 1.11;
+ double beta = 0.0134;
+ double delta = 1.98e-06;
+ double zeta = 0.241;
+ double alpha1 = 0.973;
if (P_tract <= 0) return alpha1;
return alpha + beta*v*3.6 + delta*v*v*v*(3.6*3.6*3.6) + zeta*a*v;
View
35 src/mobility/models/TraCIMobility.h
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
//
// Documentation for these modules is at http://veins.car2x.org/
//
@@ -26,19 +26,27 @@
#include <list>
#include <stdexcept>
+#include <omnetpp.h>
+
#include "MobilityBase.h"
#include "ModuleAccess.h"
#include "world/traci/TraCIScenarioManager.h"
/**
* @brief
- * TraCIMobility is a mobility module for hosts controlled by TraCIScenarioManager.
- * It receives position and state updates from an external module and updates
- * the parent module accordingly.
- * See NED file for more info.
+ * Used in modules created by the TraCIScenarioManager.
+ *
+ * This module relies on the TraCIScenarioManager for state updates
+ * and can not be used on its own.
+ *
+ * See the Veins website <a href="http://veins.car2x.org/"> for a tutorial, documentation, and publications </a>.
+ *
+ * @author Christoph Sommer, David Eckhoff, Luca Bedogni, Bastian Halmos
+ *
+ * @see TraCIScenarioManager
+ * @see TraCIScenarioManagerLaunchd
*
* @ingroup mobility
- * @author Christoph Sommer
*/
class INET_API TraCIMobility : public MobilityBase
{
@@ -73,7 +81,7 @@ class INET_API TraCIMobility : public MobilityBase
virtual void handleSelfMessage(cMessage *msg);
virtual void preInitialize(std::string external_id, const Coord& position, std::string road_id = "", double speed = -1, double angle = -1);
- virtual void nextPosition(const Coord& position, std::string road_id = "", double speed = -1, double angle = -1);
+ virtual void nextPosition(const Coord& position, std::string road_id = "", double speed = -1, double angle = -1, TraCIScenarioManager::VehicleSignal signals = TraCIScenarioManager::VEH_SIGNAL_UNDEF);
virtual void move();
virtual void updateDisplayString();
virtual void setExternalId(std::string external_id) {
@@ -94,6 +102,10 @@ class INET_API TraCIMobility : public MobilityBase
if (speed == -1) throw cRuntimeError("TraCIMobility::getSpeed called with no speed set yet");
return speed;
}
+ virtual TraCIScenarioManager::VehicleSignal getSignals() const {
+ if (signals == -1) throw cRuntimeError("TraCIMobility::getSignals called with no signals set yet");
+ return signals;
+ }
/**
* returns angle in rads, 0 being east, with -M_PI <= angle < M_PI.
*/
@@ -114,6 +126,14 @@ class INET_API TraCIMobility : public MobilityBase
void commandChangeRoute(std::string roadId, double travelTime) {
getManager()->commandChangeRoute(getExternalId(), roadId, travelTime);
}
+
+ void commandNewRoute(std::string roadId) {
+ getManager()->commandNewRoute(getExternalId(), roadId);
+ }
+ void commandParkVehicle() {
+ getManager()->commandSetVehicleParking(getExternalId());
+ }
+
double commandDistanceRequest(Coord position1, Coord position2, bool returnDrivingDistance) {
return getManager()->commandDistanceRequest(position1, position2, returnDrivingDistance);
}
@@ -157,6 +177,7 @@ class INET_API TraCIMobility : public MobilityBase
std::string road_id; /**< updated by nextPosition() */
double speed; /**< updated by nextPosition() */
double angle; /**< updated by nextPosition() */
+ TraCIScenarioManager::VehicleSignal signals; /**<updated by nextPosition() */
cMessage* startAccidentMsg;
cMessage* stopAccidentMsg;
View
16 src/mobility/models/TraCIMobility.ned
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
//
// Documentation for these modules is at http://veins.car2x.org/
//
@@ -21,9 +21,17 @@
package inet.mobility.models;
//
-// TraCIMobility is a mobility module for hosts controlled by TraCIScenarioManager.
-// It receives position and state updates from an external module and updates
-// the parent module accordingly.
+// Used in modules created by the TraCIScenarioManager.
+//
+// This module relies on the TraCIScenarioManager for state updates
+// and can not be used on its own.
+//
+// See the Veins website <a href="http://veins.car2x.org/"> for a tutorial, documentation, and publications </a>.
+//
+// @author Christoph Sommer, David Eckhoff, Luca Bedogni, Bastian Halmos
+//
+// @see TraCIScenarioManager
+// @see TraCIScenarioManagerLaunchd
//
simple TraCIMobility extends MobilityBase
{
View
67 src/world/traci/TraCIScenarioManager.cc
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2006-2011 Christoph Sommer <christoph.sommer@uibk.ac.at>
+// Copyright (C) 2006-2012 Christoph Sommer <christoph.sommer@uibk.ac.at>
//
// Documentation for these modules is at http://veins.car2x.org/
//
@@ -52,11 +52,16 @@ void TraCIScenarioManager::initialize(int stage) {
return;
}
+
debug = par("debug");
+ connectAt = par("connectAt");
+ firstStepAt = par("firstStepAt");
updateInterval = par("updateInterval");
+ if (firstStepAt == -1) firstStepAt = connectAt + updateInterval;
moduleType = par("moduleType").stdstringValue();
moduleName = par("moduleName").stdstringValue();
moduleDisplayString = par("moduleDisplayString").stdstringValue();
+ penetrationRate = par("penetrationRate").doubleValue();
host = par("host").stdstringValue();
port = par("port");
autoShutdown = par("autoShutdown");
@@ -94,16 +99,17 @@ void TraCIScenarioManager::initialize(int stage) {
activeVehicleCount = 0;
autoShutdownTriggered = false;
- executeOneTimestepTrigger = new cMessage("step");
- scheduleAt(0, executeOneTimestepTrigger);