ArduPilot / node-mavlink

This project is providing native TypeScript bindings and tools for sending and receiving MavLink messages over a verity of medium
GNU Lesser General Public License v3.0
75 stars 25 forks source link

Unable to send messages over UDP #4

Closed Pexeus closed 2 years ago

Pexeus commented 2 years ago

I am trying to send and revieve messages from/to a simulation (dronekit-sitl)

I have managed to recieve and parse messages without problems. However, when I tried to send the ARM command to the simulated drone, nothing happens. However, it does work when I tried the same in Python, so I dont think the simulator is the problem. I think there is something I dont understand in the JS library.

Here is the JS Code:

` async function main() { const port = new MavEsp8266()

// THIS PART WORKS

// start the communication
await port.start()

// log incomming packets
port.on('data', packet => {
    const hit = REGISTRY[packet.header.msgid]

    if(hit) {
        const data = packet.protocol.data(packet.payload, hit)
        console.log(data)
    }
})

// THIS IS THE PART THAT DOES NOT WORK

const msg = new common.CommandInt()
msg.command = common.MavCmd.COMPONENT_ARM_DISARM
msg.param2 = 1

await port.send(msg)

}`

Here is the Python code that worked: ` def arm():

Arm

# master.arducopter_arm() or:
master.mav.command_long_send(
    master.target_system,
    master.target_component,
    mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM,
    0,
    1, 0, 0, 0, 0, 0, 0)

# wait until arming confirmed (can manually check with master.motors_armed())
print("Waiting for the vehicle to arm")
master.motors_armed_wait()
print('Armed!')

`

I am not getting any Errors. It just doesnt arrive in the simulator.

padcom commented 2 years ago

Hi, you'll have to be a bit more specific and, maybe if you'll find the time, cleanup the code you pasted. Nevertheless, I think there might be a number of problems.

First, the destination you are sending the message to might be different from what you'd expect. You might think you are sending the data back to the correct host (the sim in this case) but it may be that you're sending it out into the void if the IP address changes. Stranger things have happened.

Second, your REGISTRY (which you didn't show here) might not contain the command you are expecting. This would mean that the hit key is always undefined and, as we know, that evaluates to a falsy value in which case the if-block will be skipped.

HTH.

Pexeus commented 2 years ago

Good Evening!

First of all, thank you so much for the swift response!

Lets start with the complete code

const { MavEsp8266, common, MavLinkProtocolV2, send } = require("node-mavlink")
const {
    minimal, ardupilotmega, uavionix, icarous,
    asluav, development, matrixpilot, paparazzi, ualberta,
} = require("node-mavlink")

const REGISTRY = {
...minimal.REGISTRY,
...common.REGISTRY,
...ardupilotmega.REGISTRY,
...uavionix.REGISTRY,
...icarous.REGISTRY,
...asluav.REGISTRY,
...development.REGISTRY,
...matrixpilot.REGISTRY,
...paparazzi.REGISTRY,
...ualberta.REGISTRY,
}

async function main() {
    const port = new MavEsp8266()

    // start the communication
    await port.start()

    // log incomming packets
    port.on('data', packet => {
        const hit = REGISTRY[packet.header.msgid]

        if(hit) {
            const data = packet.protocol.data(packet.payload, hit)
            console.log(data)
        }
    })

    console.log("sending...");

    const msg = new common.CommandInt()
    msg.command = common.MavCmd.COMPONENT_ARM_DISARM
    msg.param2 = 1

    await port.send(msg)

    console.log("message sent!")
}

main()

About the destination port This might be the issue! However, im pretty sure I am using the default ports on MAVProxy. For Verification, here is the Output of the simulator:

SIM_VEHICLE: "mavproxy.py" "--out" "127.0.0.1:14550" "--out" "127.0.0.1:14551" "--master" "tcp:127.0.0.1:5760" "--sitl" "127.0.0.1:5501" "--map" "--console"

-> Both the simulator and the JS app are running on the same machine.

About the verification of the message I am using the UI privided by the sim_vehicle.py application, found in the Ardupilot Repository. So I can verificate if the simulated drone is getting armed over the UI.

Is my approach on this generally not ideal? The reason im using UDP in the first place is because thats how I did it over Python. Should I do it in a different way?

Thanks so much for your time!

padcom commented 2 years ago

Let's start with the basics. First of all modify your code to display what you are getting and if you are getting anything useful:

    if(hit) {
        const data = packet.protocol.data(packet.payload, hit)
        console.log(data)
    } else {
      console.log(packet.debug())
    }

and see if you are getting any packages back.

Pexeus commented 2 years ago

Ok, here is the Output from the console:

SystemTime { timeUnixUsec: 1644529881096661n, timeBootMs: 281100 }
Ahrs {
  omegaIx: -0.0037435279227793217,
  omegaIy: -0.0037949790712445974,
  omegaIz: -0.0033192026894539595,
  accelWeight: 0,
  renormVal: 0,
  errorRp: 0.0023874498438090086,
  errorYaw: 0.0015264579560607672
}
SimState {
  roll: 0,
  pitch: 0,
  yaw: -0.12217313796281815,
  xacc: 0,
  yacc: 0,
  zacc: -9.806650161743164,
  xgyro: 0,
  ygyro: 0,
  zgyro: 0,
  lat: -353632621,
  lng: 1491652374
}
HwStatus { Vcc: 5000, I2Cerr: 0 }
Wind { direction: -180, speed: 0, speedZ: 0 }
TerrainReport {
  lat: -353632622,
  lon: 1491652376,
  terrainHeight: 583.8436889648438,
  currentHeight: 0.07999999821186066,
  spacing: 100,
  pending: 0,
  loaded: 504
}
EkfStatusReport {
  velocityVariance: 0.00720558874309063,
  posHorizVariance: 0.006014871411025524,
  posVertVariance: 0.005755728110671043,
  compassVariance: 0.010953007265925407,
  terrainAltVariance: 0,
  flags: 831,
  airspeedVariance: 0
}
LocalPositionNed {
  timeBootMs: 281100,
  x: -0.014994458295404911,
  y: 0.018585756421089172,
  z: -0.08430256694555283,
  vx: -0.017012668773531914,
  vy: 0.021161163225769997,
  vz: -0.018189823254942894
}
Vibration {
  timeUsec: 281100848n,
  vibrationX: 0.0027525308541953564,
  vibrationY: 0.0027524353936314583,
  vibrationZ: 0.002870206953957677,
  clipping0: 0,
  clipping1: 0,
  clipping2: 0
}
BatteryStatus {
  currentConsumed: 0,
  energyConsumed: 0,
  temperature: 32767,
  voltages: [
    12587, 65535, 65535,
    65535, 65535, 65535,
    65535, 65535, 65535,
    65535
  ],
  currentBattery: 0,
  id: 0,
  batteryFunction: 0,
  type: 0,
  batteryRemaining: 100,
  timeRemaining: 0,
  chargeState: 1,
  voltagesExt: [ 0, 0, 0, 0 ],
  mode: 0,
  faultBitmask: 0
}
AoaSsa { timeUsec: 281100848n, AOA: 0, SSA: 0 }
Attitude {
  timeBootMs: 281360,
  roll: 0.0012741833925247192,
  pitch: 0.001072244718670845,
  yaw: -0.10873375833034515,
  rollspeed: 0.0003962656483054161,
  pitchspeed: 0.0003454601392149925,
  yawspeed: 0.0007556115742772818
}
GlobalPositionInt {
  timeBootMs: 281360,
  lat: -353632622,
  lon: 1491652376,
  alt: 584170,
  relativeAlt: 88,
  vx: -1,
  vy: 2,
  vz: -1,
  hdg: 35378
}
SysStatus {
  onboardControlSensorsPresent: 325188671,
  onboardControlSensorsEnabled: 308379711,
  onboardControlSensorsHealth: 326205503,
  load: 0,
  voltageBattery: 12587,
  currentBattery: 0,
  dropRateComm: 0,
  errorsComm: 0,
  errorsCount1: 0,
  errorsCount2: 0,
  errorsCount3: 0,
  errorsCount4: 0,
  batteryRemaining: 100,
  onboardControlSensorsPresentExtended: 0,
  onboardControlSensorsEnabledExtended: 0,
  onboardControlSensorsHealthExtended: 0
}
PowerStatus { Vcc: 5000, Vservo: 0, flags: 0 }
MissionCurrent { seq: 0 }
VfrHud {
  airspeed: 0.022061703726649284,
  groundspeed: 0.027317345142364502,
  alt: 584.1699829101562,
  climb: 0.017944587394595146,
  heading: 353,
  throttle: 0
}
ServoOutputRaw {
  timeUsec: 281360744,
  servo1Raw: 1500,
  servo2Raw: 1500,
  servo3Raw: 1000,
  servo4Raw: 1500,
  servo5Raw: 0,
  servo6Raw: 0,
  servo7Raw: 0,
  servo8Raw: 0,
  port: 0,
  servo9Raw: 0,
  servo10Raw: 0,
  servo11Raw: 0,
  servo12Raw: 0,
  servo13Raw: 0,
  servo14Raw: 0,
  servo15Raw: 0,
  servo16Raw: 0
}
RcChannels {
  timeBootMs: 281360,
  chan1Raw: 1500,
  chan2Raw: 1500,
  chan3Raw: 1000,
  chan4Raw: 1500,
  chan5Raw: 1800,
  chan6Raw: 1000,
  chan7Raw: 1000,
  chan8Raw: 1800,
  chan9Raw: 0,
  chan10Raw: 0,
  chan11Raw: 0,
  chan12Raw: 0,
  chan13Raw: 0,
  chan14Raw: 0,
  chan15Raw: 0,
  chan16Raw: 0,
  chan17Raw: 0,
  chan18Raw: 0,
  chancount: 16,
  rssi: 255
}
RawImu {
  timeUsec: 281360744n,
  xacc: 0,
  yacc: 0,
  zacc: -1001,
  xgyro: 4,
  ygyro: 4,
  zgyro: 4,
  xmag: 224,
  ymag: 80,
  zmag: -528,
  id: 0,
  temperature: 3716
}
ScaledImu2 {
  timeBootMs: 281360,
  xacc: 0,
  yacc: 0,
  zacc: -1001,
  xgyro: 4,
  ygyro: 4,
  zgyro: 4,
  xmag: 224,
  ymag: 80,
  zmag: -528,
  temperature: 3716
}
ScaledImu3 {
  timeBootMs: 281360,
  xacc: 0,
  yacc: 0,
  zacc: 0,
  xgyro: 0,
  ygyro: 0,
  zgyro: 0,
  xmag: 224,
  ymag: 80,
  zmag: -528,
  temperature: 0
}
ScaledPressure {
  timeBootMs: 281360,
  pressAbs: 945.0450439453125,
  pressDiff: 0.000002441406195430318,
  temperature: 3120,
  temperaturePressDiff: 0
}
ScaledPressure2 {
  timeBootMs: 281360,
  pressAbs: 945.0382080078125,
  pressDiff: 0,
  temperature: 3120,
  temperaturePressDiff: 0
}
GpsRawInt {
  timeUsec: 281204000n,
  lat: -353632621,
  lon: 1491652374,
  alt: 584090,
  eph: 121,
  epv: 200,
  vel: 0,
  cog: 0,
  fixType: 6,
  satellitesVisible: 10,
  altEllipsoid: 0,
  hAcc: 300,
  vAcc: 300,
  velAcc: 40,
  hdgAcc: 0,
  yaw: 0
}

This comes in at about 10 messages per second.

Pexeus commented 2 years ago

Good news and bad news!

Apologies for all the stupid questions!

I have now managed to connect to the simulator over TCP by adding --out tcpin:127.0.0.1:7070 to the mavproxy.py parameters.

This is the "TCP based" code:

const {connect} = require("net")
const {MavLinkPacketSplitter, MavLinkPacketParser, MavLinkProtocolV2, common, send } = require("node-mavlink")

const {
  minimal, ardupilotmega, uavionix, icarous,
  asluav, development, matrixpilot, paparazzi, ualberta,
} = require("node-mavlink")

const REGISTRY = {
...minimal.REGISTRY,
...common.REGISTRY,
...ardupilotmega.REGISTRY,
...uavionix.REGISTRY,
...icarous.REGISTRY,
...asluav.REGISTRY,
...development.REGISTRY,
...matrixpilot.REGISTRY,
...paparazzi.REGISTRY,
...ualberta.REGISTRY,
}

const port = connect({ host: '127.0.0.1', port: 7070 })

port.on('connect',async () => {
  console.log('Connected!')

  const msg = new common.CommandInt()
  msg.command = common.MavCmd.REQUEST_PROTOCOL_VERSION
  msg.param1 = 1

  await send(port, msg, new MavLinkProtocolV2())

})

const reader = port
  .pipe(new MavLinkPacketSplitter())
  .pipe(new MavLinkPacketParser())

reader.on('data', packet => {
  const hit = REGISTRY[packet.header.msgid]

  if(hit) {
    const data = packet.protocol.data(packet.payload, hit)
    console.log(data)
  } else {
    console.log(packet.debug())
  }
})

However, there is a new problem:

When i send the following command to the simulator:

const msg = new common.CommandInt()
msg.command = common.MavCmd.REQUEST_PROTOCOL_VERSION
msg.param1 = 1

await send(port, msg, new MavLinkProtocolV2())

I get this message in the simulators console: Got COMMAND_ACK: REQUEST_PROTOCOL_VERSION: UNSUPPORTED

Am I using incompatible systems? Or is my code wrong?

Again, sorry for all the stupid questions!

padcom commented 2 years ago

There are no stupid questions :)

I think what is happening here is you're not executing the protocol negotiation phase or the sim only works with protocol version 1 (I don't know which is which tbh). Try sending the command using MavLinkProtocolV1 and see what happens.

https://mavlink.io/en/guide/mavlink_version.html#negotiating_versions

padcom commented 2 years ago

Closing due to inactivity

sumew commented 11 months ago

I'm also unable to send data to the sitl using ESP8266, @Pexeus did you figure this out?

upcfeather commented 11 months ago

I'm the same question can not send message in udp mode and I create a new issue, please answer me.

https://github.com/ArduPilot/node-mavlink/issues/30

sumew commented 11 months ago

@upcfeather I did these two things and was able to send to SITL

  1. add to the sitl startup script --out udpin:127.0.0.1:14555
  2. set the sendPort to the udpin (14555)
  3. I did not use the correct sysid and compid (needs to be set from packet.protocol)

good luck