From c18eb039811f422ac4b9f1a004c57c94cfeec988 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 7 Dec 2018 20:05:41 +0530 Subject: [PATCH 01/20] * Added new scenario in control_loss.py * Added new atomic SteerVehicle * Added new criteria ReachedLocationTest * Added new scenario to list in scenario_runner.py --- ScenarioManager/atomic_scenario_behavior.py | 41 +++++++ ScenarioManager/atomic_scenario_criteria.py | 42 +++++++ Scenarios/control_loss.py | 124 ++++++++++++++++++++ scenario_runner.py | 7 +- 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 Scenarios/control_loss.py diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 9fb243d42..af592900f 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -201,9 +201,14 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING +<<<<<<< 211b9fbc35138cf2a3f18736fb53036ed40447f0 delta_velocity = CarlaDataProvider.get_velocity( self._vehicle) - self._target_velocity if delta_velocity < EPSILON: +======= + if (CarlaDataProvider.get_velocity( + self.vehicle) - self.target_velocity) < EPSILON: +>>>>>>> * Added new scenario in control_loss.py new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % @@ -635,3 +640,39 @@ def terminate(self, new_status): self._control.brake = 0.0 self._vehicle.apply_control(self._control) super(SyncArrival, self).terminate(new_status) + +class SteerVehicle(AtomicBehavior): + + """ + This class contains an atomic control loss behavior. + The vehicle looses control with steering angle. + """ + + def __init__(self, vehicle, steer_value, name="Steering"): + """ + Setup vehicle and maximum steer value + """ + super(SteerVehicle, self).__init__(name) + self.logger.debug("%s.__init__()" % (self.__class__.__name__)) + self.control = carla.VehicleControl() + self.vehicle = vehicle + self.steer_value = steer_value + + def update(self): + """ + Set steer to steer_value until reaching full stop + """ + new_status = py_trees.common.Status.RUNNING + + if CarlaDataProvider.get_velocity(self.vehicle) > EPSILON: + self.control.steer = self.steer_value + new_status = py_trees.common.Status.SUCCESS + else: + new_status = py_trees.common.Status.FAILURE + self.control.steer = 0 + + self.logger.debug("%s.update()[%s->%s]" % + (self.__class__.__name__, self.status, new_status)) + self.vehicle.apply_control(self.control) + + return new_status diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index f95e2591e..89dbd9887 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -354,3 +354,45 @@ def _count_lane_invasion(weak_self, event): if not self: return self.actual_value += 1 + + +class ReachedRegionTest(Criterion): + + """ + This class contains the reached region test + """ + + def __init__(self, vehicle, min_x, max_x, min_y, + max_y, name="ReachedRegionTest"): + """ + Setup trigger region (rectangle provided by + [min_x,min_y] and [max_x,max_y] + """ + super(ReachedRegionTest, self).__init__(name, vehicle, 0) + self.logger.debug("%s.__init__()" % (self.__class__.__name__)) + self.vehicle = vehicle + self.min_x = min_x + self.max_x = max_x + self.min_y = min_y + self.max_y = max_y + + def update(self): + """ + Check if the vehicle location is within trigger region + """ + new_status = py_trees.common.Status.RUNNING + + location = CarlaDataProvider.get_location(self.vehicle) + + if location is None: + return new_status + + not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( + location.y < self.min_y or location.y > self.max_y) + if not not_in_region: + new_status = py_trees.common.Status.SUCCESS + + self.logger.debug("%s.update()[%s->%s]" % + (self.__class__.__name__, self.status, new_status)) + + return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py new file mode 100644 index 000000000..d41cbafe9 --- /dev/null +++ b/Scenarios/control_loss.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +# +# This work is licensed under the terms of the MIT license. +# For a copy, see . + +""" +Control Loss Vehicle scenario: + +The scenario realizes that the vehicle looses control due to +bad road conditions, etc. +""" + +import random +import sys + +import py_trees +import carla + +from ScenarioManager.atomic_scenario_behavior import * +from ScenarioManager.atomic_scenario_criteria import * +from ScenarioManager.scenario_manager import Scenario +from ScenarioManager.timer import TimeOut +from Scenarios.basic_scenario import * + + +class ControlLoss(BasicScenario): + + """ + This class holds everything required for a simple "Control Loss Vehicle" + to perform jitter sequence with steering angle. + """ + + timeout = 60 # Timeout of scenario in seconds + + # ego vehicle parameters + ego_vehicle_model = 'vehicle.carlamotors.carlacola' + ego_vehicle_start = carla.Transform( + carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) + ego_vehicle_max_steer = 0.1 + no_of_jitter_actions = 5 + ego_vehicle_driven_distance = 35 + + # other vehicle parameter + other_vehicles = [] + + def __init__(self, world, debug_mode=False): + """ + Setup all relevant parameters and create scenario + and instantiate scenario manager + """ + self.ego_vehicle = setup_vehicle(world, + self.ego_vehicle_model, + self.ego_vehicle_start, + hero=True) + + super(ControlLoss, self).__init__(name="ControlLoss", + debug_mode=debug_mode) + + def create_behavior(self): + """ + The scenario defined after is a "control loss vehicle" scenario. After + invoking this scenario, it will wait for the user controlled vehicle to + enter the start region, then it performs a jitter action. Finally, the user-controlled + vehicle has to reach a target region. + If this does not happen within 60 seconds, a timeout stops the scenario + """ + + # start condition + startcondition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + + # jitter sequence + jitterSequence = py_trees.composites.Sequence( + "Jitter Sequence Behavior") + jitterTimeout = TimeOut(timeout=1.0, name="Timeout for next jitter") + + for i in range(self.no_of_jitter_actions): + jitter_steer = self.ego_vehicle_max_steer + if i % 2 != 0: + jitter_steer = self.ego_vehicle_max_steer * -1.0 + # turn vehicle + turn = SteerVehicle( + self.ego_vehicle, + jitter_steer, + name='Steering ' + str(i)) + jitterAction = py_trees.composites.Parallel("Jitter Actions with Timeouts", + policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ALL) + jitterAction.add_child(turn) + if i == 0: + jitterAction.add_child(TimeOut(0.5)) + else: + jitterAction.add_child(jitterTimeout) + jitterSequence.add_child(jitterAction) + + # Build behavior tree + sequence = py_trees.composites.Sequence("Sequence Behavior") + sequence.add_child(startcondition) + sequence.add_child(jitterSequence) + sequence.add_child(TimeOut(20)) + return sequence + + def create_test_criteria(self): + """ + A list of all test criteria will be created that is later used + in parallel behavior tree. + """ + criteria = [] + + collision_criterion = CollisionTest(self.ego_vehicle) + driven_distance_criterion = DrivenDistanceTest( + self.ego_vehicle, + self.ego_vehicle_driven_distance) + reached_region_criterion = ReachedRegionTest( + self.ego_vehicle, + 115, 120, + 104, 110) + keep_lane_criterion = KeepLaneTest(self.ego_vehicle) + + criteria.append(collision_criterion) + criteria.append(driven_distance_criterion) + criteria.append(reached_region_criterion) + criteria.append(keep_lane_criterion) + + return criteria diff --git a/scenario_runner.py b/scenario_runner.py index 09bf88523..722ea257b 100644 --- a/scenario_runner.py +++ b/scenario_runner.py @@ -24,6 +24,7 @@ from Scenarios.object_crash_vehicle import * from Scenarios.no_signal_junction_crossing import NoSignalJunctionCrossing from Scenarios.object_crash_intersection import * +from Scenarios.control_loss import * from ScenarioManager.scenario_manager import ScenarioManager @@ -40,7 +41,8 @@ "OppositeVehicleRunningRedLight", "NoSignalJunctionCrossing", "VehicleTurningRight", - "VehicleTurningLeft" + "VehicleTurningLeft", + "ControlLoss" } @@ -100,7 +102,8 @@ def main(args): if args.junit is not None: junit_filename = args.junit.split(".")[0] + "_{}.xml".format(i) - if not manager.analyze_scenario(args.output, args.filename, junit_filename): + if not manager.analyze_scenario( + args.output, args.filename, junit_filename): print("Success!") else: print("Failure!") From 53ea36ca136d5b39f39f25a829a402f131f2c285 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 13 Dec 2018 11:44:21 +0530 Subject: [PATCH 02/20] * Changed steering noise to Gauss sampling * Fixed ReachedRegion criteria * Fixed SteerVehicle --- ScenarioManager/atomic_scenario_behavior.py | 14 ++----- ScenarioManager/atomic_scenario_criteria.py | 8 +++- Scenarios/control_loss.py | 43 +++++++++------------ 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index af592900f..5c2aa1f08 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -644,8 +644,8 @@ def terminate(self, new_status): class SteerVehicle(AtomicBehavior): """ - This class contains an atomic control loss behavior. - The vehicle looses control with steering angle. + This class contains an atomic steer behavior. + To set the steer value of the vehicle. """ def __init__(self, vehicle, steer_value, name="Steering"): @@ -662,14 +662,8 @@ def update(self): """ Set steer to steer_value until reaching full stop """ - new_status = py_trees.common.Status.RUNNING - - if CarlaDataProvider.get_velocity(self.vehicle) > EPSILON: - self.control.steer = self.steer_value - new_status = py_trees.common.Status.SUCCESS - else: - new_status = py_trees.common.Status.FAILURE - self.control.steer = 0 + self.control.steer = self.steer_value + new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 89dbd9887..dd66ab359 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -390,9 +390,15 @@ def update(self): not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( location.y < self.min_y or location.y > self.max_y) if not not_in_region: - new_status = py_trees.common.Status.SUCCESS + self.test_status = "FAILURE" + else: + self.test_status = "SUCCESS" + + if self.terminate_on_failure and (self.test_status == "FAILURE"): + new_status = py_trees.common.Status.FAILURE self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) + print("Reached location criteria ", new_status) return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index d41cbafe9..71d00648a 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -8,7 +8,8 @@ Control Loss Vehicle scenario: The scenario realizes that the vehicle looses control due to -bad road conditions, etc. +bad road conditions, etc. and checks to see if the vehicle +regains control and corrects it's course. """ import random @@ -27,8 +28,7 @@ class ControlLoss(BasicScenario): """ - This class holds everything required for a simple "Control Loss Vehicle" - to perform jitter sequence with steering angle. + Implementation of "Control Loss Vehicle" (Traffic Scenario 01) """ timeout = 60 # Timeout of scenario in seconds @@ -37,13 +37,9 @@ class ControlLoss(BasicScenario): ego_vehicle_model = 'vehicle.carlamotors.carlacola' ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) - ego_vehicle_max_steer = 0.1 - no_of_jitter_actions = 5 + no_of_jitter_actions = 20 ego_vehicle_driven_distance = 35 - # other vehicle parameter - other_vehicles = [] - def __init__(self, world, debug_mode=False): """ Setup all relevant parameters and create scenario @@ -61,8 +57,8 @@ def create_behavior(self): """ The scenario defined after is a "control loss vehicle" scenario. After invoking this scenario, it will wait for the user controlled vehicle to - enter the start region, then it performs a jitter action. Finally, the user-controlled - vehicle has to reach a target region. + enter the start region, then it performs a jitter action. Finally, + the user-controlled vehicle has to reach a target region. If this does not happen within 60 seconds, a timeout stops the scenario """ @@ -72,31 +68,30 @@ def create_behavior(self): # jitter sequence jitterSequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=1.0, name="Timeout for next jitter") + jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") for i in range(self.no_of_jitter_actions): - jitter_steer = self.ego_vehicle_max_steer - if i % 2 != 0: - jitter_steer = self.ego_vehicle_max_steer * -1.0 + ego_vehicle_max_steer = random.gauss(0, 0.2) + # turn vehicle turn = SteerVehicle( self.ego_vehicle, - jitter_steer, + ego_vehicle_max_steer, name='Steering ' + str(i)) - jitterAction = py_trees.composites.Parallel("Jitter Actions with Timeouts", - policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ALL) + + jitterAction = py_trees.composites.Parallel( + "Jitter Actions with Timeouts", + policy=py_trees.common. + ParallelPolicy.SUCCESS_ON_ALL) jitterAction.add_child(turn) - if i == 0: - jitterAction.add_child(TimeOut(0.5)) - else: - jitterAction.add_child(jitterTimeout) + jitterAction.add_child(jitterTimeout) jitterSequence.add_child(jitterAction) # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") sequence.add_child(startcondition) sequence.add_child(jitterSequence) - sequence.add_child(TimeOut(20)) + sequence.add_child(TimeOut(60)) return sequence def create_test_criteria(self): @@ -113,12 +108,10 @@ def create_test_criteria(self): reached_region_criterion = ReachedRegionTest( self.ego_vehicle, 115, 120, - 104, 110) - keep_lane_criterion = KeepLaneTest(self.ego_vehicle) + 109, 112) criteria.append(collision_criterion) criteria.append(driven_distance_criterion) criteria.append(reached_region_criterion) - criteria.append(keep_lane_criterion) return criteria From d098c5da24dd5ac271f3aed227f706593109feed Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 13 Dec 2018 12:39:24 +0530 Subject: [PATCH 03/20] Changed to new _ method names --- ScenarioManager/atomic_scenario_criteria.py | 3 +-- Scenarios/control_loss.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index dd66ab359..4f30e0146 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -394,11 +394,10 @@ def update(self): else: self.test_status = "SUCCESS" - if self.terminate_on_failure and (self.test_status == "FAILURE"): + if self._terminate_on_failure and (self.test_status == "FAILURE"): new_status = py_trees.common.Status.FAILURE self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) - print("Reached location criteria ", new_status) return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 71d00648a..cf76c6743 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -53,7 +53,7 @@ def __init__(self, world, debug_mode=False): super(ControlLoss, self).__init__(name="ControlLoss", debug_mode=debug_mode) - def create_behavior(self): + def _create_behavior(self): """ The scenario defined after is a "control loss vehicle" scenario. After invoking this scenario, it will wait for the user controlled vehicle to @@ -94,7 +94,7 @@ def create_behavior(self): sequence.add_child(TimeOut(60)) return sequence - def create_test_criteria(self): + def _create_test_criteria(self): """ A list of all test criteria will be created that is later used in parallel behavior tree. From 474c60295c8375a495a8ee98d94ba00af29b1878 Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Fri, 14 Dec 2018 18:16:25 +0530 Subject: [PATCH 04/20] * Code formatting * Removed duplicate class definition * Changed to _ private members * Added to docstring --- Scenarios/control_loss.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index cf76c6743..555dd4bd2 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -29,16 +29,18 @@ class ControlLoss(BasicScenario): """ Implementation of "Control Loss Vehicle" (Traffic Scenario 01) + + Location : Town02 """ timeout = 60 # Timeout of scenario in seconds # ego vehicle parameters - ego_vehicle_model = 'vehicle.carlamotors.carlacola' - ego_vehicle_start = carla.Transform( + _ego_vehicle_model = 'vehicle.carlamotors.carlacola' + _ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) - no_of_jitter_actions = 20 - ego_vehicle_driven_distance = 35 + _no_of_jitter_actions = 20 + _ego_vehicle_driven_distance = 35 def __init__(self, world, debug_mode=False): """ @@ -46,8 +48,8 @@ def __init__(self, world, debug_mode=False): and instantiate scenario manager """ self.ego_vehicle = setup_vehicle(world, - self.ego_vehicle_model, - self.ego_vehicle_start, + self._ego_vehicle_model, + self._ego_vehicle_start, hero=True) super(ControlLoss, self).__init__(name="ControlLoss", @@ -70,7 +72,7 @@ def _create_behavior(self): "Jitter Sequence Behavior") jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") - for i in range(self.no_of_jitter_actions): + for i in range(self._no_of_jitter_actions): ego_vehicle_max_steer = random.gauss(0, 0.2) # turn vehicle @@ -104,7 +106,8 @@ def _create_test_criteria(self): collision_criterion = CollisionTest(self.ego_vehicle) driven_distance_criterion = DrivenDistanceTest( self.ego_vehicle, - self.ego_vehicle_driven_distance) + self._ego_vehicle_driven_distance) + # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, 115, 120, From b573cced8abe1678938304c5a5802f45611c661b Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Fri, 14 Dec 2018 18:58:54 +0530 Subject: [PATCH 05/20] * Parameterised noise characteristics --- Scenarios/control_loss.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 555dd4bd2..1f3c3920c 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -41,6 +41,8 @@ class ControlLoss(BasicScenario): carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 _ego_vehicle_driven_distance = 35 + _noise_mean = 0 # Mean value of steering noise + _noise_std = 0.1 # Std. deviation of steerning noise def __init__(self, world, debug_mode=False): """ @@ -73,7 +75,7 @@ def _create_behavior(self): jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): - ego_vehicle_max_steer = random.gauss(0, 0.2) + ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) # turn vehicle turn = SteerVehicle( From 36e2cb7167ddeef22dee91fe1babbb19f6bc97ef Mon Sep 17 00:00:00 2001 From: Subhashini Date: Tue, 18 Dec 2018 12:19:13 +0100 Subject: [PATCH 06/20] * Added new end condition * Changed private members to _* * Increased jitter noise * Removed redundant criteria --- ScenarioManager/atomic_scenario_behavior.py | 10 +++++----- ScenarioManager/atomic_scenario_criteria.py | 16 ++++++++-------- Scenarios/control_loss.py | 17 +++++++++-------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 5c2aa1f08..55fd3952a 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -654,19 +654,19 @@ def __init__(self, vehicle, steer_value, name="Steering"): """ super(SteerVehicle, self).__init__(name) self.logger.debug("%s.__init__()" % (self.__class__.__name__)) - self.control = carla.VehicleControl() - self.vehicle = vehicle - self.steer_value = steer_value + self._control = carla.VehicleControl() + self._vehicle = vehicle + self._steer_value = steer_value def update(self): """ Set steer to steer_value until reaching full stop """ - self.control.steer = self.steer_value + self._control.steer = self._steer_value new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) - self.vehicle.apply_control(self.control) + self._vehicle.apply_control(self._control) return new_status diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 4f30e0146..9920a0251 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -370,11 +370,11 @@ def __init__(self, vehicle, min_x, max_x, min_y, """ super(ReachedRegionTest, self).__init__(name, vehicle, 0) self.logger.debug("%s.__init__()" % (self.__class__.__name__)) - self.vehicle = vehicle - self.min_x = min_x - self.max_x = max_x - self.min_y = min_y - self.max_y = max_y + self._vehicle = vehicle + self._min_x = min_x + self._max_x = max_x + self._min_y = min_y + self._max_y = max_y def update(self): """ @@ -382,13 +382,13 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING - location = CarlaDataProvider.get_location(self.vehicle) + location = CarlaDataProvider.get_location(self._vehicle) if location is None: return new_status - not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( - location.y < self.min_y or location.y > self.max_y) + not_in_region = (location.x < self._min_x or location.x > self._max_x) or ( + location.y < self._min_y or location.y > self._max_y) if not not_in_region: self.test_status = "FAILURE" else: diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 1f3c3920c..dcd9f16f8 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -13,7 +13,6 @@ """ import random -import sys import py_trees import carla @@ -42,7 +41,7 @@ class ControlLoss(BasicScenario): _no_of_jitter_actions = 20 _ego_vehicle_driven_distance = 35 _noise_mean = 0 # Mean value of steering noise - _noise_std = 0.1 # Std. deviation of steerning noise + _noise_std = 0.3 # Std. deviation of steerning noise def __init__(self, world, debug_mode=False): """ @@ -72,7 +71,7 @@ def _create_behavior(self): # jitter sequence jitterSequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") + jitterTimeout = TimeOut(timeout=0.2, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) @@ -91,11 +90,17 @@ def _create_behavior(self): jitterAction.add_child(jitterTimeout) jitterSequence.add_child(jitterAction) + target_location = carla.Location(x=150, y=112, z=2.0) + + # endcondition + endcondition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, + "InDistanceLocation") + # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") sequence.add_child(startcondition) sequence.add_child(jitterSequence) - sequence.add_child(TimeOut(60)) + sequence.add_child(endcondition) return sequence def _create_test_criteria(self): @@ -106,9 +111,6 @@ def _create_test_criteria(self): criteria = [] collision_criterion = CollisionTest(self.ego_vehicle) - driven_distance_criterion = DrivenDistanceTest( - self.ego_vehicle, - self._ego_vehicle_driven_distance) # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, @@ -116,7 +118,6 @@ def _create_test_criteria(self): 109, 112) criteria.append(collision_criterion) - criteria.append(driven_distance_criterion) criteria.append(reached_region_criterion) return criteria From c4fe00d19e4046df64c8e90e66cc3d91b34511e2 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Wed, 19 Dec 2018 12:12:46 +0100 Subject: [PATCH 07/20] * Fixed rebase * Added narrow dynamic mean noise * Fixed reached location criteria * Formatting --- ScenarioManager/atomic_scenario_criteria.py | 22 +++++----- Scenarios/control_loss.py | 46 ++++++++++++--------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 9920a0251..d09f985cc 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -360,6 +360,7 @@ class ReachedRegionTest(Criterion): """ This class contains the reached region test + The test is a success if the vehicle reaches a specified region """ def __init__(self, vehicle, min_x, max_x, min_y, @@ -383,19 +384,20 @@ def update(self): new_status = py_trees.common.Status.RUNNING location = CarlaDataProvider.get_location(self._vehicle) - if location is None: return new_status - not_in_region = (location.x < self._min_x or location.x > self._max_x) or ( - location.y < self._min_y or location.y > self._max_y) - if not not_in_region: - self.test_status = "FAILURE" - else: - self.test_status = "SUCCESS" - - if self._terminate_on_failure and (self.test_status == "FAILURE"): - new_status = py_trees.common.Status.FAILURE + in_region = False + if self.test_status != "SUCCESS": + in_region = (location.x > self._min_x and location.x < self._max_x) and ( + location.y > self._min_y and location.y < self._max_y) + if in_region: + self.test_status = "SUCCESS" + else: + self.test_status = "RUNNING" + + if self.test_status == "SUCCESS": + new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index dcd9f16f8..73157d726 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -39,9 +39,9 @@ class ControlLoss(BasicScenario): _ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 - _ego_vehicle_driven_distance = 35 _noise_mean = 0 # Mean value of steering noise - _noise_std = 0.3 # Std. deviation of steerning noise + _noise_std = 0.02 # Std. deviation of steerning noise + _dynamic_mean = 0.05 def __init__(self, world, debug_mode=False): """ @@ -53,8 +53,11 @@ def __init__(self, world, debug_mode=False): self._ego_vehicle_start, hero=True) - super(ControlLoss, self).__init__(name="ControlLoss", - debug_mode=debug_mode) + super(ControlLoss, self).__init__( + name="ControlLoss", + town="Town02", + world=world, + debug_mode=debug_mode) def _create_behavior(self): """ @@ -66,15 +69,20 @@ def _create_behavior(self): """ # start condition - startcondition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + start_condition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) # jitter sequence - jitterSequence = py_trees.composites.Sequence( + jitter_sequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=0.2, name="Timeout for next jitter") + jitter_timeout = TimeOut(timeout=0.2, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): - ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) + ego_vehicle_max_steer = random.gauss( + self._noise_mean, self._noise_std) + if ego_vehicle_max_steer > 0: + ego_vehicle_max_steer += self._dynamic_mean + elif ego_vehicle_max_steer < 0: + ego_vehicle_max_steer -= self._dynamic_mean # turn vehicle turn = SteerVehicle( @@ -82,25 +90,25 @@ def _create_behavior(self): ego_vehicle_max_steer, name='Steering ' + str(i)) - jitterAction = py_trees.composites.Parallel( + jitter_action = py_trees.composites.Parallel( "Jitter Actions with Timeouts", policy=py_trees.common. ParallelPolicy.SUCCESS_ON_ALL) - jitterAction.add_child(turn) - jitterAction.add_child(jitterTimeout) - jitterSequence.add_child(jitterAction) + jitter_action.add_child(turn) + jitter_action.add_child(jitter_timeout) + jitter_sequence.add_child(jitter_action) target_location = carla.Location(x=150, y=112, z=2.0) # endcondition - endcondition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, - "InDistanceLocation") + end_condition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, + "InDistanceLocation") # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") - sequence.add_child(startcondition) - sequence.add_child(jitterSequence) - sequence.add_child(endcondition) + sequence.add_child(start_condition) + sequence.add_child(jitter_sequence) + sequence.add_child(end_condition) return sequence def _create_test_criteria(self): @@ -114,8 +122,8 @@ def _create_test_criteria(self): # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, - 115, 120, - 109, 112) + 125, 130, + 107, 111) criteria.append(collision_criterion) criteria.append(reached_region_criterion) From be293ff1d157d7e7298d067f309e2a41fa43d682 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 20 Dec 2018 13:05:04 +0100 Subject: [PATCH 08/20] Changed the location to Town03 --- Scenarios/control_loss.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 73157d726..3ce99fbb5 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -29,7 +29,7 @@ class ControlLoss(BasicScenario): """ Implementation of "Control Loss Vehicle" (Traffic Scenario 01) - Location : Town02 + Location : Town03 """ timeout = 60 # Timeout of scenario in seconds @@ -37,7 +37,7 @@ class ControlLoss(BasicScenario): # ego vehicle parameters _ego_vehicle_model = 'vehicle.carlamotors.carlacola' _ego_vehicle_start = carla.Transform( - carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) + carla.Location(x=15, y=207.2, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 _noise_mean = 0 # Mean value of steering noise _noise_std = 0.02 # Std. deviation of steerning noise @@ -55,7 +55,7 @@ def __init__(self, world, debug_mode=False): super(ControlLoss, self).__init__( name="ControlLoss", - town="Town02", + town="Town03", world=world, debug_mode=debug_mode) @@ -69,7 +69,7 @@ def _create_behavior(self): """ # start condition - start_condition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + start_condition = InTriggerRegion(self.ego_vehicle, 43, 49, 190, 210) # jitter sequence jitter_sequence = py_trees.composites.Sequence( @@ -98,11 +98,8 @@ def _create_behavior(self): jitter_action.add_child(jitter_timeout) jitter_sequence.add_child(jitter_action) - target_location = carla.Location(x=150, y=112, z=2.0) - # endcondition - end_condition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, - "InDistanceLocation") + end_condition = InTriggerRegion(self.ego_vehicle, 145, 150, 190, 210) # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") @@ -122,8 +119,8 @@ def _create_test_criteria(self): # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, - 125, 130, - 107, 111) + 113, 119, + 204.2, 210.2) criteria.append(collision_criterion) criteria.append(reached_region_criterion) From 97e52acae2535bbb75bb535601edc018c9f3c20b Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 21 Dec 2018 11:44:40 +0100 Subject: [PATCH 09/20] Updated the document for ControlLoss scenario --- Docs/list_of_scenarios.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Docs/list_of_scenarios.md b/Docs/list_of_scenarios.md index 6fd1a02a5..7701b15ef 100644 --- a/Docs/list_of_scenarios.md +++ b/Docs/list_of_scenarios.md @@ -63,3 +63,8 @@ through a junction without signal. The ego vehicle is passing through a junction without traffic lights And encounters another vehicle passing across the junction. The ego vehicle has to avoid collision and navigate accross the junction to succeed. + +### ControlLoss +In this scenario control loss of a vehicle is tested due to bad road conditions, etc +and it checks whether the vehicle is regained its control and corrected its course. + From a906945d39a2dc99b42a2dcb1a26368ab2d2f839 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 21 Dec 2018 22:13:52 +0100 Subject: [PATCH 10/20] Resolved the conflicts --- ScenarioManager/atomic_scenario_behavior.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 55fd3952a..6cd5dbd84 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -201,14 +201,9 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING -<<<<<<< 211b9fbc35138cf2a3f18736fb53036ed40447f0 delta_velocity = CarlaDataProvider.get_velocity( self._vehicle) - self._target_velocity if delta_velocity < EPSILON: -======= - if (CarlaDataProvider.get_velocity( - self.vehicle) - self.target_velocity) < EPSILON: ->>>>>>> * Added new scenario in control_loss.py new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % From a274260109cca32fbb536683363df7f02b26c065 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 7 Dec 2018 20:05:41 +0530 Subject: [PATCH 11/20] * Added new scenario in control_loss.py * Added new atomic SteerVehicle * Added new criteria ReachedLocationTest * Added new scenario to list in scenario_runner.py --- ScenarioManager/atomic_scenario_behavior.py | 41 +++++++ ScenarioManager/atomic_scenario_criteria.py | 42 +++++++ Scenarios/control_loss.py | 124 ++++++++++++++++++++ scenario_runner.py | 7 +- 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 Scenarios/control_loss.py diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 9fb243d42..af592900f 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -201,9 +201,14 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING +<<<<<<< 211b9fbc35138cf2a3f18736fb53036ed40447f0 delta_velocity = CarlaDataProvider.get_velocity( self._vehicle) - self._target_velocity if delta_velocity < EPSILON: +======= + if (CarlaDataProvider.get_velocity( + self.vehicle) - self.target_velocity) < EPSILON: +>>>>>>> * Added new scenario in control_loss.py new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % @@ -635,3 +640,39 @@ def terminate(self, new_status): self._control.brake = 0.0 self._vehicle.apply_control(self._control) super(SyncArrival, self).terminate(new_status) + +class SteerVehicle(AtomicBehavior): + + """ + This class contains an atomic control loss behavior. + The vehicle looses control with steering angle. + """ + + def __init__(self, vehicle, steer_value, name="Steering"): + """ + Setup vehicle and maximum steer value + """ + super(SteerVehicle, self).__init__(name) + self.logger.debug("%s.__init__()" % (self.__class__.__name__)) + self.control = carla.VehicleControl() + self.vehicle = vehicle + self.steer_value = steer_value + + def update(self): + """ + Set steer to steer_value until reaching full stop + """ + new_status = py_trees.common.Status.RUNNING + + if CarlaDataProvider.get_velocity(self.vehicle) > EPSILON: + self.control.steer = self.steer_value + new_status = py_trees.common.Status.SUCCESS + else: + new_status = py_trees.common.Status.FAILURE + self.control.steer = 0 + + self.logger.debug("%s.update()[%s->%s]" % + (self.__class__.__name__, self.status, new_status)) + self.vehicle.apply_control(self.control) + + return new_status diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index f95e2591e..89dbd9887 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -354,3 +354,45 @@ def _count_lane_invasion(weak_self, event): if not self: return self.actual_value += 1 + + +class ReachedRegionTest(Criterion): + + """ + This class contains the reached region test + """ + + def __init__(self, vehicle, min_x, max_x, min_y, + max_y, name="ReachedRegionTest"): + """ + Setup trigger region (rectangle provided by + [min_x,min_y] and [max_x,max_y] + """ + super(ReachedRegionTest, self).__init__(name, vehicle, 0) + self.logger.debug("%s.__init__()" % (self.__class__.__name__)) + self.vehicle = vehicle + self.min_x = min_x + self.max_x = max_x + self.min_y = min_y + self.max_y = max_y + + def update(self): + """ + Check if the vehicle location is within trigger region + """ + new_status = py_trees.common.Status.RUNNING + + location = CarlaDataProvider.get_location(self.vehicle) + + if location is None: + return new_status + + not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( + location.y < self.min_y or location.y > self.max_y) + if not not_in_region: + new_status = py_trees.common.Status.SUCCESS + + self.logger.debug("%s.update()[%s->%s]" % + (self.__class__.__name__, self.status, new_status)) + + return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py new file mode 100644 index 000000000..d41cbafe9 --- /dev/null +++ b/Scenarios/control_loss.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +# +# This work is licensed under the terms of the MIT license. +# For a copy, see . + +""" +Control Loss Vehicle scenario: + +The scenario realizes that the vehicle looses control due to +bad road conditions, etc. +""" + +import random +import sys + +import py_trees +import carla + +from ScenarioManager.atomic_scenario_behavior import * +from ScenarioManager.atomic_scenario_criteria import * +from ScenarioManager.scenario_manager import Scenario +from ScenarioManager.timer import TimeOut +from Scenarios.basic_scenario import * + + +class ControlLoss(BasicScenario): + + """ + This class holds everything required for a simple "Control Loss Vehicle" + to perform jitter sequence with steering angle. + """ + + timeout = 60 # Timeout of scenario in seconds + + # ego vehicle parameters + ego_vehicle_model = 'vehicle.carlamotors.carlacola' + ego_vehicle_start = carla.Transform( + carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) + ego_vehicle_max_steer = 0.1 + no_of_jitter_actions = 5 + ego_vehicle_driven_distance = 35 + + # other vehicle parameter + other_vehicles = [] + + def __init__(self, world, debug_mode=False): + """ + Setup all relevant parameters and create scenario + and instantiate scenario manager + """ + self.ego_vehicle = setup_vehicle(world, + self.ego_vehicle_model, + self.ego_vehicle_start, + hero=True) + + super(ControlLoss, self).__init__(name="ControlLoss", + debug_mode=debug_mode) + + def create_behavior(self): + """ + The scenario defined after is a "control loss vehicle" scenario. After + invoking this scenario, it will wait for the user controlled vehicle to + enter the start region, then it performs a jitter action. Finally, the user-controlled + vehicle has to reach a target region. + If this does not happen within 60 seconds, a timeout stops the scenario + """ + + # start condition + startcondition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + + # jitter sequence + jitterSequence = py_trees.composites.Sequence( + "Jitter Sequence Behavior") + jitterTimeout = TimeOut(timeout=1.0, name="Timeout for next jitter") + + for i in range(self.no_of_jitter_actions): + jitter_steer = self.ego_vehicle_max_steer + if i % 2 != 0: + jitter_steer = self.ego_vehicle_max_steer * -1.0 + # turn vehicle + turn = SteerVehicle( + self.ego_vehicle, + jitter_steer, + name='Steering ' + str(i)) + jitterAction = py_trees.composites.Parallel("Jitter Actions with Timeouts", + policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ALL) + jitterAction.add_child(turn) + if i == 0: + jitterAction.add_child(TimeOut(0.5)) + else: + jitterAction.add_child(jitterTimeout) + jitterSequence.add_child(jitterAction) + + # Build behavior tree + sequence = py_trees.composites.Sequence("Sequence Behavior") + sequence.add_child(startcondition) + sequence.add_child(jitterSequence) + sequence.add_child(TimeOut(20)) + return sequence + + def create_test_criteria(self): + """ + A list of all test criteria will be created that is later used + in parallel behavior tree. + """ + criteria = [] + + collision_criterion = CollisionTest(self.ego_vehicle) + driven_distance_criterion = DrivenDistanceTest( + self.ego_vehicle, + self.ego_vehicle_driven_distance) + reached_region_criterion = ReachedRegionTest( + self.ego_vehicle, + 115, 120, + 104, 110) + keep_lane_criterion = KeepLaneTest(self.ego_vehicle) + + criteria.append(collision_criterion) + criteria.append(driven_distance_criterion) + criteria.append(reached_region_criterion) + criteria.append(keep_lane_criterion) + + return criteria diff --git a/scenario_runner.py b/scenario_runner.py index 09bf88523..722ea257b 100644 --- a/scenario_runner.py +++ b/scenario_runner.py @@ -24,6 +24,7 @@ from Scenarios.object_crash_vehicle import * from Scenarios.no_signal_junction_crossing import NoSignalJunctionCrossing from Scenarios.object_crash_intersection import * +from Scenarios.control_loss import * from ScenarioManager.scenario_manager import ScenarioManager @@ -40,7 +41,8 @@ "OppositeVehicleRunningRedLight", "NoSignalJunctionCrossing", "VehicleTurningRight", - "VehicleTurningLeft" + "VehicleTurningLeft", + "ControlLoss" } @@ -100,7 +102,8 @@ def main(args): if args.junit is not None: junit_filename = args.junit.split(".")[0] + "_{}.xml".format(i) - if not manager.analyze_scenario(args.output, args.filename, junit_filename): + if not manager.analyze_scenario( + args.output, args.filename, junit_filename): print("Success!") else: print("Failure!") From f1acaecebe3c224fd2c65a4a1adbe2dff28fdea8 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 13 Dec 2018 11:44:21 +0530 Subject: [PATCH 12/20] * Changed steering noise to Gauss sampling * Fixed ReachedRegion criteria * Fixed SteerVehicle --- ScenarioManager/atomic_scenario_behavior.py | 14 ++----- ScenarioManager/atomic_scenario_criteria.py | 8 +++- Scenarios/control_loss.py | 43 +++++++++------------ 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index af592900f..5c2aa1f08 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -644,8 +644,8 @@ def terminate(self, new_status): class SteerVehicle(AtomicBehavior): """ - This class contains an atomic control loss behavior. - The vehicle looses control with steering angle. + This class contains an atomic steer behavior. + To set the steer value of the vehicle. """ def __init__(self, vehicle, steer_value, name="Steering"): @@ -662,14 +662,8 @@ def update(self): """ Set steer to steer_value until reaching full stop """ - new_status = py_trees.common.Status.RUNNING - - if CarlaDataProvider.get_velocity(self.vehicle) > EPSILON: - self.control.steer = self.steer_value - new_status = py_trees.common.Status.SUCCESS - else: - new_status = py_trees.common.Status.FAILURE - self.control.steer = 0 + self.control.steer = self.steer_value + new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 89dbd9887..dd66ab359 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -390,9 +390,15 @@ def update(self): not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( location.y < self.min_y or location.y > self.max_y) if not not_in_region: - new_status = py_trees.common.Status.SUCCESS + self.test_status = "FAILURE" + else: + self.test_status = "SUCCESS" + + if self.terminate_on_failure and (self.test_status == "FAILURE"): + new_status = py_trees.common.Status.FAILURE self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) + print("Reached location criteria ", new_status) return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index d41cbafe9..71d00648a 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -8,7 +8,8 @@ Control Loss Vehicle scenario: The scenario realizes that the vehicle looses control due to -bad road conditions, etc. +bad road conditions, etc. and checks to see if the vehicle +regains control and corrects it's course. """ import random @@ -27,8 +28,7 @@ class ControlLoss(BasicScenario): """ - This class holds everything required for a simple "Control Loss Vehicle" - to perform jitter sequence with steering angle. + Implementation of "Control Loss Vehicle" (Traffic Scenario 01) """ timeout = 60 # Timeout of scenario in seconds @@ -37,13 +37,9 @@ class ControlLoss(BasicScenario): ego_vehicle_model = 'vehicle.carlamotors.carlacola' ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) - ego_vehicle_max_steer = 0.1 - no_of_jitter_actions = 5 + no_of_jitter_actions = 20 ego_vehicle_driven_distance = 35 - # other vehicle parameter - other_vehicles = [] - def __init__(self, world, debug_mode=False): """ Setup all relevant parameters and create scenario @@ -61,8 +57,8 @@ def create_behavior(self): """ The scenario defined after is a "control loss vehicle" scenario. After invoking this scenario, it will wait for the user controlled vehicle to - enter the start region, then it performs a jitter action. Finally, the user-controlled - vehicle has to reach a target region. + enter the start region, then it performs a jitter action. Finally, + the user-controlled vehicle has to reach a target region. If this does not happen within 60 seconds, a timeout stops the scenario """ @@ -72,31 +68,30 @@ def create_behavior(self): # jitter sequence jitterSequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=1.0, name="Timeout for next jitter") + jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") for i in range(self.no_of_jitter_actions): - jitter_steer = self.ego_vehicle_max_steer - if i % 2 != 0: - jitter_steer = self.ego_vehicle_max_steer * -1.0 + ego_vehicle_max_steer = random.gauss(0, 0.2) + # turn vehicle turn = SteerVehicle( self.ego_vehicle, - jitter_steer, + ego_vehicle_max_steer, name='Steering ' + str(i)) - jitterAction = py_trees.composites.Parallel("Jitter Actions with Timeouts", - policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ALL) + + jitterAction = py_trees.composites.Parallel( + "Jitter Actions with Timeouts", + policy=py_trees.common. + ParallelPolicy.SUCCESS_ON_ALL) jitterAction.add_child(turn) - if i == 0: - jitterAction.add_child(TimeOut(0.5)) - else: - jitterAction.add_child(jitterTimeout) + jitterAction.add_child(jitterTimeout) jitterSequence.add_child(jitterAction) # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") sequence.add_child(startcondition) sequence.add_child(jitterSequence) - sequence.add_child(TimeOut(20)) + sequence.add_child(TimeOut(60)) return sequence def create_test_criteria(self): @@ -113,12 +108,10 @@ def create_test_criteria(self): reached_region_criterion = ReachedRegionTest( self.ego_vehicle, 115, 120, - 104, 110) - keep_lane_criterion = KeepLaneTest(self.ego_vehicle) + 109, 112) criteria.append(collision_criterion) criteria.append(driven_distance_criterion) criteria.append(reached_region_criterion) - criteria.append(keep_lane_criterion) return criteria From 3a78bfeb50c65f91c6159ada906f3d78f5203e01 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 13 Dec 2018 12:39:24 +0530 Subject: [PATCH 13/20] Changed to new _ method names --- ScenarioManager/atomic_scenario_criteria.py | 3 +-- Scenarios/control_loss.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index dd66ab359..4f30e0146 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -394,11 +394,10 @@ def update(self): else: self.test_status = "SUCCESS" - if self.terminate_on_failure and (self.test_status == "FAILURE"): + if self._terminate_on_failure and (self.test_status == "FAILURE"): new_status = py_trees.common.Status.FAILURE self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) - print("Reached location criteria ", new_status) return new_status diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 71d00648a..cf76c6743 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -53,7 +53,7 @@ def __init__(self, world, debug_mode=False): super(ControlLoss, self).__init__(name="ControlLoss", debug_mode=debug_mode) - def create_behavior(self): + def _create_behavior(self): """ The scenario defined after is a "control loss vehicle" scenario. After invoking this scenario, it will wait for the user controlled vehicle to @@ -94,7 +94,7 @@ def create_behavior(self): sequence.add_child(TimeOut(60)) return sequence - def create_test_criteria(self): + def _create_test_criteria(self): """ A list of all test criteria will be created that is later used in parallel behavior tree. From 408d4528cb691cf2b3fce4a13f12991183560c6f Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Fri, 14 Dec 2018 18:16:25 +0530 Subject: [PATCH 14/20] * Code formatting * Removed duplicate class definition * Changed to _ private members * Added to docstring --- Scenarios/control_loss.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index cf76c6743..555dd4bd2 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -29,16 +29,18 @@ class ControlLoss(BasicScenario): """ Implementation of "Control Loss Vehicle" (Traffic Scenario 01) + + Location : Town02 """ timeout = 60 # Timeout of scenario in seconds # ego vehicle parameters - ego_vehicle_model = 'vehicle.carlamotors.carlacola' - ego_vehicle_start = carla.Transform( + _ego_vehicle_model = 'vehicle.carlamotors.carlacola' + _ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) - no_of_jitter_actions = 20 - ego_vehicle_driven_distance = 35 + _no_of_jitter_actions = 20 + _ego_vehicle_driven_distance = 35 def __init__(self, world, debug_mode=False): """ @@ -46,8 +48,8 @@ def __init__(self, world, debug_mode=False): and instantiate scenario manager """ self.ego_vehicle = setup_vehicle(world, - self.ego_vehicle_model, - self.ego_vehicle_start, + self._ego_vehicle_model, + self._ego_vehicle_start, hero=True) super(ControlLoss, self).__init__(name="ControlLoss", @@ -70,7 +72,7 @@ def _create_behavior(self): "Jitter Sequence Behavior") jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") - for i in range(self.no_of_jitter_actions): + for i in range(self._no_of_jitter_actions): ego_vehicle_max_steer = random.gauss(0, 0.2) # turn vehicle @@ -104,7 +106,8 @@ def _create_test_criteria(self): collision_criterion = CollisionTest(self.ego_vehicle) driven_distance_criterion = DrivenDistanceTest( self.ego_vehicle, - self.ego_vehicle_driven_distance) + self._ego_vehicle_driven_distance) + # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, 115, 120, From 0d988587962a8f2ce84ab01d57daa4233f31740c Mon Sep 17 00:00:00 2001 From: Praveen Kumar Date: Fri, 14 Dec 2018 18:58:54 +0530 Subject: [PATCH 15/20] * Parameterised noise characteristics --- Scenarios/control_loss.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 555dd4bd2..1f3c3920c 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -41,6 +41,8 @@ class ControlLoss(BasicScenario): carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 _ego_vehicle_driven_distance = 35 + _noise_mean = 0 # Mean value of steering noise + _noise_std = 0.1 # Std. deviation of steerning noise def __init__(self, world, debug_mode=False): """ @@ -73,7 +75,7 @@ def _create_behavior(self): jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): - ego_vehicle_max_steer = random.gauss(0, 0.2) + ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) # turn vehicle turn = SteerVehicle( From 3645b6ca7ea8c13ddb2eb7362d7afe8ca37f274d Mon Sep 17 00:00:00 2001 From: Subhashini Date: Tue, 18 Dec 2018 12:19:13 +0100 Subject: [PATCH 16/20] * Added new end condition * Changed private members to _* * Increased jitter noise * Removed redundant criteria --- ScenarioManager/atomic_scenario_behavior.py | 10 +++++----- ScenarioManager/atomic_scenario_criteria.py | 16 ++++++++-------- Scenarios/control_loss.py | 17 +++++++++-------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 5c2aa1f08..55fd3952a 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -654,19 +654,19 @@ def __init__(self, vehicle, steer_value, name="Steering"): """ super(SteerVehicle, self).__init__(name) self.logger.debug("%s.__init__()" % (self.__class__.__name__)) - self.control = carla.VehicleControl() - self.vehicle = vehicle - self.steer_value = steer_value + self._control = carla.VehicleControl() + self._vehicle = vehicle + self._steer_value = steer_value def update(self): """ Set steer to steer_value until reaching full stop """ - self.control.steer = self.steer_value + self._control.steer = self._steer_value new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) - self.vehicle.apply_control(self.control) + self._vehicle.apply_control(self._control) return new_status diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 4f30e0146..9920a0251 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -370,11 +370,11 @@ def __init__(self, vehicle, min_x, max_x, min_y, """ super(ReachedRegionTest, self).__init__(name, vehicle, 0) self.logger.debug("%s.__init__()" % (self.__class__.__name__)) - self.vehicle = vehicle - self.min_x = min_x - self.max_x = max_x - self.min_y = min_y - self.max_y = max_y + self._vehicle = vehicle + self._min_x = min_x + self._max_x = max_x + self._min_y = min_y + self._max_y = max_y def update(self): """ @@ -382,13 +382,13 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING - location = CarlaDataProvider.get_location(self.vehicle) + location = CarlaDataProvider.get_location(self._vehicle) if location is None: return new_status - not_in_region = (location.x < self.min_x or location.x > self.max_x) or ( - location.y < self.min_y or location.y > self.max_y) + not_in_region = (location.x < self._min_x or location.x > self._max_x) or ( + location.y < self._min_y or location.y > self._max_y) if not not_in_region: self.test_status = "FAILURE" else: diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 1f3c3920c..dcd9f16f8 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -13,7 +13,6 @@ """ import random -import sys import py_trees import carla @@ -42,7 +41,7 @@ class ControlLoss(BasicScenario): _no_of_jitter_actions = 20 _ego_vehicle_driven_distance = 35 _noise_mean = 0 # Mean value of steering noise - _noise_std = 0.1 # Std. deviation of steerning noise + _noise_std = 0.3 # Std. deviation of steerning noise def __init__(self, world, debug_mode=False): """ @@ -72,7 +71,7 @@ def _create_behavior(self): # jitter sequence jitterSequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=0.1, name="Timeout for next jitter") + jitterTimeout = TimeOut(timeout=0.2, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) @@ -91,11 +90,17 @@ def _create_behavior(self): jitterAction.add_child(jitterTimeout) jitterSequence.add_child(jitterAction) + target_location = carla.Location(x=150, y=112, z=2.0) + + # endcondition + endcondition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, + "InDistanceLocation") + # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") sequence.add_child(startcondition) sequence.add_child(jitterSequence) - sequence.add_child(TimeOut(60)) + sequence.add_child(endcondition) return sequence def _create_test_criteria(self): @@ -106,9 +111,6 @@ def _create_test_criteria(self): criteria = [] collision_criterion = CollisionTest(self.ego_vehicle) - driven_distance_criterion = DrivenDistanceTest( - self.ego_vehicle, - self._ego_vehicle_driven_distance) # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, @@ -116,7 +118,6 @@ def _create_test_criteria(self): 109, 112) criteria.append(collision_criterion) - criteria.append(driven_distance_criterion) criteria.append(reached_region_criterion) return criteria From 455d9a9d7e473301ae077210c6d70d7c0d7f1422 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Wed, 19 Dec 2018 12:12:46 +0100 Subject: [PATCH 17/20] * Fixed rebase * Added narrow dynamic mean noise * Fixed reached location criteria * Formatting --- ScenarioManager/atomic_scenario_criteria.py | 22 +++++----- Scenarios/control_loss.py | 46 ++++++++++++--------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/ScenarioManager/atomic_scenario_criteria.py b/ScenarioManager/atomic_scenario_criteria.py index 9920a0251..d09f985cc 100644 --- a/ScenarioManager/atomic_scenario_criteria.py +++ b/ScenarioManager/atomic_scenario_criteria.py @@ -360,6 +360,7 @@ class ReachedRegionTest(Criterion): """ This class contains the reached region test + The test is a success if the vehicle reaches a specified region """ def __init__(self, vehicle, min_x, max_x, min_y, @@ -383,19 +384,20 @@ def update(self): new_status = py_trees.common.Status.RUNNING location = CarlaDataProvider.get_location(self._vehicle) - if location is None: return new_status - not_in_region = (location.x < self._min_x or location.x > self._max_x) or ( - location.y < self._min_y or location.y > self._max_y) - if not not_in_region: - self.test_status = "FAILURE" - else: - self.test_status = "SUCCESS" - - if self._terminate_on_failure and (self.test_status == "FAILURE"): - new_status = py_trees.common.Status.FAILURE + in_region = False + if self.test_status != "SUCCESS": + in_region = (location.x > self._min_x and location.x < self._max_x) and ( + location.y > self._min_y and location.y < self._max_y) + if in_region: + self.test_status = "SUCCESS" + else: + self.test_status = "RUNNING" + + if self.test_status == "SUCCESS": + new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" % (self.__class__.__name__, self.status, new_status)) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index dcd9f16f8..73157d726 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -39,9 +39,9 @@ class ControlLoss(BasicScenario): _ego_vehicle_start = carla.Transform( carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 - _ego_vehicle_driven_distance = 35 _noise_mean = 0 # Mean value of steering noise - _noise_std = 0.3 # Std. deviation of steerning noise + _noise_std = 0.02 # Std. deviation of steerning noise + _dynamic_mean = 0.05 def __init__(self, world, debug_mode=False): """ @@ -53,8 +53,11 @@ def __init__(self, world, debug_mode=False): self._ego_vehicle_start, hero=True) - super(ControlLoss, self).__init__(name="ControlLoss", - debug_mode=debug_mode) + super(ControlLoss, self).__init__( + name="ControlLoss", + town="Town02", + world=world, + debug_mode=debug_mode) def _create_behavior(self): """ @@ -66,15 +69,20 @@ def _create_behavior(self): """ # start condition - startcondition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + start_condition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) # jitter sequence - jitterSequence = py_trees.composites.Sequence( + jitter_sequence = py_trees.composites.Sequence( "Jitter Sequence Behavior") - jitterTimeout = TimeOut(timeout=0.2, name="Timeout for next jitter") + jitter_timeout = TimeOut(timeout=0.2, name="Timeout for next jitter") for i in range(self._no_of_jitter_actions): - ego_vehicle_max_steer = random.gauss(self._noise_mean, self._noise_std) + ego_vehicle_max_steer = random.gauss( + self._noise_mean, self._noise_std) + if ego_vehicle_max_steer > 0: + ego_vehicle_max_steer += self._dynamic_mean + elif ego_vehicle_max_steer < 0: + ego_vehicle_max_steer -= self._dynamic_mean # turn vehicle turn = SteerVehicle( @@ -82,25 +90,25 @@ def _create_behavior(self): ego_vehicle_max_steer, name='Steering ' + str(i)) - jitterAction = py_trees.composites.Parallel( + jitter_action = py_trees.composites.Parallel( "Jitter Actions with Timeouts", policy=py_trees.common. ParallelPolicy.SUCCESS_ON_ALL) - jitterAction.add_child(turn) - jitterAction.add_child(jitterTimeout) - jitterSequence.add_child(jitterAction) + jitter_action.add_child(turn) + jitter_action.add_child(jitter_timeout) + jitter_sequence.add_child(jitter_action) target_location = carla.Location(x=150, y=112, z=2.0) # endcondition - endcondition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, - "InDistanceLocation") + end_condition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, + "InDistanceLocation") # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") - sequence.add_child(startcondition) - sequence.add_child(jitterSequence) - sequence.add_child(endcondition) + sequence.add_child(start_condition) + sequence.add_child(jitter_sequence) + sequence.add_child(end_condition) return sequence def _create_test_criteria(self): @@ -114,8 +122,8 @@ def _create_test_criteria(self): # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, - 115, 120, - 109, 112) + 125, 130, + 107, 111) criteria.append(collision_criterion) criteria.append(reached_region_criterion) From 2a10a492b125ad7f1f1d4f8e90282147761915f4 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Thu, 20 Dec 2018 13:05:04 +0100 Subject: [PATCH 18/20] Changed the location to Town03 --- Scenarios/control_loss.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Scenarios/control_loss.py b/Scenarios/control_loss.py index 73157d726..3ce99fbb5 100644 --- a/Scenarios/control_loss.py +++ b/Scenarios/control_loss.py @@ -29,7 +29,7 @@ class ControlLoss(BasicScenario): """ Implementation of "Control Loss Vehicle" (Traffic Scenario 01) - Location : Town02 + Location : Town03 """ timeout = 60 # Timeout of scenario in seconds @@ -37,7 +37,7 @@ class ControlLoss(BasicScenario): # ego vehicle parameters _ego_vehicle_model = 'vehicle.carlamotors.carlacola' _ego_vehicle_start = carla.Transform( - carla.Location(x=60, y=109.5, z=2.0), carla.Rotation(yaw=0)) + carla.Location(x=15, y=207.2, z=2.0), carla.Rotation(yaw=0)) _no_of_jitter_actions = 20 _noise_mean = 0 # Mean value of steering noise _noise_std = 0.02 # Std. deviation of steerning noise @@ -55,7 +55,7 @@ def __init__(self, world, debug_mode=False): super(ControlLoss, self).__init__( name="ControlLoss", - town="Town02", + town="Town03", world=world, debug_mode=debug_mode) @@ -69,7 +69,7 @@ def _create_behavior(self): """ # start condition - start_condition = InTriggerRegion(self.ego_vehicle, 75, 80, 100, 110) + start_condition = InTriggerRegion(self.ego_vehicle, 43, 49, 190, 210) # jitter sequence jitter_sequence = py_trees.composites.Sequence( @@ -98,11 +98,8 @@ def _create_behavior(self): jitter_action.add_child(jitter_timeout) jitter_sequence.add_child(jitter_action) - target_location = carla.Location(x=150, y=112, z=2.0) - # endcondition - end_condition = InTriggerDistanceToLocation(self.ego_vehicle, target_location, 10, - "InDistanceLocation") + end_condition = InTriggerRegion(self.ego_vehicle, 145, 150, 190, 210) # Build behavior tree sequence = py_trees.composites.Sequence("Sequence Behavior") @@ -122,8 +119,8 @@ def _create_test_criteria(self): # Region check to verify if the vehicle reached correct lane reached_region_criterion = ReachedRegionTest( self.ego_vehicle, - 125, 130, - 107, 111) + 113, 119, + 204.2, 210.2) criteria.append(collision_criterion) criteria.append(reached_region_criterion) From 446b5277a1b8240aa9723f9d6ca526e93b7744c4 Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 21 Dec 2018 11:44:40 +0100 Subject: [PATCH 19/20] Updated the document for ControlLoss scenario --- Docs/list_of_scenarios.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Docs/list_of_scenarios.md b/Docs/list_of_scenarios.md index 6fd1a02a5..7701b15ef 100644 --- a/Docs/list_of_scenarios.md +++ b/Docs/list_of_scenarios.md @@ -63,3 +63,8 @@ through a junction without signal. The ego vehicle is passing through a junction without traffic lights And encounters another vehicle passing across the junction. The ego vehicle has to avoid collision and navigate accross the junction to succeed. + +### ControlLoss +In this scenario control loss of a vehicle is tested due to bad road conditions, etc +and it checks whether the vehicle is regained its control and corrected its course. + From b3223d2a14f5f58632c89b46e06945160a7e6f1f Mon Sep 17 00:00:00 2001 From: Subhashini Date: Fri, 21 Dec 2018 22:13:52 +0100 Subject: [PATCH 20/20] Resolved the conflicts --- ScenarioManager/atomic_scenario_behavior.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ScenarioManager/atomic_scenario_behavior.py b/ScenarioManager/atomic_scenario_behavior.py index 55fd3952a..6cd5dbd84 100644 --- a/ScenarioManager/atomic_scenario_behavior.py +++ b/ScenarioManager/atomic_scenario_behavior.py @@ -201,14 +201,9 @@ def update(self): """ new_status = py_trees.common.Status.RUNNING -<<<<<<< 211b9fbc35138cf2a3f18736fb53036ed40447f0 delta_velocity = CarlaDataProvider.get_velocity( self._vehicle) - self._target_velocity if delta_velocity < EPSILON: -======= - if (CarlaDataProvider.get_velocity( - self.vehicle) - self.target_velocity) < EPSILON: ->>>>>>> * Added new scenario in control_loss.py new_status = py_trees.common.Status.SUCCESS self.logger.debug("%s.update()[%s->%s]" %