{
  "id": "bLIV5Ixt5nveGZHb",
  "name": "Autonomous UAVmission control with multi-agent AI and dynamics integration",
  "tags": [],
  "nodes": [
    {
      "id": "fbf746f7-ac32-4cf3-91b1-2a41896cd5a0",
      "name": "Start ROV Mission",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        240,
        448
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "5b2f8e5b-9447-4ca6-9d7e-afad97316250",
      "name": "Initialize Mission & Agents",
      "type": "n8n-nodes-base.code",
      "position": [
        464,
        448
      ],
      "parameters": {
        "jsCode": "// ROV Control Architecture Initialization\n// 20 Hz control loop (\u0394t = 0.05 s)\n\nconst DT = 0.05;  // Time step (s)\nconst T_END = 10.0;  // Mission end time (s) - adjust as needed\nconst CONTROL_FREQ = 20;  // Hz\n\n// Mission waypoints [x, y, z, dwell_time]\nconst waypoints = [\n  [0, 0, -5, 2.0],\n  [10, 0, -5, 1.0],\n  [10, 10, -10, 1.5],\n  [0, 10, -10, 1.0],\n  [0, 0, -5, 0.0]\n];\n\n// ROV initial state [x, y, z, roll, pitch, yaw, vx, vy, vz, wx, wy, wz]\nconst state = {\n  position: [0, 0, 0],  // [x, y, z]\n  attitude: [0, 0, 0],  // [roll, pitch, yaw]\n  velocity: [0, 0, 0],  // [vx, vy, vz]\n  angular_velocity: [0, 0, 0]  // [wx, wy, wz]\n};\n\n// Mission Planning Agent state\nconst missionAgent = {\n  currentWaypointIndex: 0,\n  dwellStartTime: null,\n  isDwelling: false,\n  waypointsReached: 0\n};\n\n// Sonar Agent parameters (16-beam multibeam)\nconst sonarAgent = {\n  numBeams: 16,\n  maxRange: 20.0,  // meters\n  fov: 120,  // degrees\n  detections: []\n};\n\n// Navigation Agent parameters (PD controller + APF)\nconst navAgent = {\n  kp_pos: 2.0,  // Position proportional gain\n  kd_pos: 1.5,  // Position derivative gain\n  kp_yaw: 1.0,  // Yaw proportional gain\n  kd_yaw: 0.5,  // Yaw derivative gain\n  apf_gain: 5.0,  // Artificial potential field gain\n  apf_range: 3.0,  // APF activation range (m)\n  thrust: [0, 0, 0, 0]  // [Fx, Fy, Fz, Mz]\n};\n\n// Fault Monitoring Agent thresholds\nconst faultAgent = {\n  thrusterDegradationThreshold: 0.7,  // 70% efficiency\n  overspeedThreshold: 2.0,  // m/s\n  saturationThreshold: 0.95,  // 95% of max thrust\n  faultDetected: false,\n  faultType: null,\n  safeModeActive: false,\n  thrusterEfficiency: [1.0, 1.0, 1.0, 1.0]  // Per-thruster efficiency\n};\n\n// Communication Agent parameters\nconst commAgent = {\n  packetLossRate: 0.05,  // 5%\n  latencyMin: 0.1,  // seconds\n  latencyMax: 0.5,  // seconds\n  packetsTransmitted: 0,\n  packetsLost: 0,\n  telemetryLog: []\n};\n\n// Hydrodynamic parameters\nconst hydro = {\n  mass: 50.0,  // kg\n  drag_linear: [10, 10, 15],  // Linear drag coefficients [x, y, z]\n  drag_quadratic: [20, 20, 30],  // Quadratic drag coefficients\n  inertia_z: 5.0  // Yaw moment of inertia\n};\n\n// Mission state\nconst mission = {\n  time: 0.0,\n  iteration: 0,\n  trajectoryLog: [],\n  telemetryLog: []\n};\n\nreturn [{\n  json: {\n    DT,\n    T_END,\n    CONTROL_FREQ,\n    waypoints,\n    state,\n    missionAgent,\n    sonarAgent,\n    navAgent,\n    faultAgent,\n    commAgent,\n    hydro,\n    mission\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "70218b70-8e55-40b2-94c1-6d7996e590e0",
      "name": "Performance Analysis",
      "type": "n8n-nodes-base.code",
      "position": [
        3152,
        208
      ],
      "parameters": {
        "jsCode": "// Post-mission performance analysis\nconst data = $input.first().json;\n\nconst trajectoryLog = data.mission.trajectoryLog;\nconst telemetryLog = data.commAgent.telemetryLog;\nconst waypoints = data.waypoints;\n\n// Calculate total distance traveled\nlet totalDistance = 0;\nfor (let i = 1; i < trajectoryLog.length; i++) {\n  const p1 = trajectoryLog[i - 1].position;\n  const p2 = trajectoryLog[i].position;\n  const dx = p2[0] - p1[0];\n  const dy = p2[1] - p1[1];\n  const dz = p2[2] - p1[2];\n  totalDistance += Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\n// Calculate average speed\nconst avgSpeed = trajectoryLog.reduce((sum, entry) => {\n  const v = entry.velocity;\n  return sum + Math.sqrt(v[0] ** 2 + v[1] ** 2 + v[2] ** 2);\n}, 0) / trajectoryLog.length;\n\n// Waypoint completion rate\nconst waypointsReached = data.missionAgent.waypointsReached;\nconst completionRate = (waypointsReached / waypoints.length) * 100;\n\n// Communication statistics\nconst packetsTransmitted = data.commAgent.packetsTransmitted;\nconst packetsLost = data.commAgent.packetsLost;\nconst packetLossRate = (packetsLost / packetsTransmitted) * 100;\n\n// Fault statistics\nconst faultDetected = data.faultAgent.faultDetected;\nconst faultType = data.faultAgent.faultType;\n\nconst performanceReport = {\n  missionDuration: data.mission.time,\n  totalIterations: data.mission.iteration,\n  totalDistance: totalDistance,\n  averageSpeed: avgSpeed,\n  waypointsReached: waypointsReached,\n  waypointCompletionRate: completionRate,\n  packetsTransmitted: packetsTransmitted,\n  packetsLost: packetsLost,\n  packetLossRate: packetLossRate,\n  faultDetected: faultDetected,\n  faultType: faultType,\n  finalPosition: data.state.position,\n  finalVelocity: data.state.velocity\n};\n\ndata.performanceReport = performanceReport;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "cbac6673-e567-46bc-b182-37bf741fb95e",
      "name": "Generate Telemetry Log (HTTP)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3376,
        208
      ],
      "parameters": {
        "url": "<__PLACEHOLDER_VALUE__Mission log endpoint URL (e.g., https://api.example.com/mission-log)__>",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "jsonBody": "={{ { \"performanceReport\": $json.performanceReport, \"trajectoryLog\": $json.mission.trajectoryLog, \"telemetryLog\": $json.commAgent.telemetryLog, \"faultLog\": { \"detected\": $json.faultAgent.faultDetected, \"type\": $json.faultAgent.faultType, \"thrusterEfficiency\": $json.faultAgent.thrusterEfficiency } } }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.4
    },
    {
      "id": "611a14c8-6bed-46f6-9e2d-38599dfe1c5d",
      "name": "Trajectory Visualization (animate_rov)",
      "type": "n8n-nodes-base.set",
      "position": [
        3600,
        208
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "viz",
              "name": "visualizationComplete",
              "type": "boolean",
              "value": true
            },
            {
              "id": "msg",
              "name": "message",
              "type": "string",
              "value": "Mission complete. Trajectory visualization would be generated by animate_rov() function."
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "fd082cbe-4188-4435-a4ac-d9e5840b8169",
      "name": "Sonar Agent",
      "type": "n8n-nodes-base.code",
      "position": [
        912,
        448
      ],
      "parameters": {
        "jsCode": "// Sonar Agent: 16-beam multibeam sonar simulation\nconst data = $input.first().json;\n\nconst numBeams = data.sonarAgent.numBeams;\nconst maxRange = data.sonarAgent.maxRange;\nconst fov = data.sonarAgent.fov;\nconst position = data.state.position;\nconst yaw = data.state.attitude[2];\n\n// Simulate obstacle detection (simplified)\nconst detections = [];\nfor (let i = 0; i < numBeams; i++) {\n  const beamAngle = yaw + (fov / 2) * (Math.PI / 180) * (2 * i / (numBeams - 1) - 1);\n  \n  // Simulate random obstacles with 10% detection probability\n  if (Math.random() < 0.1) {\n    const range = Math.random() * maxRange;\n    const bearing = beamAngle;\n    detections.push({\n      beam: i,\n      range: range,\n      bearing: bearing,\n      x: position[0] + range * Math.cos(bearing),\n      y: position[1] + range * Math.sin(bearing)\n    });\n  }\n}\n\ndata.sonarAgent.detections = detections;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d485031a-1e88-4dbc-b1f3-85754f09ebf9",
      "name": "Mission Planning Agent",
      "type": "n8n-nodes-base.code",
      "position": [
        1136,
        448
      ],
      "parameters": {
        "jsCode": "// Mission Planning Agent: Waypoint management and dwell operations\nconst data = $input.first().json;\n\nconst waypoints = data.waypoints;\nconst missionAgent = data.missionAgent;\nconst position = data.state.position;\nconst time = data.mission.time;\n\nconst currentWpIdx = missionAgent.currentWaypointIndex;\n\nif (currentWpIdx >= waypoints.length) {\n  // Mission complete\n  data.missionAgent.missionComplete = true;\n  return [{ json: data }];\n}\n\nconst targetWp = waypoints[currentWpIdx];\nconst targetPos = [targetWp[0], targetWp[1], targetWp[2]];\nconst dwellTime = targetWp[3];\n\n// Calculate distance to waypoint\nconst dx = targetPos[0] - position[0];\nconst dy = targetPos[1] - position[1];\nconst dz = targetPos[2] - position[2];\nconst distance = Math.sqrt(dx * dx + dy * dy + dz * dz);\n\nconst WAYPOINT_THRESHOLD = 0.5;  // meters\n\n// Check if waypoint reached\nif (distance < WAYPOINT_THRESHOLD) {\n  if (!missionAgent.isDwelling && dwellTime > 0) {\n    // Start dwell\n    missionAgent.isDwelling = true;\n    missionAgent.dwellStartTime = time;\n  } else if (missionAgent.isDwelling) {\n    // Check if dwell complete\n    const dwellElapsed = time - missionAgent.dwellStartTime;\n    if (dwellElapsed >= dwellTime) {\n      // Move to next waypoint\n      missionAgent.currentWaypointIndex++;\n      missionAgent.waypointsReached++;\n      missionAgent.isDwelling = false;\n      missionAgent.dwellStartTime = null;\n    }\n  } else {\n    // No dwell required, move to next waypoint\n    missionAgent.currentWaypointIndex++;\n    missionAgent.waypointsReached++;\n  }\n}\n\ndata.missionAgent.targetWaypoint = targetPos;\ndata.missionAgent.distanceToWaypoint = distance;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "256a8f56-2673-4629-8bc3-0cef5308df28",
      "name": "Navigation Agent",
      "type": "n8n-nodes-base.code",
      "position": [
        1360,
        448
      ],
      "parameters": {
        "jsCode": "// Navigation Agent: PD position control + Artificial Potential Field\nconst data = $input.first().json;\n\nconst navAgent = data.navAgent;\nconst state = data.state;\nconst missionAgent = data.missionAgent;\nconst sonarDetections = data.sonarAgent.detections;\n\nconst position = state.position;\nconst velocity = state.velocity;\nconst yaw = state.attitude[2];\nconst targetPos = missionAgent.targetWaypoint || [0, 0, -5];\n\n// PD position control\nconst kp = navAgent.kp_pos;\nconst kd = navAgent.kd_pos;\n\nconst error_x = targetPos[0] - position[0];\nconst error_y = targetPos[1] - position[1];\nconst error_z = targetPos[2] - position[2];\n\nlet Fx = kp * error_x - kd * velocity[0];\nlet Fy = kp * error_y - kd * velocity[1];\nlet Fz = kp * error_z - kd * velocity[2];\n\n// Artificial Potential Field obstacle avoidance\nconst apf_gain = navAgent.apf_gain;\nconst apf_range = navAgent.apf_range;\n\nfor (const detection of sonarDetections) {\n  if (detection.range < apf_range) {\n    const repulsion = apf_gain * (1.0 / detection.range - 1.0 / apf_range);\n    const angle = detection.bearing;\n    Fx -= repulsion * Math.cos(angle);\n    Fy -= repulsion * Math.sin(angle);\n  }\n}\n\n// Yaw control (simple heading to target)\nconst desired_yaw = Math.atan2(error_y, error_x);\nconst yaw_error = desired_yaw - yaw;\nconst Mz = navAgent.kp_yaw * yaw_error - navAgent.kd_yaw * state.angular_velocity[2];\n\n// Store thrust commands\nnavAgent.thrust = [Fx, Fy, Fz, Mz];\ndata.navAgent = navAgent;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "354909d6-6723-49bb-bd45-3487f431deee",
      "name": "Fault Monitoring Agent",
      "type": "n8n-nodes-base.code",
      "position": [
        1584,
        448
      ],
      "parameters": {
        "jsCode": "// Fault Monitoring Agent: Thruster degradation, overspeed, saturation\nconst data = $input.first().json;\n\nconst faultAgent = data.faultAgent;\nconst state = data.state;\nconst thrust = data.navAgent.thrust;\n\n// Check thruster degradation (simulate random degradation)\nif (Math.random() < 0.01) {\n  const thrusterIdx = Math.floor(Math.random() * 4);\n  faultAgent.thrusterEfficiency[thrusterIdx] *= 0.95;\n}\n\n// Check for degraded thrusters\nconst minEfficiency = Math.min(...faultAgent.thrusterEfficiency);\nif (minEfficiency < faultAgent.thrusterDegradationThreshold) {\n  faultAgent.faultDetected = true;\n  faultAgent.faultType = 'thruster_degradation';\n  faultAgent.safeModeActive = true;\n}\n\n// Check overspeed\nconst speed = Math.sqrt(\n  state.velocity[0] ** 2 + \n  state.velocity[1] ** 2 + \n  state.velocity[2] ** 2\n);\nif (speed > faultAgent.overspeedThreshold) {\n  faultAgent.faultDetected = true;\n  faultAgent.faultType = 'overspeed';\n  faultAgent.safeModeActive = true;\n}\n\n// Check actuator saturation\nconst MAX_THRUST = 100.0;\nconst thrustMag = Math.sqrt(\n  thrust[0] ** 2 + thrust[1] ** 2 + thrust[2] ** 2\n);\nif (thrustMag > MAX_THRUST * faultAgent.saturationThreshold) {\n  faultAgent.faultDetected = true;\n  faultAgent.faultType = 'actuator_saturation';\n  faultAgent.safeModeActive = true;\n}\n\ndata.faultAgent = faultAgent;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "60d275ca-9645-43de-a63b-45facc56519d",
      "name": "Check Safe Mode",
      "type": "n8n-nodes-base.if",
      "position": [
        1808,
        448
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.faultAgent.safeModeActive }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "fc8193de-1ce3-416a-a61b-826fc241cd29",
      "name": "Safe Mode Thrust Scaling",
      "type": "n8n-nodes-base.code",
      "position": [
        2032,
        304
      ],
      "parameters": {
        "jsCode": "// Safe Mode: Scale thrust commands to safe levels\nconst data = $input.first().json;\n\nconst SAFE_MODE_SCALE = 0.5;  // Reduce thrust to 50%\nconst thrust = data.navAgent.thrust;\n\ndata.navAgent.thrust = [\n  thrust[0] * SAFE_MODE_SCALE,\n  thrust[1] * SAFE_MODE_SCALE,\n  thrust[2] * SAFE_MODE_SCALE,\n  thrust[3] * SAFE_MODE_SCALE\n];\n\ndata.faultAgent.thrustScaled = true;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "e1f1b7d7-97e1-448d-a283-a093971a8635",
      "name": "Normal Mode",
      "type": "n8n-nodes-base.set",
      "position": [
        2032,
        592
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "normal",
              "name": "faultAgent.thrustScaled",
              "type": "boolean",
              "value": false
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "0ff02c99-edf4-4e63-95c5-a1bd9798f5b1",
      "name": "Dynamics Integration (6-DOF)",
      "type": "n8n-nodes-base.code",
      "position": [
        2784,
        384
      ],
      "parameters": {
        "jsCode": "// 6-DOF Dynamics Integration with Euler method and quadratic drag\nconst data = $input.first().json;\n\nconst DT = data.DT;\nconst state = data.state;\nconst thrust = data.navAgent.thrust;\nconst hydro = data.hydro;\nconst faultAgent = data.faultAgent;\n\n// Apply thruster efficiency\nconst eff = faultAgent.thrusterEfficiency;\nconst Fx = thrust[0] * eff[0];\nconst Fy = thrust[1] * eff[1];\nconst Fz = thrust[2] * eff[2];\nconst Mz = thrust[3] * eff[3];\n\n// Current state\nconst vx = state.velocity[0];\nconst vy = state.velocity[1];\nconst vz = state.velocity[2];\nconst wz = state.angular_velocity[2];\n\n// Quadratic hydrodynamic drag\nconst drag_x = -hydro.drag_linear[0] * vx - hydro.drag_quadratic[0] * vx * Math.abs(vx);\nconst drag_y = -hydro.drag_linear[1] * vy - hydro.drag_quadratic[1] * vy * Math.abs(vy);\nconst drag_z = -hydro.drag_linear[2] * vz - hydro.drag_quadratic[2] * vz * Math.abs(vz);\n\n// Acceleration (F = ma)\nconst ax = (Fx + drag_x) / hydro.mass;\nconst ay = (Fy + drag_y) / hydro.mass;\nconst az = (Fz + drag_z) / hydro.mass;\n\n// Angular acceleration (M = I * alpha)\nconst alpha_z = Mz / hydro.inertia_z;\n\n// Euler integration\nstate.velocity[0] += ax * DT;\nstate.velocity[1] += ay * DT;\nstate.velocity[2] += az * DT;\nstate.angular_velocity[2] += alpha_z * DT;\n\nstate.position[0] += state.velocity[0] * DT;\nstate.position[1] += state.velocity[1] * DT;\nstate.position[2] += state.velocity[2] * DT;\nstate.attitude[2] += state.angular_velocity[2] * DT;\n\n// Normalize yaw to [-pi, pi]\nwhile (state.attitude[2] > Math.PI) state.attitude[2] -= 2 * Math.PI;\nwhile (state.attitude[2] < -Math.PI) state.attitude[2] += 2 * Math.PI;\n\n// Update mission time and iteration\ndata.mission.time += DT;\ndata.mission.iteration++;\n\n// Log trajectory\ndata.mission.trajectoryLog.push({\n  time: data.mission.time,\n  position: [...state.position],\n  velocity: [...state.velocity],\n  attitude: [...state.attitude]\n});\n\ndata.state = state;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "adc10393-7edc-4da1-8041-7003e2ebf82a",
      "name": "Check Mission Complete",
      "type": "n8n-nodes-base.if",
      "position": [
        2960,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.mission.time }}",
              "rightValue": "={{ $json.T_END }}"
            },
            {
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.missionAgent.missionComplete }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e7f7d77d-144a-41ba-99cd-ee5a3c35c41d",
      "name": "Loop Feedback",
      "type": "n8n-nodes-base.set",
      "position": [
        3152,
        688
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": []
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "5454ff05-ada9-4b79-b152-1d63a583e960",
      "name": "Control Loop (20 Hz)",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        688,
        448
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c9b47739-5a87-4c5c-863f-503248885f90",
      "name": "Communication Agent (Telemetry TX)",
      "type": "n8n-nodes-base.code",
      "position": [
        2256,
        304
      ],
      "parameters": {
        "jsCode": "// Communication Agent: Package and transmit telemetry\nconst data = $input.first().json;\nconst commAgent = data.commAgent;\n\n// Simulate packet loss (5%)\nconst packetLost = Math.random() < commAgent.packetLossRate;\n\ncommAgent.packetsTransmitted++;\nif (packetLost) {\n  commAgent.packetsLost++;\n}\n\n// Simulate latency jitter\nconst latency = commAgent.latencyMin + \n  Math.random() * (commAgent.latencyMax - commAgent.latencyMin);\n\n// Package telemetry\nconst telemetryPacket = {\n  time: data.mission.time,\n  position: [...data.state.position],\n  velocity: [...data.state.velocity],\n  thrust: [...data.navAgent.thrust],\n  faults: data.faultAgent.faultDetected,\n  waypoint: data.missionAgent.currentWaypointIndex,\n  packet_id: commAgent.packetsTransmitted,\n  packetLost: packetLost,\n  latency: latency\n};\n\n// Log telemetry\ncommAgent.telemetryLog.push(telemetryPacket);\ndata.commAgent = commAgent;\n\nreturn [{ json: data }];"
      },
      "typeVersion": 2
    },
    {
      "id": "4d9744b1-6bd1-422c-a9f3-1d470e4a4a66",
      "name": "Merge Comm Paths",
      "type": "n8n-nodes-base.merge",
      "position": [
        2480,
        376
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "9d4fe7d4-a29b-481c-af9d-06e87d757118",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1760,
        -512
      ],
      "parameters": {
        "color": 6,
        "width": 624,
        "height": 448,
        "content": "\n## Prerequisites\n- AI model API key (OpenAI / NVIDIA NIM)\n- Microsoft Dynamics IS-OGP credentials\n- HTTP endpoint for telemetry logging\n- UAV simulation or live telemetry data source\n## Use Cases\n- Autonomous UAV search-and-rescue mission coordination\n- Drone fleet fault monitoring and safe-mode handling\n## Customisation\n- Swap AI agents for domain-specific models (e.g., NVIDIA Isaac)\n- Extend Dynamics integration to other ERP systems (SAP, Salesforce)\n## Benefits\n- Fully autonomous UAV control with no manual intervention\n- Real-time fault detection and safe-mode branching"
      },
      "typeVersion": 1
    },
    {
      "id": "1e2a427a-2cb7-4493-9b1a-8d323000adcf",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        -368
      ],
      "parameters": {
        "width": 512,
        "height": 320,
        "content": "## Setup Steps\n\n1. Import workflow JSON into your n8n instance.\n2. Configure UAV mission trigger parameters (start coordinates, mission ID).\n3. Set agent credentials \u2014 connect AI model API keys (e.g., OpenAI or NVIDIA NIM).\n4. Link Microsoft Dynamics IS-OGP credentials under n8n Credentials Manager.\n5. Set HTTP endpoint URL for telemetry log generation node.\n6. Configure trajectory visualisation output path (e.g., `telemetry_csv` file destination).\n7. Adjust control loop interval (default 10 Hz) to match your UAV's requirements."
      },
      "typeVersion": 1
    },
    {
      "id": "ee7fd4cf-e0d0-42fa-8330-8292a0812c5e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -320
      ],
      "parameters": {
        "width": 672,
        "height": 272,
        "content": "## How It Works\nThis workflow automates an Autonomous UAV (Unmanned Aerial Vehicle) mission using a multi-agent AI architecture in n8n. Designed for aerospace engineers, UAV operators, and autonomous systems researchers, it solves the challenge of coordinating mission planning, real-time fault monitoring, safe-mode handling, telemetry communication, and enterprise system integration in a single pipeline. The flow begins with mission initialisation, spawning specialised agents such as Sonar, Mission Planning, Navigation, and Fault Monitoring within a 10 Hz control loop. A safe-mode checker branches into thrust scaling or normal operation. A Communication Agent streams telemetry, which feeds into performance analysis, path merging, and Microsoft Dynamics OGP integration. Mission completion is verified, telemetry logs are generated via HTTP, trajectory is visualised, and a loop feedback closes the cycle."
      },
      "typeVersion": 1
    },
    {
      "id": "fa13d8a8-1513-4a2c-b445-91f04815ee92",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1760,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 704,
        "content": "## Check Safe Mode\n**What:** Evaluates flight safety status.\n**Why:** Branches execution into safe-mode thrust scaling or normal operation."
      },
      "typeVersion": 1
    },
    {
      "id": "c7f2804e-15bd-41a2-be39-7a147adfcc28",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 1104,
        "height": 528,
        "content": "## Sonar / Mission Planning / Navigation / Fault Monitoring Agents\n**What:** Execute domain-specific tasks in parallel.\n**Why:** Distributes intelligence across specialised agents for accuracy and speed."
      },
      "typeVersion": 1
    },
    {
      "id": "a2b1a03d-834b-475f-b5f5-bf16e17c8c9f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 656,
        "content": "## Initialise Mission & Agents\n**What:** Spins up all sub-agents.\n**Why:** Ensures each specialist agent is ready before the control loop begins."
      },
      "typeVersion": 1
    },
    {
      "id": "d3c9086c-dbad-4176-b5b5-0b9f2837e7df",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3328,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 544,
        "content": "## Generate Telemetry Log / Trajectory Visualisation\n**What:** Outputs HTTP log and renders trajectory file.\n**Why:** Creates auditable records and visual mission replays."
      },
      "typeVersion": 1
    },
    {
      "id": "7a789916-2891-4d30-b6c4-48993b899867",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2224,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 576,
        "content": "## Merge Comm Paths / Performance Analysis\n**What:** Consolidates outputs and analyses performance.\n**Why:** Provides unified mission health metrics.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "025cb636-ecb1-46c6-a061-74e196c7df29",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2688,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 640,
        "content": "## Dynamics Integration (IS-OGP)\n**What:** Pushes mission data to Microsoft Dynamics.\n**Why:** Enables enterprise traceability and compliance logging."
      },
      "typeVersion": 1
    },
    {
      "id": "b13e0843-47c3-43f8-9b10-b764baf990f0",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2496,
        704
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 416,
        "content": "## Loop Feedback\n**What:** Returns execution to the control loop.\n**Why:** Sustains continuous autonomous operation until mission completion."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "320a09ef-464a-4eff-9afd-bc74581071f4",
  "connections": {
    "Normal Mode": {
      "main": [
        [
          {
            "node": "Communication Agent (Telemetry TX)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sonar Agent": {
      "main": [
        [
          {
            "node": "Mission Planning Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Feedback": {
      "main": [
        [
          {
            "node": "Control Loop (20 Hz)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Safe Mode": {
      "main": [
        [
          {
            "node": "Safe Mode Thrust Scaling",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Comm Paths",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Normal Mode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Comm Paths": {
      "main": [
        [
          {
            "node": "Dynamics Integration (6-DOF)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Navigation Agent": {
      "main": [
        [
          {
            "node": "Fault Monitoring Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start ROV Mission": {
      "main": [
        [
          {
            "node": "Initialize Mission & Agents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Control Loop (20 Hz)": {
      "main": [
        [
          {
            "node": "Performance Analysis",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sonar Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Performance Analysis": {
      "main": [
        [
          {
            "node": "Generate Telemetry Log (HTTP)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Mission Complete": {
      "main": [
        [
          {
            "node": "Performance Analysis",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Feedback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fault Monitoring Agent": {
      "main": [
        [
          {
            "node": "Check Safe Mode",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mission Planning Agent": {
      "main": [
        [
          {
            "node": "Navigation Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Safe Mode Thrust Scaling": {
      "main": [
        [
          {
            "node": "Communication Agent (Telemetry TX)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize Mission & Agents": {
      "main": [
        [
          {
            "node": "Control Loop (20 Hz)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dynamics Integration (6-DOF)": {
      "main": [
        [
          {
            "node": "Check Mission Complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Telemetry Log (HTTP)": {
      "main": [
        [
          {
            "node": "Trajectory Visualization (animate_rov)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Communication Agent (Telemetry TX)": {
      "main": [
        [
          {
            "node": "Merge Comm Paths",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Comm Paths",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}