Skip to content

Commit

Permalink
All external mission loading put inside mission loader
Browse files Browse the repository at this point in the history
  • Loading branch information
Christdej committed Aug 29, 2024
1 parent 9fe5ab6 commit 9d460f3
Show file tree
Hide file tree
Showing 63 changed files with 2,221 additions and 1,071 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ backend/*/obj
backend/api/Database/Maps/*
backend/backend.sln.DotSettings.user

#Broker
# Broker
broker/mosquitto/config/certs/server-key.pem
*.DS_Store

# Local missions
missions/
14 changes: 9 additions & 5 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ To set up the backend on **Windows/Mac**, install visual studio and include the
If you already have visual studio installed, you can open the "Visual Studio Installer" and modify your install to add the workload.

To set up the backend on **Linux**, install .NET for linux
[here](https://docs.microsoft.com/en-us/dotnet/core/install/linux).
You need to also install the dev certificate for local .NET development on linux.
[here](https://docs.microsoft.com/en-us/dotnet/core/install/linux).
You need to also install the dev certificate for local .NET development on linux.
Follow
[this guide](https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-7.0&tabs=visual-studio%2Clinux-ubuntu#trust-https-certificate-on-linux),
for each of the browser(s) you wish to trust it in.
for each of the browser(s) you wish to trust it in.
**NB:** You probably need to run the commands with `sudo` prefixed to have permission to change them.

For the configuration to be able to read secrets from the keyvault, you will need to have the client secret stored locally in your secret manager.
Expand Down Expand Up @@ -267,7 +267,7 @@ events and not receiving them, and all transmissions are sent using the SignalRS
doing so it is important to make sure that the event name provided corresponds with the name expected
in the frontend.

It is also crucial that we do not await sending signalR messages in our code. Instead we ignore the
It is also crucial that we do not await sending signalR messages in our code. Instead we ignore the
await warning. In the current version of the SignalR library, sending a message in an
asynchronous thread may cause the thread to silently exit without returning an exception, which is
avoided by letting the SignalR code run asynchronously after the current thread has executed.
Expand All @@ -280,6 +280,10 @@ to monitor the backend of our application.
We have one application insight instance for each environment.
The connection strings for the AI instances are stored in the keyvault.

## Custom Mission Loaders

You can create your own mission loader to fetch missions from some external system. The custom mission loader needs to fulfill the [IMissionLoader](api/Services/MissionLoaders/MissionLoaderInterface.cs) interface. If you mission loader is an external API you might need to add it as a downstreamapi in [Program.cs](api/Program.cs)

## Authorization

We use role based access control (RBAC) for authorization.
Expand All @@ -292,7 +296,7 @@ The access matrix looks like this:
| Deck | Read | Read | CRUD |
| Plant | Read | Read | CRUD |
| Installation | Read | Read | CRUD |
| Echo | Read | Read | CRUD |
| MissionLoader | Read | Read | CRUD |
| Missions | Read | Read | CRUD |
| Robots | Read | Read | CRUD |
| Robot Models | Read | Read | CRUD |
Expand Down
2 changes: 1 addition & 1 deletion backend/api.test/Client/AreaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public async Task MissionIsCreatedInArea()

// Assert
Assert.True(areaMissionsResponse.IsSuccessStatusCode);
var missions = await areaMissionsResponse.Content.ReadFromJsonAsync<IList<CondensedMissionDefinitionResponse>>(_serializerOptions);
var missions = await areaMissionsResponse.Content.ReadFromJsonAsync<IList<MissionDefinitionResponse>>(_serializerOptions);
Assert.NotNull(missions);
Assert.Single(missions.Where(m => m.Id.Equals(mission.MissionId, StringComparison.Ordinal)));
}
Expand Down
51 changes: 25 additions & 26 deletions backend/api.test/Client/MissionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private async Task<Installation> PostInstallationInformationToDb(string installa
}

[Fact]
public async Task ScheduleOneEchoMissionTest()
public async Task ScheduleOneMissionTest()
{
// Arrange - Robot
string robotUrl = "/robots";
Expand All @@ -274,21 +274,21 @@ public async Task ScheduleOneEchoMissionTest()
string robotId = robot.Id;

// Arrange - Area
string installationCode = "installationScheduleOneEchoMissionTest";
string plantCode = "plantScheduleOneEchoMissionTest";
string deckName = "deckScheduleOneEchoMissionTest";
string areaName = "areaScheduleOneEchoMissionTest";
string installationCode = "installationScheduleOneMissionTest";
string plantCode = "plantScheduleOneMissionTest";
string deckName = "deckScheduleOneMissionTest";
string areaName = "areaScheduleOneMissionTest";
(_, _, _, _) = await PostAssetInformationToDb(installationCode, plantCode, deckName, areaName);

int echoMissionId = 95;
string missionId = "95";

// Act
var query = new ScheduledMissionQuery
{
RobotId = robotId,
InstallationCode = installationCode,
AreaName = areaName,
EchoMissionId = echoMissionId,
MissionId = missionId,
DesiredStartTime = DateTime.UtcNow
};
var content = new StringContent(
Expand All @@ -308,7 +308,7 @@ public async Task ScheduleOneEchoMissionTest()
}

[Fact]
public async Task Schedule3EchoMissionsTest()
public async Task Schedule3MissionsTest()
{
// Arrange - Robot
string robotUrl = "/robots";
Expand All @@ -321,21 +321,21 @@ public async Task Schedule3EchoMissionsTest()
string robotId = robot.Id;

// Arrange - Area
string installationCode = "installationSchedule3EchoMissionsTest";
string plantCode = "plantSchedule3EchoMissionsTest";
string deckName = "deckSchedule3EchoMissionsTest";
string areaName = "areaSchedule3EchoMissionsTest";
string installationCode = "installationSchedule3MissionsTest";
string plantCode = "plantSchedule3MissionsTest";
string deckName = "deckSchedule3MissionsTest";
string areaName = "areaSchedule3MissionsTest";
(_, _, _, _) = await PostAssetInformationToDb(installationCode, plantCode, deckName, areaName);

int echoMissionId = 97;
string missionId = "97";

// Act
var query = new ScheduledMissionQuery
{
RobotId = robotId,
InstallationCode = installationCode,
AreaName = areaName,
EchoMissionId = echoMissionId,
MissionId = missionId,
DesiredStartTime = DateTime.UtcNow
};
var content = new StringContent(
Expand Down Expand Up @@ -645,31 +645,31 @@ public async Task GetNextRun()
}

[Fact]
public async Task ScheduleDuplicateEchoMissionDefinitions()
public async Task ScheduleDuplicatMissionDefinitions()
{
// Arrange - Initialise areas
string installationCode = "installationScheduleDuplicateEchoMissionDefinitions";
string plantCode = "plantScheduleDuplicateEchoMissionDefinitions";
string deckName = "deckScheduleDuplicateEchoMissionDefinitions";
string areaName = "areaScheduleDuplicateEchoMissionDefinitions";
string installationCode = "installationScheduleDuplicatMissionDefinitions";
string plantCode = "plantScheduleDuplicatMissionDefinitions";
string deckName = "deckScheduleDuplicatMissionDefinitions";
string areaName = "areaScheduleDuplicatMissionDefinitions";
(_, _, _, _) = await PostAssetInformationToDb(installationCode, plantCode, deckName, areaName);

// Arrange - Create echo mission definition
// Arrange - Create mission definition
string robotUrl = "/robots";
var response = await _client.GetAsync(robotUrl);
Assert.True(response.IsSuccessStatusCode);
var robots = await response.Content.ReadFromJsonAsync<List<Robot>>(_serializerOptions);
Assert.NotNull(robots);
var robot = robots.Where(robot => robot.Name == "Shockwave").First();
string robotId = robot.Id;
int echoMissionId = 1; // Corresponds to mock in EchoServiceMock.cs
string missionId = "986"; // Corresponds to mock in ServiceMock.cs

var query = new ScheduledMissionQuery
{
RobotId = robotId,
InstallationCode = installationCode,
AreaName = areaName,
EchoMissionId = echoMissionId,
MissionId = missionId,
DesiredStartTime = DateTime.UtcNow
};
var content = new StringContent(
Expand All @@ -679,9 +679,9 @@ public async Task ScheduleDuplicateEchoMissionDefinitions()
);

// Act
string echoMissionsUrl = "/missions";
var response1 = await _client.PostAsync(echoMissionsUrl, content);
var response2 = await _client.PostAsync(echoMissionsUrl, content);
string missionsUrl = "/missions";
var response1 = await _client.PostAsync(missionsUrl, content);
var response2 = await _client.PostAsync(missionsUrl, content);

// Assert
Assert.True(response1.IsSuccessStatusCode);
Expand All @@ -693,7 +693,6 @@ public async Task ScheduleDuplicateEchoMissionDefinitions()
string? missionId1 = missionRun1.MissionId;
string? missionId2 = missionRun2.MissionId;
Assert.Equal(missionId1, missionId2);

string missionDefinitionsUrl = "/missions/definitions?pageSize=50";
var missionDefinitionsResponse = await _client.GetAsync(missionDefinitionsUrl);
var missionDefinitions = await missionDefinitionsResponse.Content.ReadFromJsonAsync<List<MissionDefinition>>(_serializerOptions);
Expand Down
59 changes: 1 addition & 58 deletions backend/api.test/Database/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Api.Services.Models;
using Xunit;

namespace Api.Test.Services
namespace Api.Test.Database
{
public class TestPose
{
Expand Down Expand Up @@ -71,62 +71,5 @@ public void TestNegativaRotation()
3.0
);
}

[Fact]
public void AssertCoordinateConversion()
{
var pose = new Pose(
new Position(25.041F, 23.682F, 0),
new Orientation(0, 0, 0.8907533F, 0.4544871F)
);
var predefinedPosition = pose.Position;
var predefinedOrientation = pose.Orientation;
var echoPose = ConvertPredefinedPoseToEchoPose(
predefinedPosition,
predefinedOrientation
);

var flotillaPose = new Pose(echoPose.Position, echoPose.Orientation.Angle);
Assert.Equal(predefinedOrientation, flotillaPose.Orientation);
}

private static EchoPose ConvertPredefinedPoseToEchoPose(
Position position,
Orientation orientation
)
{
var enuPosition = new EnuPosition(position.X, position.Y, position.Z);
var axisAngle = ConvertOrientation(orientation);
return new EchoPose(enuPosition, axisAngle);
}

private static AxisAngle ConvertOrientation(Orientation orientation)
// This is the method used to convert predefined poses to the Angle-Axis representation used by Echo
{
float qw = orientation.W;
float angle = -2 * MathF.Acos(qw);
if (orientation.Z >= 0)
angle = 2 * MathF.Acos(qw);

angle = (450 * MathF.PI / 180) - angle;

angle %= 2F * MathF.PI;

if (angle < 0) angle += 2F * MathF.PI;

return new AxisAngle(new EnuPosition(0, 0, 1), angle);
}

public class AxisAngle(EnuPosition axis, float angle)
{
public EnuPosition Axis = axis;
public float Angle = angle;
}

public class EchoPose(EnuPosition position, AxisAngle orientation)
{
public EnuPosition Position = position;
public AxisAngle Orientation = orientation;
}
}
}
5 changes: 2 additions & 3 deletions backend/api.test/EventHandlers/TestMissionEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ public TestMissionEventHandler(DatabaseFixture fixture)
_missionRunService = new MissionRunService(context, signalRService, missionLogger, accessRoleService, userInfoService);


var echoServiceMock = new MockEchoService();
var missionLoader = new MockMissionLoader();
var stidServiceMock = new MockStidService(context);
var sourceService = new SourceService(context, echoServiceMock, sourceServiceLogger);
var missionDefinitionService = new MissionDefinitionService(context, echoServiceMock, sourceService, signalRService, accessRoleService, missionDefinitionServiceLogger, _missionRunService);
var missionDefinitionService = new MissionDefinitionService(context, missionLoader, signalRService, accessRoleService, missionDefinitionServiceLogger, _missionRunService);
var robotModelService = new RobotModelService(context);
var taskDurationServiceMock = new MockTaskDurationService();
var isarServiceMock = new MockIsarService();
Expand Down
73 changes: 0 additions & 73 deletions backend/api.test/Mocks/EchoServiceMock.cs

This file was deleted.

Loading

0 comments on commit 9d460f3

Please sign in to comment.