Simulation over network!
This commit is contained in:
parent
198830a424
commit
46180110d4
@ -1,81 +1,90 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "moxitech/dns/internal/database"
|
"moxitech/dns/internal/database"
|
||||||
// "moxitech/dns/internal/server"
|
"moxitech/dns/internal/server"
|
||||||
"moxitech/dns/package/math/simulator"
|
|
||||||
|
// "fmt"
|
||||||
|
// "moxitech/dns/package/math/simulator"
|
||||||
|
// u_sorting "moxitech/dns/package/utils/sorting"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// var wg sync.WaitGroup = sync.WaitGroup{}
|
// var wg sync.WaitGroup = sync.WaitGroup{}
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Пример карты высот, замените на настоящие данные
|
|
||||||
heightData := [][]float64{
|
|
||||||
{0, 10, 15, 20},
|
|
||||||
{5, 15, 25, 30},
|
|
||||||
{10, 20, 35, 40},
|
|
||||||
{15, 25, 40, 50},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Определяем карту высот
|
|
||||||
mapObj := &simulator.Map{
|
|
||||||
Name: "Example Map",
|
|
||||||
MinBound: [3]float64{-1000, -1000, 0},
|
|
||||||
MaxBound: [3]float64{1000, 1000, 500},
|
|
||||||
HeightData: heightData,
|
|
||||||
}
|
|
||||||
// Определяем дронов
|
|
||||||
drones := []*simulator.Drone{
|
|
||||||
{
|
|
||||||
ID: 1,
|
|
||||||
Name: "Drone 1",
|
|
||||||
Coords: [3]float64{100, 100, 50},
|
|
||||||
Params: simulator.DroneParams{
|
|
||||||
AntennaRadius: 500,
|
|
||||||
AntennaDirection: [3]float64{1, 0, 0},
|
|
||||||
Waypoints: [][3]float64{{200, 200, 50}},
|
|
||||||
Speed: 10,
|
|
||||||
MeshName: "MeshA",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Определяем базовые станции
|
|
||||||
baseStations := []*simulator.BaseStation{
|
|
||||||
{
|
|
||||||
ID: 1,
|
|
||||||
Name: "BaseStation1",
|
|
||||||
Coords: [3]float64{0, 0, 0},
|
|
||||||
Params: simulator.BaseStationParams{
|
|
||||||
AntennaRadius: 2000,
|
|
||||||
AntennaDirection: [3]float64{1, 0, 0},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Создаем симуляцию
|
|
||||||
sim := &simulator.NetworkSimulation{
|
|
||||||
Map: mapObj,
|
|
||||||
Drones: drones,
|
|
||||||
BaseStations: baseStations,
|
|
||||||
TimeStep: 5,
|
|
||||||
}
|
|
||||||
// Запуск симуляции на 30 секунд
|
|
||||||
sim.Simulate(300)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// func main() {
|
// func main() {
|
||||||
// D_EXPORT_VARS()
|
// // Пример карты высот, замените на настоящие данные
|
||||||
// err := database.NewDBConnection()
|
// heightData := [][]float64{
|
||||||
// if err != nil {
|
// {0, 10, 15, 20},
|
||||||
// panic(err)
|
// {5, 15, 25, 30},
|
||||||
|
// {10, 20, 35, 40},
|
||||||
|
// {15, 25, 40, 50},
|
||||||
// }
|
// }
|
||||||
// err = server.SpawnServer()
|
|
||||||
// if err != nil {
|
// // Определяем карту высот
|
||||||
// panic(err)
|
// mapObj := &simulator.Map{
|
||||||
|
// Name: "Example Map",
|
||||||
|
// MinBound: [3]float64{-1000, -1000, 0},
|
||||||
|
// MaxBound: [3]float64{1000, 1000, 500},
|
||||||
|
// HeightData: heightData,
|
||||||
// }
|
// }
|
||||||
|
// // Определяем дронов
|
||||||
|
// drones := []*simulator.Drone{
|
||||||
|
// {
|
||||||
|
// ID: 1,
|
||||||
|
// Name: "Drone 1",
|
||||||
|
// Coords: [3]float64{100, 100, 50},
|
||||||
|
// Params: simulator.DroneParams{
|
||||||
|
// AntennaRadius: 500,
|
||||||
|
// AntennaDirection: [3]float64{1, 0, 0},
|
||||||
|
// Waypoints: [][3]float64{{200, 200, 50}},
|
||||||
|
// Speed: 10,
|
||||||
|
// MeshName: "MeshA",
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// // Определяем базовые станции
|
||||||
|
// baseStations := []*simulator.BaseStation{
|
||||||
|
// {
|
||||||
|
// ID: 1,
|
||||||
|
// Name: "BaseStation1",
|
||||||
|
// Coords: [3]float64{0, 0, 0},
|
||||||
|
// Params: simulator.BaseStationParams{
|
||||||
|
// AntennaRadius: 2000,
|
||||||
|
// AntennaDirection: [3]float64{1, 0, 0},
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// // Создаем симуляцию
|
||||||
|
// sim := &simulator.NetworkSimulation{
|
||||||
|
// Map: mapObj,
|
||||||
|
// Drones: drones,
|
||||||
|
// BaseStations: baseStations,
|
||||||
|
// TimeStep: 2,
|
||||||
|
// }
|
||||||
|
// // Запуск симуляции на 300 секунд
|
||||||
|
// result_sim := sim.Simulate(300)
|
||||||
|
// result := u_sorting.SortMap(result_sim)
|
||||||
|
// for time, state := range result {
|
||||||
|
// for localstate, f := range state {
|
||||||
|
// fmt.Printf("%v| %v sec :: %v\n", time, localstate, f)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
D_EXPORT_VARS()
|
||||||
|
err := database.NewDBConnection()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = server.SpawnServer()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func D_EXPORT_VARS() {
|
func D_EXPORT_VARS() {
|
||||||
os.Setenv("SERVER_BASE_ADDRESS", "0.0.0.0:8080")
|
os.Setenv("SERVER_BASE_ADDRESS", "0.0.0.0:8080")
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
model "moxitech/dns/entity/math"
|
model "moxitech/dns/entity/math"
|
||||||
loss "moxitech/dns/package/math"
|
loss "moxitech/dns/package/math/loss"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CalculateCoverage Расчет зон радиопокрытия
|
// CalculateCoverage Расчет зон радиопокрытия
|
||||||
|
8
src/server/package/math/distance/distance.go
Normal file
8
src/server/package/math/distance/distance.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package distance
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// euclideanDistance рассчитывает евклидово расстояние между двумя точками
|
||||||
|
func EuclideanDistance(p1, p2 [3]float64) float64 {
|
||||||
|
return math.Sqrt(math.Pow(p2[0]-p1[0], 2) + math.Pow(p2[1]-p1[1], 2) + math.Pow(p2[2]-p1[2], 2))
|
||||||
|
}
|
@ -2,6 +2,7 @@ package simulator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"moxitech/dns/package/math/distance"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,9 @@ type DroneParams struct {
|
|||||||
Waypoints [][3]float64
|
Waypoints [][3]float64
|
||||||
Speed float64
|
Speed float64
|
||||||
MeshName string
|
MeshName string
|
||||||
|
Modulation string // Тип модуляции (например, QPSK, QAM, OFDM)
|
||||||
|
Bandwidth float64 // Полоса частот в MHz
|
||||||
|
DataRate float64 // Скорость передачи данных в Mbps
|
||||||
}
|
}
|
||||||
|
|
||||||
type Drone struct {
|
type Drone struct {
|
||||||
@ -31,6 +35,9 @@ type Drone struct {
|
|||||||
type BaseStationParams struct {
|
type BaseStationParams struct {
|
||||||
AntennaRadius float64
|
AntennaRadius float64
|
||||||
AntennaDirection [3]float64
|
AntennaDirection [3]float64
|
||||||
|
Modulation string // Тип модуляции
|
||||||
|
Bandwidth float64 // Полоса частот
|
||||||
|
DataRate float64 // Скорость передачи данных
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseStation struct {
|
type BaseStation struct {
|
||||||
@ -47,12 +54,21 @@ type NetworkSimulation struct {
|
|||||||
TimeStep int
|
TimeStep int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate запускает симуляцию с параллельной обработкой дронов
|
// Simulate запускает симуляцию и возвращает состояние сети на каждую секунду
|
||||||
func (sim *NetworkSimulation) Simulate(totalTime int) {
|
func (sim *NetworkSimulation) Simulate(totalTime int) map[int]map[string][]interface{} {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
times := totalTime / sim.TimeStep
|
times := totalTime / sim.TimeStep
|
||||||
|
simulationData := make(map[int]map[string][]interface{})
|
||||||
|
|
||||||
for t := 0; t < times; t++ {
|
for t := 0; t < times; t++ {
|
||||||
|
currentTime := t * sim.TimeStep
|
||||||
|
|
||||||
|
// Создаем временное хранилище для дронов и базовых станций в данной секунде
|
||||||
|
secondState := map[string][]interface{}{
|
||||||
|
"drones": make([]interface{}, 0),
|
||||||
|
// "baseStations": make([]interface{}, 0),
|
||||||
|
}
|
||||||
|
|
||||||
wg.Add(len(sim.Drones))
|
wg.Add(len(sim.Drones))
|
||||||
|
|
||||||
// Параллельная обработка каждого дрона
|
// Параллельная обработка каждого дрона
|
||||||
@ -69,14 +85,40 @@ func (sim *NetworkSimulation) Simulate(totalTime int) {
|
|||||||
closestDrone := FindClosestDroneToBaseStation(d, sim.Drones, sim.BaseStations[0], sim.Map)
|
closestDrone := FindClosestDroneToBaseStation(d, sim.Drones, sim.BaseStations[0], sim.Map)
|
||||||
if closestDrone != nil {
|
if closestDrone != nil {
|
||||||
// Дрон может передавать данные через другой дрон
|
// Дрон может передавать данные через другой дрон
|
||||||
// Можно добавить логику для регистрации передачи данных
|
// Логику передачи можно добавить сюда
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Добавляем данные о дроне в текущее состояние
|
||||||
|
// Пример в симуляции, где обновляется информация о дроне
|
||||||
|
secondState["drones"] = append(secondState["drones"], map[string]interface{}{
|
||||||
|
"id": d.ID,
|
||||||
|
"name": d.Name,
|
||||||
|
"coords": d.CurrentCoords,
|
||||||
|
"speed": d.Params.Speed,
|
||||||
|
"dataRate": CalculateDataRate(d.Params.Modulation, d.Params.Bandwidth), // Добавляем расчет скорости передачи
|
||||||
|
})
|
||||||
|
|
||||||
}(drone)
|
}(drone)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait() // Ожидание завершения всех горутин
|
wg.Wait() // Ожидание завершения всех горутин
|
||||||
|
|
||||||
|
// Добавляем параметры базовых станций в текущее состояние
|
||||||
|
// TODO : для возможности динамической смены параметров базовой станции
|
||||||
|
// for _, baseStation := range sim.BaseStations {
|
||||||
|
// secondState["baseStations"] = append(secondState["baseStations"], map[string]interface{}{
|
||||||
|
// "id": baseStation.ID,
|
||||||
|
// "name": baseStation.Name,
|
||||||
|
// "coords": baseStation.Coords,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Сохраняем состояние для данной секунды
|
||||||
|
simulationData[currentTime] = secondState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return simulationData
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsInLOS проверяет, находится ли дрон в зоне прямой видимости с базовой станцией
|
// IsInLOS проверяет, находится ли дрон в зоне прямой видимости с базовой станцией
|
||||||
@ -84,25 +126,6 @@ func IsInLOS(drone *Drone, baseStation *BaseStation, mapObj *Map) bool {
|
|||||||
return CheckLineOfSight(drone.CurrentCoords, baseStation.Coords, mapObj)
|
return CheckLineOfSight(drone.CurrentCoords, baseStation.Coords, mapObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckLineOfSight проверяет прямую видимость между двумя точками с учетом рельефа карты
|
|
||||||
func CheckLineOfSight(from, to [3]float64, mapObj *Map) bool {
|
|
||||||
steps := 100 // Количество шагов для дискретизации
|
|
||||||
dx := (to[0] - from[0]) / float64(steps)
|
|
||||||
dy := (to[1] - from[1]) / float64(steps)
|
|
||||||
dz := (to[2] - from[2]) / float64(steps)
|
|
||||||
|
|
||||||
for i := 0; i <= steps; i++ {
|
|
||||||
x := from[0] + float64(i)*dx
|
|
||||||
y := from[1] + float64(i)*dy
|
|
||||||
z := from[2] + float64(i)*dz
|
|
||||||
|
|
||||||
if z <= GetHeightAt(mapObj, x, y) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetHeightAt возвращает высоту рельефа на карте для данной координаты
|
// GetHeightAt возвращает высоту рельефа на карте для данной координаты
|
||||||
func GetHeightAt(mapObj *Map, x, y float64) float64 {
|
func GetHeightAt(mapObj *Map, x, y float64) float64 {
|
||||||
// Предположим, что высота карты представлена как двумерный массив
|
// Предположим, что высота карты представлена как двумерный массив
|
||||||
@ -122,7 +145,7 @@ func GetHeightAt(mapObj *Map, x, y float64) float64 {
|
|||||||
// IsDroneInNetwork проверяет, может ли дрон подключиться к базовой станции
|
// IsDroneInNetwork проверяет, может ли дрон подключиться к базовой станции
|
||||||
func IsDroneInNetwork(drone *Drone, baseStations []*BaseStation, mapObj *Map) bool {
|
func IsDroneInNetwork(drone *Drone, baseStations []*BaseStation, mapObj *Map) bool {
|
||||||
for _, base := range baseStations {
|
for _, base := range baseStations {
|
||||||
if IsInLOS(drone, base, mapObj) && euclideanDistance(drone.CurrentCoords, base.Coords) <= base.Params.AntennaRadius {
|
if IsInLOS(drone, base, mapObj) && distance.EuclideanDistance(drone.CurrentCoords, base.Coords) <= base.Params.AntennaRadius {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,24 +154,50 @@ func IsDroneInNetwork(drone *Drone, baseStations []*BaseStation, mapObj *Map) bo
|
|||||||
|
|
||||||
// Move перемещает дрон по точкам следования
|
// Move перемещает дрон по точкам следования
|
||||||
func (d *Drone) Move(timeStep int) {
|
func (d *Drone) Move(timeStep int) {
|
||||||
if len(d.Params.Waypoints) > 0 {
|
if len(d.Params.Waypoints) == 0 {
|
||||||
target := d.Params.Waypoints[0]
|
return // Если нет путевых точек, дрон останавливается
|
||||||
direction := [3]float64{
|
}
|
||||||
target[0] - d.CurrentCoords[0],
|
|
||||||
target[1] - d.CurrentCoords[1],
|
|
||||||
target[2] - d.CurrentCoords[2],
|
|
||||||
}
|
|
||||||
|
|
||||||
distance := math.Sqrt(direction[0]*direction[0] + direction[1]*direction[1] + direction[2]*direction[2])
|
target := d.Params.Waypoints[0]
|
||||||
moveDistance := d.Params.Speed * float64(timeStep)
|
direction := [3]float64{
|
||||||
|
target[0] - d.CurrentCoords[0],
|
||||||
|
target[1] - d.CurrentCoords[1],
|
||||||
|
target[2] - d.CurrentCoords[2],
|
||||||
|
}
|
||||||
|
|
||||||
// Обновляем координаты
|
distance := math.Sqrt(direction[0]*direction[0] + direction[1]*direction[1] + direction[2]*direction[2])
|
||||||
|
moveDistance := d.Params.Speed * float64(timeStep)
|
||||||
|
|
||||||
|
if moveDistance >= distance {
|
||||||
|
d.CurrentCoords = target
|
||||||
|
d.Params.Waypoints = d.Params.Waypoints[1:] // Удаляем достигнутую точку
|
||||||
|
} else {
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
d.CurrentCoords[i] += direction[i] / distance * moveDistance
|
d.CurrentCoords[i] += direction[i] / distance * moveDistance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckLineOfSight проверяет прямую видимость между двумя точками с учетом рельеф
|
||||||
|
func CheckLineOfSight(from, to [3]float64, mapObj *Map) bool {
|
||||||
|
distance := distance.EuclideanDistance(from, to)
|
||||||
|
steps := int(distance * 10) // Используем шаги, пропорциональные длине пути
|
||||||
|
dx := (to[0] - from[0]) / float64(steps)
|
||||||
|
dy := (to[1] - from[1]) / float64(steps)
|
||||||
|
dz := (to[2] - from[2]) / float64(steps)
|
||||||
|
|
||||||
|
for i := 0; i <= steps; i++ {
|
||||||
|
x := from[0] + float64(i)*dx
|
||||||
|
y := from[1] + float64(i)*dy
|
||||||
|
z := from[2] + float64(i)*dz
|
||||||
|
|
||||||
|
if z <= GetHeightAt(mapObj, x, y) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// FindClosestDroneToBaseStation находит ближайший дрон к базовой станции в mesh-сети
|
// FindClosestDroneToBaseStation находит ближайший дрон к базовой станции в mesh-сети
|
||||||
func FindClosestDroneToBaseStation(drone *Drone, allDrones []*Drone, baseStation *BaseStation, mapObj *Map) *Drone {
|
func FindClosestDroneToBaseStation(drone *Drone, allDrones []*Drone, baseStation *BaseStation, mapObj *Map) *Drone {
|
||||||
var closestDrone *Drone
|
var closestDrone *Drone
|
||||||
@ -160,7 +209,7 @@ func FindClosestDroneToBaseStation(drone *Drone, allDrones []*Drone, baseStation
|
|||||||
}
|
}
|
||||||
|
|
||||||
if IsInLOS(otherDrone, baseStation, mapObj) {
|
if IsInLOS(otherDrone, baseStation, mapObj) {
|
||||||
distance := euclideanDistance(otherDrone.CurrentCoords, baseStation.Coords)
|
distance := distance.EuclideanDistance(otherDrone.CurrentCoords, baseStation.Coords)
|
||||||
if distance < minDistance {
|
if distance < minDistance {
|
||||||
minDistance = distance
|
minDistance = distance
|
||||||
closestDrone = otherDrone
|
closestDrone = otherDrone
|
||||||
@ -171,7 +220,24 @@ func FindClosestDroneToBaseStation(drone *Drone, allDrones []*Drone, baseStation
|
|||||||
return closestDrone
|
return closestDrone
|
||||||
}
|
}
|
||||||
|
|
||||||
// euclideanDistance рассчитывает евклидово расстояние между двумя точками
|
// CalculateDataRate рассчитывает скорость передачи данных на основе типа модуляции и полосы частот
|
||||||
func euclideanDistance(p1, p2 [3]float64) float64 {
|
func CalculateDataRate(modulation string, bandwidth float64) float64 {
|
||||||
return math.Sqrt(math.Pow(p2[0]-p1[0], 2) + math.Pow(p2[1]-p1[1], 2) + math.Pow(p2[2]-p1[2], 2))
|
var spectralEfficiency float64
|
||||||
|
|
||||||
|
switch modulation {
|
||||||
|
case "QPSK":
|
||||||
|
spectralEfficiency = 2.0 // биты/Гц
|
||||||
|
case "16QAM":
|
||||||
|
spectralEfficiency = 4.0
|
||||||
|
case "64QAM":
|
||||||
|
spectralEfficiency = 6.0
|
||||||
|
case "256QAM":
|
||||||
|
spectralEfficiency = 8.0
|
||||||
|
case "OFDM":
|
||||||
|
spectralEfficiency = 10.0
|
||||||
|
default:
|
||||||
|
spectralEfficiency = 1.0 // базовый случай
|
||||||
|
}
|
||||||
|
|
||||||
|
return spectralEfficiency * bandwidth // скорость передачи данных в Mbps
|
||||||
}
|
}
|
||||||
|
23
src/server/package/utils/sorting/sorting.go
Normal file
23
src/server/package/utils/sorting/sorting.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package u_sorting
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
// Функция сортировки карты по ключам int
|
||||||
|
func SortMap(m map[int]map[string][]interface{}) []map[int]map[string][]interface{} {
|
||||||
|
// Извлечь ключи карты
|
||||||
|
keys := make([]int, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отсортировать ключи
|
||||||
|
sort.Ints(keys)
|
||||||
|
|
||||||
|
// Подготовить результат с отсортированными ключами
|
||||||
|
sorted := make([]map[int]map[string][]interface{}, 0, len(m))
|
||||||
|
for _, k := range keys {
|
||||||
|
sorted = append(sorted, map[int]map[string][]interface{}{k: m[k]})
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user