Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 103 additions & 13 deletions FITonyashkii/public/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class MapInterface {
this.gridSize = 50;
this.cellSize = 30;

// Route state
this.routeActive = false;
this.routeData = []; // массив точек маршрута {x, y}

this.setupCanvas();
this.setupEventListeners();
Expand Down Expand Up @@ -249,22 +251,25 @@ class MapInterface {
}
}

startRoute() {

// Модифицируйте метод startRoute
startRoute() {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
const message = {
type: "start_route",
};
const message = {
type: "start_route",
};

this.ws.send(JSON.stringify(message));
this.routeActive = true;
this.updateRouteButton();
this.showNotification("Маршрут начат!");
this.ws.send(JSON.stringify(message));
this.routeActive = true;
this.routeData = [];
this.updateRouteButton();
this.showNotification("Маршрут начат!");

console.log("Начало маршрута:", message);
console.log("Начало маршрута:", message);
} else {
this.showNotification("Нет подключения к серверу", true);
this.showNotification("Нет подключения к серверу", true);
}
}
}

finishRoute() {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
Expand Down Expand Up @@ -296,6 +301,56 @@ class MapInterface {
}
}

addRoutePoint(x, y) {
if (this.routeActive) {
this.routeData.push({ x, y });
}
}

drawRoute() {
if (!this.routeData || this.routeData.length < 2) return;

this.ctx.strokeStyle = "#a824c9";
this.ctx.lineWidth = 4 * this.scale;
this.ctx.lineJoin = "round";
this.ctx.lineCap = "round";
this.ctx.setLineDash([]);

this.ctx.beginPath();

const firstPoint = this.scalePos(this.routeData[0].x, this.routeData[0].y);
this.ctx.moveTo(firstPoint.x, firstPoint.y);

for (let i = 1; i < this.routeData.length; i++) {
const point = this.scalePos(this.routeData[i].x, this.routeData[i].y);
this.ctx.lineTo(point.x, point.y);
}

this.ctx.stroke();

if (this.routeData.length > 0) {
const startPoint = this.scalePos(this.routeData[0].x, this.routeData[0].y);
this.ctx.fillStyle = "#2ecc71";
this.ctx.beginPath();
this.ctx.arc(startPoint.x, startPoint.y, 5 * this.scale, 0, Math.PI * 2);
this.ctx.fill();

}

// Рисуем конечную точку другим цветом
if (this.routeData.length > 1) {
const endPoint = this.scalePos(
this.routeData[this.routeData.length - 1].x,
this.routeData[this.routeData.length - 1].y
);
this.ctx.fillStyle = "#e74c3c"; // красный для финиша
this.ctx.beginPath();
this.ctx.arc(endPoint.x, endPoint.y, 5 * this.scale, 0, Math.PI * 2);
this.ctx.fill();

}
}

toggleGrid() {
this.showGrid = !this.showGrid;
}
Expand Down Expand Up @@ -408,10 +463,26 @@ class MapInterface {
}
} else if (data.playerPosition && data.objects) {
// Full map data format
const prevX = this.playerPosition.x;
const prevY = this.playerPosition.y;

this.playerPosition = data.playerPosition;
this.objects = data.objects;
this.statusValues = data.statusValues || [];

// Автоматически добавляем точку в маршрут при движении
if (this.routeActive) {
const distance = Math.sqrt(
Math.pow(this.playerPosition.x - prevX, 2) +
Math.pow(this.playerPosition.y - prevY, 2)
);

// Добавляем точку только если перемещение значительное
if (distance > 0.1) {
this.addRoutePoint(this.playerPosition.x, this.playerPosition.y);
}
}

const messageLine = document.getElementById("messageLine");
if (data.messageLine) {
messageLine.textContent = data.messageLine;
Expand All @@ -420,7 +491,23 @@ class MapInterface {
}
} else if (data.x !== undefined && data.y !== undefined) {
// Simple position update
const prevX = this.playerPosition.x;
const prevY = this.playerPosition.y;

this.playerPosition = { x: data.x, y: data.y };

// Автоматически добавляем точку в маршрут при движении
if (this.routeActive) {
const distance = Math.sqrt(
Math.pow(this.playerPosition.x - prevX, 2) +
Math.pow(this.playerPosition.y - prevY, 2)
);

// Добавляем точку только если перемещение значительное
if (distance > 0.5) {
this.addRoutePoint(this.playerPosition.x, this.playerPosition.y);
}
}
} else if (data.type === "error") {
console.error("Ошибка сервера:", data.message);
this.showNotification("Ошибка: " + data.message, true);
Expand Down Expand Up @@ -517,6 +604,9 @@ class MapInterface {
this.drawGrid();
}

// Draw route (добавляем эту строку)
this.drawRoute();

// Draw objects
this.drawObjects();

Expand All @@ -528,7 +618,7 @@ class MapInterface {
scalePos(x, y) {
return {
x: x * this.cellSize * this.scale + this.offsetX,
y: y * this.cellSize * this.scale * -1 + this.offsetY,
y: -y * this.cellSize * this.scale + this.offsetY,
};
}

Expand Down Expand Up @@ -658,4 +748,4 @@ document.addEventListener("visibilitychange", function () {
) {
window.mapInterface.connect();
}
});
});
16 changes: 8 additions & 8 deletions FITonyashkii/server/beacons.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Name;X;Y
beacon_1;-7.2;-4.8
beacon_2;3;-4.8
beacon_3;9.6;-0.6
beacon_4;-13.8;-1.8
beacon_5;-9;4.2
beacon_6;6;9
beacon_7;-13.2;10.8
Name;X;Y
beacon_1;-7.2;-4.8
beacon_2;3;-4.8
beacon_3;9.6;-0.6
beacon_4;-13.8;-1.8
beacon_5;-9;4.2
beacon_6;6;9
beacon_7;-13.2;10.8
beacon_8;-3;2.4
1 change: 1 addition & 0 deletions FITonyashkii/server/config.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

MIN_DISTANCE_TO_UPDATE_ROUTE = 1.0 # meters
BROADCAST_FREQUENCY = 1.0
2 changes: 1 addition & 1 deletion FITonyashkii/server/rssi_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class KalmanFilterManager:
def __init__(self):
self.filters: Dict[str, Any] = {}
self.measurement_uncertainty = 100
self.measurement_uncertainty = 120

def initialize_kalman_filter(self):
# Initialize the Kalman Filter
Expand Down
4 changes: 2 additions & 2 deletions FITonyashkii/server/rssi_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,5 @@ def on_data(self, device_name: str, rssi: int, tx_power: int = -46):
position = self.solver.get_position(self.filtered_rssi)
# print(position)
if position:
self.x = 0.9 * self.x + 0.1*position[0]
self.y = 0.9 * self.y + 0.1*position[1]
self.x = 0.95 * self.x + 0.05 * position[0]
self.y = 0.95 * self.y + 0.05 * position[1]
9 changes: 6 additions & 3 deletions FITonyashkii/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def __init__(
async def websocket_handler(self, websocket):
self.connected_clients.add(websocket)
print(f"WebSocket client connected from {websocket.remote_address}")
await self.broadcast_state()
try:
async for message in websocket:
try:
Expand Down Expand Up @@ -192,6 +191,11 @@ async def broadcast_state(self):
await client.send(message)
except websockets.exceptions.ConnectionClosed:
self.connected_clients.discard(client)

async def broadcast_task(self):
while True:
await self.broadcast_state()
await asyncio.sleep(config.BROADCAST_FREQUENCY)

def update(self, udp_data):
current_time = int(datetime.now().timestamp())
Expand Down Expand Up @@ -221,8 +225,6 @@ def update(self, udp_data):
if distance >= config.MIN_DISTANCE_TO_UPDATE_ROUTE:
self.route_data.append((self.locator.x, self.locator.y))

asyncio.create_task(self.broadcast_state())

class UDPServerProtocol(asyncio.DatagramProtocol):
def __init__(self, server):
self.server = server
Expand Down Expand Up @@ -257,6 +259,7 @@ async def start(self):
print(f"Starting WebSocket server on ws://{self.ws_host}:{self.ws_port}")
await websockets.serve(self.websocket_handler, self.ws_host, self.ws_port)
asyncio.create_task(self.udp_server())
asyncio.create_task(self.broadcast_task())
await asyncio.Future() # Run forever


Expand Down
4 changes: 2 additions & 2 deletions FITonyashkii/server/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


class Solver:
def __init__(self, beacons: Iterable, tx: int = -65, n: float = 1.5):
def __init__(self, beacons: Iterable, tx: int = -65, n: float = 1.0):
self.beacons = {
beacon.name: (float(beacon.x), float(beacon.y)) for beacon in beacons
}
Expand All @@ -23,7 +23,7 @@ def get_position(self, rssies: Dict):
x, y = self.beacons[beacon_name]
distance = float(self.get_distance(beacon_rssi))
# Use inverse distance as weight (closer beacons have more influence)
weight = 1.0 / (distance + 0.1) # Add small value to avoid division by zero
weight = 1.0 / (distance + 0.05) # Add small value to avoid division by zero
weighted_x += x * weight
weighted_y += y * weight
total_weight += weight
Expand Down