diff --git a/CHANGELOG.md b/CHANGELOG.md index f0fb5165..13634bfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- PerformOrbit API added +- PerformRacetrack API added - Added `ActivateGroup` API which allows to activate groups with late activation. - Added `DestroyGroup` API which removes the entire group from the game world. - `DestroyUnit` API - -### Fixed - Fixed `MarkAddEvent`, `MarkChangeEvent` and `MarkRemoveEvent` position - Fixed crash of concurrent Windows TTS synthesis ([#223](https://github.com/DCS-gRPC/rust-server/issues/223)) diff --git a/STATUS.md b/STATUS.md index 2596151b..a455850f 100644 --- a/STATUS.md +++ b/STATUS.md @@ -478,7 +478,7 @@ Primarily enhanced with `GRPC.exporters.unit` - [ ] `CarpetBombing` - [ ] `AttackMapObject` - [ ] `BombingRunway` - - [ ] `orbit` + - [x] `orbit` (Orbit and Racetrack APIs separated) - [ ] `refueling` - [ ] `land` - [ ] `follow` diff --git a/lua/DCS-gRPC/methods/controllers.lua b/lua/DCS-gRPC/methods/controllers.lua index d2f4c731..e4f22800 100644 --- a/lua/DCS-gRPC/methods/controllers.lua +++ b/lua/DCS-gRPC/methods/controllers.lua @@ -91,4 +91,98 @@ GRPC.methods.getDetectedTargets = function(params) return GRPC.success({ contacts = results }) -end \ No newline at end of file +end + +GRPC.methods.performOrbitTask = function(params) + + local obj + if params.name.groupName then + obj = Group.getByName(params.name.groupName) + elseif params.name.unitName then + obj = Unit.getByName(params.name.unitName) + else + return GRPC.errorInvalidArgument("No Group or Unit name provided") + end + + if obj == nil then + return GRPC.errorNotFound("Could not find group or unit with provided name") + end + + local controller = obj:getController() + + local point = coord.LLtoLO(params.orbitPoint.lat, params.orbitPoint.lon, params.orbitPoint.alt) + point = {x = point.x, y = point.z} -- Convert to Vec2 + + local orbit = { + id = 'Orbit', + params = { + pattern = 'Circle', + point = point, + } + } + + if params.speed then + orbit.params.speed = params.speed + end + + if params.altitude then + orbit.params.altitude = params.altitude + end + + if params.priority = 0 then + controller:setTask(orbit) + else + controller:pushTask(orbit) + end + + return GRPC.success({}) +end + +GRPC.methods.performRacetrackTask = function(params) + + local obj + if params.name.groupName then + obj = Group.getByName(params.name.groupName) + elseif params.name.unitName then + obj = Unit.getByName(params.name.unitName) + else + return GRPC.errorInvalidArgument("No Group or Unit name provided") + end + + if obj == nil then + return GRPC.errorNotFound("Could not find group or unit with provided name") + end + + local controller = obj:getController() + + local startPoint = coord.LLtoLO(params.startPoint.lat, params.startPoint.lon, params.startPoint.alt) + startPoint = {x = startPoint.x, y = startPoint.z} -- Convert to Vec2 + + local endPoint = coord.LLtoLO(params.endPoint.lat, params.endPoint.lon, params.endPoint.alt) + endPoint = {x = endPoint.x, y = endPoint.z} -- Convert to Vec2 + + local racetrack = { + id = 'Orbit', + params = { + pattern = 'Race-Track', + point = startPoint, + point2 = endPoint, + } + } + + if params.speed then + racetrack.params.speed = params.speed + end + + if params.altitude then + racetrack.params.altitude = params.altitude + end + + if params.priority = 0 then + controller:setTask(racetrack) + else + controller:pushTask(racetrack) + end + + return GRPC.success({}) +end diff --git a/protos/dcs/controller/v0/controller.proto b/protos/dcs/controller/v0/controller.proto index 89ec86a9..09082944 100644 --- a/protos/dcs/controller/v0/controller.proto +++ b/protos/dcs/controller/v0/controller.proto @@ -11,6 +11,16 @@ service ControllerService { // https://wiki.hoggitworld.com/view/DCS_func_getDetectedTargets rpc GetDetectedTargets(GetDetectedTargetsRequest) returns (GetDetectedTargetsResponse) {} + + // We split this into two separate calls to aid in clarity + // https://wiki.hoggitworld.com/view/DCS_task_orbit + rpc PerformOrbitTask(PerformOrbitTaskRequest) + returns (PerformOrbitTaskResponse) {} + + // We split this into two separate calls to aid in clarity + // https://wiki.hoggitworld.com/view/DCS_task_orbit + rpc PerformRacetrackTask(PerformRacetrackTaskRequest) + returns (PerformRacetrackTaskResponse) {} } message SetAlarmStateRequest { @@ -48,4 +58,40 @@ message GetDetectedTargetsRequest { message GetDetectedTargetsResponse { repeated dcs.common.v0.Contact contacts = 1; +} + +enum TaskingPriority { + TASKING_PRIORITY_IMMEDIATE = 0; + TASKING_PRIORITY_QUEUE = 1; +} + +message PerformOrbitTaskRequest { + oneof name { + string group_name = 1; + string unit_name = 2; + } + // The alt field in the Input position is ignored as an optional value is used elsewhere + dcs.common.v0.InputPosition orbit_point = 3; + TaskingPriority priority = 4; + optional int32 speed = 5; + optional int32 altitude = 6; +} + +message PerformOrbitTaskResponse { +} + +message PerformRacetrackTaskRequest { + oneof name { + string group_name = 1; + string unit_name = 2; + } + // The alt field in the Input position is ignored as an optional value is used elsewhere + dcs.common.v0.InputPosition start_point = 3; + dcs.common.v0.InputPosition end_point = 4; + TaskingPriority priority = 5; + optional int32 speed = 6; + optional int32 altitude = 7; +} + +message PerformRacetrackTaskResponse { } \ No newline at end of file diff --git a/src/rpc/controller.rs b/src/rpc/controller.rs index a08e713d..365d1da4 100644 --- a/src/rpc/controller.rs +++ b/src/rpc/controller.rs @@ -20,4 +20,18 @@ impl ControllerService for MissionRpc { let res = self.request("getDetectedTargets", request).await?; Ok(Response::new(res)) } + async fn perform_orbit_task( + &self, + request: Request, + ) -> Result, Status> { + let res = self.request("performOrbitTask", request).await?; + Ok(Response::new(res)) + } + async fn perform_racetrack_task( + &self, + request: Request, + ) -> Result, Status> { + let res = self.request("performRacetrackTask", request).await?; + Ok(Response::new(res)) + } }