From acf43db7bc087e387de94b7ff86b74bf5e35d581 Mon Sep 17 00:00:00 2001 From: oysand Date: Tue, 3 Oct 2023 15:48:19 +0200 Subject: [PATCH] Make default localization pose optional for area --- .../EventHandlers/TestMissionEventHandler.cs | 2 +- backend/api.test/Services/MissionService.cs | 2 +- backend/api/Controllers/AreaController.cs | 60 ++++++++++++++++++- .../api/Controllers/Models/AreaResponse.cs | 2 +- .../api/Controllers/Models/CreateAreaQuery.cs | 2 +- .../api/Database/Context/FlotillaDbContext.cs | 5 -- backend/api/Database/Context/InitDb.cs | 12 ++-- backend/api/Database/Models/Area.cs | 4 +- backend/api/Services/AreaService.cs | 14 ++++- 9 files changed, 82 insertions(+), 21 deletions(-) diff --git a/backend/api.test/EventHandlers/TestMissionEventHandler.cs b/backend/api.test/EventHandlers/TestMissionEventHandler.cs index 22dd1466d..4335a80ae 100644 --- a/backend/api.test/EventHandlers/TestMissionEventHandler.cs +++ b/backend/api.test/EventHandlers/TestMissionEventHandler.cs @@ -109,7 +109,7 @@ public TestMissionEventHandler(DatabaseFixture fixture) Boundary = new Boundary(), TransformationMatrices = new TransformationMatrices() }, - DefaultLocalizationPose = new Pose(), + DefaultLocalizationPose = null, SafePositions = new List() }; diff --git a/backend/api.test/Services/MissionService.cs b/backend/api.test/Services/MissionService.cs index 7c9019c2b..18ac5d171 100644 --- a/backend/api.test/Services/MissionService.cs +++ b/backend/api.test/Services/MissionService.cs @@ -76,7 +76,7 @@ public async Task Create() Plant = testPlant, Name = "testArea", MapMetadata = new MapMetadata() { MapName = "testMap" }, - DefaultLocalizationPose = new Pose(), + DefaultLocalizationPose = null, SafePositions = new List() }, InstallationCode = "testInstallation", diff --git a/backend/api/Controllers/AreaController.cs b/backend/api/Controllers/AreaController.cs index 77372e874..8b6748ea0 100644 --- a/backend/api/Controllers/AreaController.cs +++ b/backend/api/Controllers/AreaController.cs @@ -12,6 +12,7 @@ namespace Api.Controllers public class AreaController : ControllerBase { private readonly IAreaService _areaService; + private readonly IDefaultLocalizationPoseService _defaultLocalizationPoseService; private readonly IMissionDefinitionService _missionDefinitionService; @@ -23,12 +24,14 @@ public AreaController( ILogger logger, IMapService mapService, IAreaService areaService, + IDefaultLocalizationPoseService defaultLocalizationPoseService, IMissionDefinitionService missionDefinitionService ) { _logger = logger; _mapService = mapService; _areaService = areaService; + _defaultLocalizationPoseService = defaultLocalizationPoseService; _missionDefinitionService = missionDefinitionService; } @@ -128,6 +131,54 @@ [FromBody] Pose safePosition } } + /// + /// Updates default localization pose + /// + /// + /// This query updates the default localization pose for a deck + /// + [HttpPut] + [Authorize(Roles = Role.Admin)] + [Route("{areaId}/update-default-localization-pose")] + [ProducesResponseType(typeof(Deck), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> UpdateDefaultLocalizationPose([FromRoute] string areaId, [FromBody] Pose newDefaultLocalizationPose) + { + _logger.LogInformation("Updating default localization pose on area '{areaId}'", areaId); + try + { + var area = await _areaService.ReadById(areaId); + if (area is null) + { + _logger.LogInformation("A area with id '{areaId}' does not exist", areaId); + return NotFound("Area does not exists"); + } + + if (area.DefaultLocalizationPose != null) + { + area.DefaultLocalizationPose.Pose = newDefaultLocalizationPose; + _ = await _defaultLocalizationPoseService.Update(area.DefaultLocalizationPose); + } + else + { + area.DefaultLocalizationPose = new DefaultLocalizationPose(newDefaultLocalizationPose); + area = await _areaService.Update(area); + } + + + return Ok(new AreaResponse(area)); + } + catch (Exception e) + { + _logger.LogError(e, "Error while updating the default localization pose"); + throw; + } + } + + /// /// Deletes the area with the specified id from the database. /// @@ -277,10 +328,17 @@ public async Task> GetMapMetadata([FromRoute] string i return StatusCode(StatusCodes.Status500InternalServerError, errorMessage); } + if (area.DefaultLocalizationPose is null) + { + string errorMessage = $"Area with id '{area.Id}' does not have a default localization pose"; + _logger.LogInformation("{ErrorMessage}", errorMessage); + return NotFound(errorMessage); + } + MapMetadata? mapMetadata; var positions = new List { - area.DefaultLocalizationPose.Position + area.DefaultLocalizationPose.Pose.Position }; try { diff --git a/backend/api/Controllers/Models/AreaResponse.cs b/backend/api/Controllers/Models/AreaResponse.cs index d5c1265f8..934bacd84 100644 --- a/backend/api/Controllers/Models/AreaResponse.cs +++ b/backend/api/Controllers/Models/AreaResponse.cs @@ -16,7 +16,7 @@ public class AreaResponse public MapMetadata MapMetadata { get; set; } - public Pose DefaultLocalizationPose { get; set; } + public DefaultLocalizationPose? DefaultLocalizationPose { get; set; } public IList SafePositions { get; set; } diff --git a/backend/api/Controllers/Models/CreateAreaQuery.cs b/backend/api/Controllers/Models/CreateAreaQuery.cs index a90ea30f8..9596753e1 100644 --- a/backend/api/Controllers/Models/CreateAreaQuery.cs +++ b/backend/api/Controllers/Models/CreateAreaQuery.cs @@ -9,6 +9,6 @@ public struct CreateAreaQuery public string DeckName { get; set; } public string AreaName { get; set; } - public Pose DefaultLocalizationPose { get; set; } + public Pose? DefaultLocalizationPose { get; set; } } } diff --git a/backend/api/Database/Context/FlotillaDbContext.cs b/backend/api/Database/Context/FlotillaDbContext.cs index fc5ac5122..648baa607 100644 --- a/backend/api/Database/Context/FlotillaDbContext.cs +++ b/backend/api/Database/Context/FlotillaDbContext.cs @@ -74,11 +74,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().OwnsOne(r => r.Pose).OwnsOne(p => p.Orientation); modelBuilder.Entity().OwnsOne(r => r.Pose).OwnsOne(p => p.Position); modelBuilder.Entity().OwnsMany(r => r.VideoStreams); - modelBuilder.Entity().OwnsOne(a => a.DefaultLocalizationPose, poseBuilder => - { - poseBuilder.OwnsOne(pose => pose.Position); - poseBuilder.OwnsOne(pose => pose.Orientation); - }); modelBuilder.Entity().HasOne(a => a.Deck).WithMany(); modelBuilder.Entity().HasOne(a => a.Installation).WithMany(); modelBuilder.Entity().HasOne(a => a.Plant).WithMany(); diff --git a/backend/api/Database/Context/InitDb.cs b/backend/api/Database/Context/InitDb.cs index 68d7bbc48..8a05e325c 100644 --- a/backend/api/Database/Context/InitDb.cs +++ b/backend/api/Database/Context/InitDb.cs @@ -112,7 +112,7 @@ private static List GetAreas() Installation = decks[0].Plant!.Installation, Name = "AP320", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; @@ -124,7 +124,7 @@ private static List GetAreas() Installation = decks[0].Plant!.Installation, Name = "AP330", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; @@ -136,7 +136,7 @@ private static List GetAreas() Installation = decks[0].Plant!.Installation, Name = "testArea", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; @@ -148,7 +148,7 @@ private static List GetAreas() Installation = decks[1].Plant.Installation, Name = "testArea2", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; @@ -160,7 +160,7 @@ private static List GetAreas() Installation = decks[2].Plant.Installation, Name = "testArea3", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; @@ -172,7 +172,7 @@ private static List GetAreas() Installation = decks[3].Plant.Installation, Name = "testArea4", MapMetadata = new MapMetadata(), - DefaultLocalizationPose = new Pose { }, + DefaultLocalizationPose = null, SafePositions = new List() }; diff --git a/backend/api/Database/Models/Area.cs b/backend/api/Database/Models/Area.cs index ae23f167c..2cb4f86f9 100644 --- a/backend/api/Database/Models/Area.cs +++ b/backend/api/Database/Models/Area.cs @@ -23,8 +23,8 @@ public class Area [Required] public MapMetadata MapMetadata { get; set; } - [Required] - public Pose DefaultLocalizationPose { get; set; } + + public DefaultLocalizationPose? DefaultLocalizationPose { get; set; } public IList SafePositions { get; set; } } diff --git a/backend/api/Services/AreaService.cs b/backend/api/Services/AreaService.cs index 3f2acaa80..98cd8bd37 100644 --- a/backend/api/Services/AreaService.cs +++ b/backend/api/Services/AreaService.cs @@ -44,14 +44,16 @@ public class AreaService : IAreaService private readonly IInstallationService _installationService; private readonly IPlantService _plantService; private readonly IDeckService _deckService; + private readonly IDefaultLocalizationPoseService _defaultLocalizationPoseService; public AreaService( - FlotillaDbContext context, IInstallationService installationService, IPlantService plantService, IDeckService deckService) + FlotillaDbContext context, IInstallationService installationService, IPlantService plantService, IDeckService deckService, IDefaultLocalizationPoseService defaultLocalizationPoseService) { _context = context; _installationService = installationService; _plantService = plantService; _deckService = deckService; + _defaultLocalizationPoseService = defaultLocalizationPoseService; } public async Task> ReadAll() @@ -62,7 +64,7 @@ public async Task> ReadAll() private IQueryable GetAreas() { return _context.Areas.Include(a => a.SafePositions) - .Include(a => a.Deck).Include(d => d.Plant).Include(i => i.Installation); + .Include(a => a.Deck).Include(d => d.Plant).Include(i => i.Installation).Include(d => d.DefaultLocalizationPose); } public async Task ReadById(string id) @@ -142,10 +144,16 @@ public async Task Create(CreateAreaQuery newAreaQuery, List position throw new AreaExistsException($"Area with name {newAreaQuery.AreaName} already exists"); } + DefaultLocalizationPose? defaultLocalizationPose = null; + if (newAreaQuery.DefaultLocalizationPose != null) + { + defaultLocalizationPose = await _defaultLocalizationPoseService.Create(new DefaultLocalizationPose(newAreaQuery.DefaultLocalizationPose)); + } + var newArea = new Area { Name = newAreaQuery.AreaName, - DefaultLocalizationPose = newAreaQuery.DefaultLocalizationPose, + DefaultLocalizationPose = defaultLocalizationPose, SafePositions = safePositions, MapMetadata = new MapMetadata(), Deck = deck!,