Simulation over network!

This commit is contained in:
moxitech 2024-10-05 00:36:05 +07:00
parent 198830a424
commit 46180110d4
5 changed files with 209 additions and 103 deletions

View File

@ -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")
} }

View File

@ -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 Расчет зон радиопокрытия

View 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))
}

View File

@ -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
} }

View 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
}