daemon: added core.location class variable type hinting
This commit is contained in:
parent
fd341bd69b
commit
784c4d2419
5 changed files with 137 additions and 130 deletions
|
@ -12,6 +12,7 @@ from core.emulator.emudata import LinkOptions
|
||||||
from core.emulator.enumerations import ConfigDataTypes, TransportType
|
from core.emulator.enumerations import ConfigDataTypes, TransportType
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.location.mobility import WirelessModel
|
from core.location.mobility import WirelessModel
|
||||||
|
from core.nodes.base import CoreNode
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.xml import emanexml
|
from core.xml import emanexml
|
||||||
|
|
||||||
|
@ -139,13 +140,13 @@ class EmaneModel(WirelessModel):
|
||||||
"""
|
"""
|
||||||
logging.debug("emane model(%s) has no post setup tasks", self.name)
|
logging.debug("emane model(%s) has no post setup tasks", self.name)
|
||||||
|
|
||||||
def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
|
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
|
||||||
"""
|
"""
|
||||||
Invoked from MobilityModel when nodes are moved; this causes
|
Invoked from MobilityModel when nodes are moved; this causes
|
||||||
emane location events to be generated for the nodes in the moved
|
emane location events to be generated for the nodes in the moved
|
||||||
list, making EmaneModels compatible with Ns2ScriptedMobility.
|
list, making EmaneModels compatible with Ns2ScriptedMobility.
|
||||||
|
|
||||||
:param moved: were nodes moved
|
:param moved: moved nodes
|
||||||
:param moved_netifs: interfaces that were moved
|
:param moved_netifs: interfaces that were moved
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -6,7 +6,7 @@ import heapq
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
|
||||||
class Timer(threading.Thread):
|
class Timer(threading.Thread):
|
||||||
|
@ -16,34 +16,33 @@ class Timer(threading.Thread):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, interval: float, function: Callable, args: Any = None, kwargs: Any = None
|
self,
|
||||||
|
interval: float,
|
||||||
|
func: Callable[..., None],
|
||||||
|
args: Tuple[Any] = None,
|
||||||
|
kwargs: Dict[Any, Any] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create a Timer instance.
|
Create a Timer instance.
|
||||||
|
|
||||||
:param interval: time interval
|
:param interval: time interval
|
||||||
:param function: function to call when timer finishes
|
:param func: function to call when timer finishes
|
||||||
:param args: function arguments
|
:param args: function arguments
|
||||||
:param kwargs: function keyword arguments
|
:param kwargs: function keyword arguments
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.interval = interval
|
self.interval: float = interval
|
||||||
self.function = function
|
self.func: Callable[..., None] = func
|
||||||
|
self.finished: threading.Event = threading.Event()
|
||||||
self.finished = threading.Event()
|
self._running: threading.Lock = threading.Lock()
|
||||||
self._running = threading.Lock()
|
|
||||||
|
|
||||||
# validate arguments were provided
|
# validate arguments were provided
|
||||||
if args:
|
if args is None:
|
||||||
self.args = args
|
args = ()
|
||||||
else:
|
self.args: Tuple[Any] = args
|
||||||
self.args = []
|
|
||||||
|
|
||||||
# validate keyword arguments were provided
|
# validate keyword arguments were provided
|
||||||
if kwargs:
|
if kwargs is None:
|
||||||
self.kwargs = kwargs
|
kwargs = {}
|
||||||
else:
|
self.kwargs: Dict[Any, Any] = kwargs
|
||||||
self.kwargs = {}
|
|
||||||
|
|
||||||
def cancel(self) -> bool:
|
def cancel(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -67,7 +66,7 @@ class Timer(threading.Thread):
|
||||||
self.finished.wait(self.interval)
|
self.finished.wait(self.interval)
|
||||||
with self._running:
|
with self._running:
|
||||||
if not self.finished.is_set():
|
if not self.finished.is_set():
|
||||||
self.function(*self.args, **self.kwargs)
|
self.func(*self.args, **self.kwargs)
|
||||||
self.finished.set()
|
self.finished.set()
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,7 +77,12 @@ class Event:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, eventnum: int, event_time: float, func: Callable, *args: Any, **kwds: Any
|
self,
|
||||||
|
eventnum: int,
|
||||||
|
event_time: float,
|
||||||
|
func: Callable[..., None],
|
||||||
|
*args: Any,
|
||||||
|
**kwds: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create an Event instance.
|
Create an Event instance.
|
||||||
|
@ -89,12 +93,12 @@ class Event:
|
||||||
:param args: function arguments
|
:param args: function arguments
|
||||||
:param kwds: function keyword arguments
|
:param kwds: function keyword arguments
|
||||||
"""
|
"""
|
||||||
self.eventnum = eventnum
|
self.eventnum: int = eventnum
|
||||||
self.time = event_time
|
self.time: float = event_time
|
||||||
self.func = func
|
self.func: Callable[..., None] = func
|
||||||
self.args = args
|
self.args: Tuple[Any] = args
|
||||||
self.kwds = kwds
|
self.kwds: Dict[Any, Any] = kwds
|
||||||
self.canceled = False
|
self.canceled: bool = False
|
||||||
|
|
||||||
def __lt__(self, other: "Event") -> bool:
|
def __lt__(self, other: "Event") -> bool:
|
||||||
result = self.time < other.time
|
result = self.time < other.time
|
||||||
|
@ -118,7 +122,6 @@ class Event:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
# XXX not thread-safe
|
|
||||||
self.canceled = True
|
self.canceled = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,14 +134,14 @@ class EventLoop:
|
||||||
"""
|
"""
|
||||||
Creates a EventLoop instance.
|
Creates a EventLoop instance.
|
||||||
"""
|
"""
|
||||||
self.lock = threading.RLock()
|
self.lock: threading.RLock = threading.RLock()
|
||||||
self.queue = []
|
self.queue: List[Event] = []
|
||||||
self.eventnum = 0
|
self.eventnum: int = 0
|
||||||
self.timer = None
|
self.timer: Optional[Timer] = None
|
||||||
self.running = False
|
self.running: bool = False
|
||||||
self.start = None
|
self.start: Optional[float] = None
|
||||||
|
|
||||||
def __run_events(self) -> None:
|
def _run_events(self) -> None:
|
||||||
"""
|
"""
|
||||||
Run events.
|
Run events.
|
||||||
|
|
||||||
|
@ -161,9 +164,9 @@ class EventLoop:
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.timer = None
|
self.timer = None
|
||||||
if schedule:
|
if schedule:
|
||||||
self.__schedule_event()
|
self._schedule_event()
|
||||||
|
|
||||||
def __schedule_event(self) -> None:
|
def _schedule_event(self) -> None:
|
||||||
"""
|
"""
|
||||||
Schedule event.
|
Schedule event.
|
||||||
|
|
||||||
|
@ -177,7 +180,7 @@ class EventLoop:
|
||||||
delay = self.queue[0].time - time.monotonic()
|
delay = self.queue[0].time - time.monotonic()
|
||||||
if self.timer:
|
if self.timer:
|
||||||
raise ValueError("timer was already set")
|
raise ValueError("timer was already set")
|
||||||
self.timer = Timer(delay, self.__run_events)
|
self.timer = Timer(delay, self._run_events)
|
||||||
self.timer.daemon = True
|
self.timer.daemon = True
|
||||||
self.timer.start()
|
self.timer.start()
|
||||||
|
|
||||||
|
@ -194,7 +197,7 @@ class EventLoop:
|
||||||
self.start = time.monotonic()
|
self.start = time.monotonic()
|
||||||
for event in self.queue:
|
for event in self.queue:
|
||||||
event.time += self.start
|
event.time += self.start
|
||||||
self.__schedule_event()
|
self._schedule_event()
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -242,5 +245,5 @@ class EventLoop:
|
||||||
if self.timer is not None and self.timer.cancel():
|
if self.timer is not None and self.timer.cancel():
|
||||||
self.timer = None
|
self.timer = None
|
||||||
if self.running and self.timer is None:
|
if self.running and self.timer is None:
|
||||||
self.__schedule_event()
|
self._schedule_event()
|
||||||
return event
|
return event
|
||||||
|
|
|
@ -6,6 +6,7 @@ import logging
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import pyproj
|
import pyproj
|
||||||
|
from pyproj import Transformer
|
||||||
|
|
||||||
from core.emulator.enumerations import RegisterTlvs
|
from core.emulator.enumerations import RegisterTlvs
|
||||||
|
|
||||||
|
@ -20,21 +21,23 @@ class GeoLocation:
|
||||||
defined projections.
|
defined projections.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "location"
|
name: str = "location"
|
||||||
config_type = RegisterTlvs.UTILITY
|
config_type: RegisterTlvs = RegisterTlvs.UTILITY
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""
|
"""
|
||||||
Creates a GeoLocation instance.
|
Creates a GeoLocation instance.
|
||||||
"""
|
"""
|
||||||
self.to_pixels = pyproj.Transformer.from_crs(
|
self.to_pixels: Transformer = pyproj.Transformer.from_crs(
|
||||||
CRS_WGS84, CRS_PROJ, always_xy=True
|
CRS_WGS84, CRS_PROJ, always_xy=True
|
||||||
)
|
)
|
||||||
self.to_geo = pyproj.Transformer.from_crs(CRS_PROJ, CRS_WGS84, always_xy=True)
|
self.to_geo: Transformer = pyproj.Transformer.from_crs(
|
||||||
self.refproj = (0.0, 0.0, 0.0)
|
CRS_PROJ, CRS_WGS84, always_xy=True
|
||||||
self.refgeo = (0.0, 0.0, 0.0)
|
)
|
||||||
self.refxyz = (0.0, 0.0, 0.0)
|
self.refproj: Tuple[float, float, float] = (0.0, 0.0, 0.0)
|
||||||
self.refscale = 1.0
|
self.refgeo: Tuple[float, float, float] = (0.0, 0.0, 0.0)
|
||||||
|
self.refxyz: Tuple[float, float, float] = (0.0, 0.0, 0.0)
|
||||||
|
self.refscale: float = 1.0
|
||||||
|
|
||||||
def setrefgeo(self, lat: float, lon: float, alt: float) -> None:
|
def setrefgeo(self, lat: float, lon: float, alt: float) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,7 +9,7 @@ import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
from typing import TYPE_CHECKING, Dict, List, Tuple
|
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.config import ConfigGroup, ConfigurableOptions, Configuration, ModelManager
|
from core.config import ConfigGroup, ConfigurableOptions, Configuration, ModelManager
|
||||||
|
@ -23,7 +23,7 @@ from core.emulator.enumerations import (
|
||||||
RegisterTlvs,
|
RegisterTlvs,
|
||||||
)
|
)
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
from core.nodes.base import CoreNode, NodeBase
|
from core.nodes.base import CoreNode
|
||||||
from core.nodes.interface import CoreInterface
|
from core.nodes.interface import CoreInterface
|
||||||
from core.nodes.network import WlanNode
|
from core.nodes.network import WlanNode
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class MobilityManager(ModelManager):
|
||||||
:param session: session this manager is tied to
|
:param session: session this manager is tied to
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.session = session
|
self.session: "Session" = session
|
||||||
self.models[BasicRangeModel.name] = BasicRangeModel
|
self.models[BasicRangeModel.name] = BasicRangeModel
|
||||||
self.models[Ns2ScriptedMobility.name] = Ns2ScriptedMobility
|
self.models[Ns2ScriptedMobility.name] = Ns2ScriptedMobility
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ class MobilityManager(ModelManager):
|
||||||
self.session.broadcast_event(event_data)
|
self.session.broadcast_event(event_data)
|
||||||
|
|
||||||
def updatewlans(
|
def updatewlans(
|
||||||
self, moved: List[NodeBase], moved_netifs: List[CoreInterface]
|
self, moved: List[CoreNode], moved_netifs: List[CoreInterface]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
A mobility script has caused nodes in the 'moved' list to move.
|
A mobility script has caused nodes in the 'moved' list to move.
|
||||||
|
@ -204,21 +204,21 @@ class WirelessModel(ConfigurableOptions):
|
||||||
Used for managing arbitrary configuration parameters.
|
Used for managing arbitrary configuration parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config_type = RegisterTlvs.WIRELESS
|
config_type: RegisterTlvs = RegisterTlvs.WIRELESS
|
||||||
bitmap = None
|
bitmap: str = None
|
||||||
position_callback = None
|
position_callback: Callable[[CoreInterface], None] = None
|
||||||
|
|
||||||
def __init__(self, session: "Session", _id: int):
|
def __init__(self, session: "Session", _id: int) -> None:
|
||||||
"""
|
"""
|
||||||
Create a WirelessModel instance.
|
Create a WirelessModel instance.
|
||||||
|
|
||||||
:param session: core session we are tied to
|
:param session: core session we are tied to
|
||||||
:param _id: object id
|
:param _id: object id
|
||||||
"""
|
"""
|
||||||
self.session = session
|
self.session: "Session" = session
|
||||||
self.id = _id
|
self.id: int = _id
|
||||||
|
|
||||||
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List:
|
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
|
||||||
"""
|
"""
|
||||||
May be used if the model can populate the GUI with wireless (green)
|
May be used if the model can populate the GUI with wireless (green)
|
||||||
link lines.
|
link lines.
|
||||||
|
@ -228,11 +228,11 @@ class WirelessModel(ConfigurableOptions):
|
||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
|
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
|
||||||
"""
|
"""
|
||||||
Update this wireless model.
|
Update this wireless model.
|
||||||
|
|
||||||
:param moved: flag is it was moved
|
:param moved: moved nodes
|
||||||
:param moved_netifs: moved network interfaces
|
:param moved_netifs: moved network interfaces
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
@ -256,8 +256,8 @@ class BasicRangeModel(WirelessModel):
|
||||||
the GUI.
|
the GUI.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "basic_range"
|
name: str = "basic_range"
|
||||||
options = [
|
options: List[Configuration] = [
|
||||||
Configuration(
|
Configuration(
|
||||||
_id="range",
|
_id="range",
|
||||||
_type=ConfigDataTypes.UINT32,
|
_type=ConfigDataTypes.UINT32,
|
||||||
|
@ -299,15 +299,15 @@ class BasicRangeModel(WirelessModel):
|
||||||
:param _id: object id
|
:param _id: object id
|
||||||
"""
|
"""
|
||||||
super().__init__(session, _id)
|
super().__init__(session, _id)
|
||||||
self.session = session
|
self.session: "Session" = session
|
||||||
self.wlan = session.get_node(_id, WlanNode)
|
self.wlan: WlanNode = session.get_node(_id, WlanNode)
|
||||||
self._netifs = {}
|
self._netifs: Dict[CoreInterface, Tuple[float, float, float]] = {}
|
||||||
self._netifslock = threading.Lock()
|
self._netifslock: threading.Lock = threading.Lock()
|
||||||
self.range = 0
|
self.range: int = 0
|
||||||
self.bw = None
|
self.bw: Optional[int] = None
|
||||||
self.delay = None
|
self.delay: Optional[int] = None
|
||||||
self.loss = None
|
self.loss: Optional[float] = None
|
||||||
self.jitter = None
|
self.jitter: Optional[int] = None
|
||||||
|
|
||||||
def _get_config(self, current_value: int, config: Dict[str, str], name: str) -> int:
|
def _get_config(self, current_value: int, config: Dict[str, str], name: str) -> int:
|
||||||
"""
|
"""
|
||||||
|
@ -374,14 +374,14 @@ class BasicRangeModel(WirelessModel):
|
||||||
|
|
||||||
position_callback = set_position
|
position_callback = set_position
|
||||||
|
|
||||||
def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
|
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
|
||||||
"""
|
"""
|
||||||
Node positions have changed without recalc. Update positions from
|
Node positions have changed without recalc. Update positions from
|
||||||
node.position, then re-calculate links for those that have moved.
|
node.position, then re-calculate links for those that have moved.
|
||||||
Assumes bidirectional links, with one calculation per node pair, where
|
Assumes bidirectional links, with one calculation per node pair, where
|
||||||
one of the nodes has moved.
|
one of the nodes has moved.
|
||||||
|
|
||||||
:param moved: flag is it was moved
|
:param moved: moved nodes
|
||||||
:param moved_netifs: moved network interfaces
|
:param moved_netifs: moved network interfaces
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
@ -535,29 +535,35 @@ class WayPoint:
|
||||||
Maintains information regarding waypoints.
|
Maintains information regarding waypoints.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, time: float, nodenum: int, coords, speed: float):
|
def __init__(
|
||||||
|
self,
|
||||||
|
_time: float,
|
||||||
|
node_id: int,
|
||||||
|
coords: Tuple[float, float, float],
|
||||||
|
speed: float,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Creates a WayPoint instance.
|
Creates a WayPoint instance.
|
||||||
|
|
||||||
:param time: waypoint time
|
:param _time: waypoint time
|
||||||
:param nodenum: node id
|
:param node_id: node id
|
||||||
:param coords: waypoint coordinates
|
:param coords: waypoint coordinates
|
||||||
:param speed: waypoint speed
|
:param speed: waypoint speed
|
||||||
"""
|
"""
|
||||||
self.time = time
|
self.time: float = _time
|
||||||
self.nodenum = nodenum
|
self.node_id: int = node_id
|
||||||
self.coords = coords
|
self.coords: Tuple[float, float, float] = coords
|
||||||
self.speed = speed
|
self.speed: float = speed
|
||||||
|
|
||||||
def __eq__(self, other: "WayPoint") -> bool:
|
def __eq__(self, other: "WayPoint") -> bool:
|
||||||
return (self.time, self.nodenum) == (other.time, other.nodenum)
|
return (self.time, self.node_id) == (other.time, other.node_id)
|
||||||
|
|
||||||
def __ne__(self, other: "WayPoint") -> bool:
|
def __ne__(self, other: "WayPoint") -> bool:
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
def __lt__(self, other: "WayPoint") -> bool:
|
def __lt__(self, other: "WayPoint") -> bool:
|
||||||
if self.time == other.time:
|
if self.time == other.time:
|
||||||
return self.nodenum < other.nodenum
|
return self.node_id < other.node_id
|
||||||
else:
|
else:
|
||||||
return self.time < other.time
|
return self.time < other.time
|
||||||
|
|
||||||
|
@ -567,12 +573,11 @@ class WayPointMobility(WirelessModel):
|
||||||
Abstract class for mobility models that set node waypoints.
|
Abstract class for mobility models that set node waypoints.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "waypoint"
|
name: str = "waypoint"
|
||||||
config_type = RegisterTlvs.MOBILITY
|
config_type: RegisterTlvs = RegisterTlvs.MOBILITY
|
||||||
|
STATE_STOPPED: int = 0
|
||||||
STATE_STOPPED = 0
|
STATE_RUNNING: int = 1
|
||||||
STATE_RUNNING = 1
|
STATE_PAUSED: int = 2
|
||||||
STATE_PAUSED = 2
|
|
||||||
|
|
||||||
def __init__(self, session: "Session", _id: int) -> None:
|
def __init__(self, session: "Session", _id: int) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -583,20 +588,21 @@ class WayPointMobility(WirelessModel):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
super().__init__(session=session, _id=_id)
|
super().__init__(session=session, _id=_id)
|
||||||
self.state = self.STATE_STOPPED
|
self.state: int = self.STATE_STOPPED
|
||||||
self.queue = []
|
self.queue: List[WayPoint] = []
|
||||||
self.queue_copy = []
|
self.queue_copy: List[WayPoint] = []
|
||||||
self.points = {}
|
self.points: Dict[int, WayPoint] = {}
|
||||||
self.initial = {}
|
self.initial: Dict[int, WayPoint] = {}
|
||||||
self.lasttime = None
|
self.lasttime: Optional[float] = None
|
||||||
self.endtime = None
|
self.endtime: Optional[int] = None
|
||||||
self.wlan = session.get_node(_id, WlanNode)
|
self.timezero: float = 0.0
|
||||||
|
self.wlan: WlanNode = session.get_node(_id, WlanNode)
|
||||||
# these are really set in child class via confmatrix
|
# these are really set in child class via confmatrix
|
||||||
self.loop = False
|
self.loop: bool = False
|
||||||
self.refresh_ms = 50
|
self.refresh_ms: int = 50
|
||||||
# flag whether to stop scheduling when queue is empty
|
# flag whether to stop scheduling when queue is empty
|
||||||
# (ns-3 sets this to False as new waypoints may be added from trace)
|
# (ns-3 sets this to False as new waypoints may be added from trace)
|
||||||
self.empty_queue_stop = True
|
self.empty_queue_stop: bool = True
|
||||||
|
|
||||||
def runround(self) -> None:
|
def runround(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -684,16 +690,11 @@ class WayPointMobility(WirelessModel):
|
||||||
self.setnodeposition(node, x2, y2, z2)
|
self.setnodeposition(node, x2, y2, z2)
|
||||||
del self.points[node.id]
|
del self.points[node.id]
|
||||||
return True
|
return True
|
||||||
# speed can be a velocity vector or speed value
|
|
||||||
if isinstance(speed, (float, int)):
|
# linear speed value
|
||||||
# linear speed value
|
alpha = math.atan2(y2 - y1, x2 - x1)
|
||||||
alpha = math.atan2(y2 - y1, x2 - x1)
|
sx = speed * math.cos(alpha)
|
||||||
sx = speed * math.cos(alpha)
|
sy = speed * math.sin(alpha)
|
||||||
sy = speed * math.sin(alpha)
|
|
||||||
else:
|
|
||||||
# velocity vector
|
|
||||||
sx = speed[0]
|
|
||||||
sy = speed[1]
|
|
||||||
|
|
||||||
# calculate dt * speed = distance moved
|
# calculate dt * speed = distance moved
|
||||||
dx = sx * dt
|
dx = sx * dt
|
||||||
|
@ -776,7 +777,7 @@ class WayPointMobility(WirelessModel):
|
||||||
if self.queue[0].time > now:
|
if self.queue[0].time > now:
|
||||||
break
|
break
|
||||||
wp = heapq.heappop(self.queue)
|
wp = heapq.heappop(self.queue)
|
||||||
self.points[wp.nodenum] = wp
|
self.points[wp.node_id] = wp
|
||||||
|
|
||||||
def copywaypoints(self) -> None:
|
def copywaypoints(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -876,8 +877,8 @@ class Ns2ScriptedMobility(WayPointMobility):
|
||||||
BonnMotion.
|
BonnMotion.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "ns2script"
|
name: str = "ns2script"
|
||||||
options = [
|
options: List[Configuration] = [
|
||||||
Configuration(
|
Configuration(
|
||||||
_id="file", _type=ConfigDataTypes.STRING, label="mobility script file"
|
_id="file", _type=ConfigDataTypes.STRING, label="mobility script file"
|
||||||
),
|
),
|
||||||
|
@ -923,7 +924,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
||||||
ConfigGroup("ns-2 Mobility Script Parameters", 1, len(cls.configurations()))
|
ConfigGroup("ns-2 Mobility Script Parameters", 1, len(cls.configurations()))
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, session: "Session", _id: int):
|
def __init__(self, session: "Session", _id: int) -> None:
|
||||||
"""
|
"""
|
||||||
Creates a Ns2ScriptedMobility instance.
|
Creates a Ns2ScriptedMobility instance.
|
||||||
|
|
||||||
|
@ -931,17 +932,14 @@ class Ns2ScriptedMobility(WayPointMobility):
|
||||||
:param _id: object id
|
:param _id: object id
|
||||||
"""
|
"""
|
||||||
super().__init__(session, _id)
|
super().__init__(session, _id)
|
||||||
self._netifs = {}
|
self.file: Optional[str] = None
|
||||||
self._netifslock = threading.Lock()
|
self.refresh_ms: Optional[int] = None
|
||||||
|
self.loop: Optional[bool] = None
|
||||||
self.file = None
|
self.autostart: Optional[str] = None
|
||||||
self.refresh_ms = None
|
self.nodemap: Dict[int, int] = {}
|
||||||
self.loop = None
|
self.script_start: Optional[str] = None
|
||||||
self.autostart = None
|
self.script_pause: Optional[str] = None
|
||||||
self.nodemap = {}
|
self.script_stop: Optional[str] = None
|
||||||
self.script_start = None
|
|
||||||
self.script_pause = None
|
|
||||||
self.script_stop = None
|
|
||||||
|
|
||||||
def update_config(self, config: Dict[str, str]) -> None:
|
def update_config(self, config: Dict[str, str]) -> None:
|
||||||
self.file = config["file"]
|
self.file = config["file"]
|
||||||
|
|
|
@ -2,15 +2,17 @@ import pytest
|
||||||
|
|
||||||
from core.location.mobility import WayPoint
|
from core.location.mobility import WayPoint
|
||||||
|
|
||||||
|
POSITION = (0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
|
||||||
class TestMobility:
|
class TestMobility:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"wp1, wp2, expected",
|
"wp1, wp2, expected",
|
||||||
[
|
[
|
||||||
(WayPoint(10.0, 1, [0, 0], 1.0), WayPoint(1.0, 2, [0, 0], 1.0), False),
|
(WayPoint(10.0, 1, POSITION, 1.0), WayPoint(1.0, 2, POSITION, 1.0), False),
|
||||||
(WayPoint(1.0, 1, [0, 0], 1.0), WayPoint(10.0, 2, [0, 0], 1.0), True),
|
(WayPoint(1.0, 1, POSITION, 1.0), WayPoint(10.0, 2, POSITION, 1.0), True),
|
||||||
(WayPoint(1.0, 1, [0, 0], 1.0), WayPoint(1.0, 2, [0, 0], 1.0), True),
|
(WayPoint(1.0, 1, POSITION, 1.0), WayPoint(1.0, 2, POSITION, 1.0), True),
|
||||||
(WayPoint(1.0, 2, [0, 0], 1.0), WayPoint(1.0, 1, [0, 0], 1.0), False),
|
(WayPoint(1.0, 2, POSITION, 1.0), WayPoint(1.0, 1, POSITION, 1.0), False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_waypoint_lessthan(self, wp1, wp2, expected):
|
def test_waypoint_lessthan(self, wp1, wp2, expected):
|
||||||
|
|
Loading…
Reference in a new issue