MAVSDK-Java icon indicating copy to clipboard operation
MAVSDK-Java copied to clipboard

mavsdk-java控制失败

Open ButyAfter opened this issue 2 months ago • 14 comments

第一步:make px4_sitl gz_x500 运行起来仿真环境了

linjl@linjl-virtual-machine:~/lin/PX4-Autopilot$ sudo make px4_sitl gz_x500 [sudo] linjl 的密码: [0/1] cd /home/linjl/lin/PX4-Autopilot/build/px4_sitl_default/src/modules/simulat...x500 GZ_IP=127.0.0.1 /home/linjl/lin/PX4-Autopilot/build/px4_sitl_default/bin/px4


| ___ \ \ \ / / / | | |/ / \ V / / /| | | __/ / \ / /| | | | / /^\ \ ___ | _| / / |_/

px4 starting.

INFO [px4] startup script: /bin/sh etc/init.d-posix/rcS 0 INFO [init] found model autostart file as SYS_AUTOSTART=4001 INFO [param] selected parameter default file parameters.bson INFO [param] importing from 'parameters.bson' INFO [parameters] BSON document size 333 bytes, decoded 333 bytes (INT32:14, FLOAT:3) INFO [param] selected parameter backup file parameters_backup.bson INFO [dataman] data manager file './dataman' size is 1208528 bytes INFO [init] Gazebo simulator 8.9.0 INFO [init] Starting gazebo with world: /home/linjl/lin/PX4-Autopilot/Tools/simulation/gz/worlds/default.sdf INFO [init] Starting gz gui INFO [init] Waiting for Gazebo world... INFO [init] Gazebo world is ready INFO [init] Spawning Gazebo model Warning [Utils.cc:132] [/sdf/model[@name="x500_base"]/link[@name="base_link"]/sensor[@name="air_pressure_sensor"]/gz_frame_id:/home/linjl/lin/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf:L219]: XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor]. Warning [Utils.cc:132] [/sdf/model[@name="x500_base"]/link[@name="base_link"]/sensor[@name="magnetometer_sensor"]/gz_frame_id:/home/linjl/lin/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf:L233]: XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor]. Warning [Utils.cc:132] [/sdf/model[@name="x500_base"]/link[@name="base_link"]/sensor[@name="imu_sensor"]/gz_frame_id:/home/linjl/lin/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf:L259]: XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor]. Warning [Utils.cc:132] [/sdf/model[@name="x500_base"]/link[@name="base_link"]/sensor[@name="navsat_sensor"]/gz_frame_id:/home/linjl/lin/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf:L311]: XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor]. INFO [gz_bridge] world: default, model: x500_0 INFO [lockstep_scheduler] setting initial absolute time to 2520000 us INFO [commander] LED: open /dev/led0 failed (22) WARN [health_and_arming_checks] Preflight Fail: ekf2 missing data WARN [health_and_arming_checks] Preflight Fail: No connection to the GCS INFO [tone_alarm] home set INFO [uxrce_dds_client] init UDP agent IP:127.0.0.1, port:8888 INFO [mavlink] mode: Normal, data rate: 4000000 B/s on udp port 18570 remote port 14550 INFO [mavlink] mode: Onboard, data rate: 4000000 B/s on udp port 14580 remote port 14540 INFO [mavlink] mode: Onboard, data rate: 4000 B/s on udp port 14280 remote port 14030 INFO [mavlink] mode: Gimbal, data rate: 400000 B/s on udp port 13030 remote port 13280 INFO [logger] logger started (mode=all) INFO [logger] Start file log (type: full) INFO [logger] [logger] ./log/2025-09-15/10_25_45.ulg INFO [logger] Opened full log file: ./log/2025-09-15/10_25_45.ulg INFO [mavlink] MAVLink only on localhost (set param MAV_{i}BROADCAST = 1 to enable network) INFO [mavlink] MAVLink only on localhost (set param MAV{i}_BROADCAST = 1 to enable network) INFO [px4] Startup script returned successfully pxh> WARN [health_and_arming_checks] Preflight Fail: No connection to the GCS WARN [health_and_arming_checks] Preflight Fail: No connection to the GCS

第二步:运行mavsdk_server

Image

第三步:查看mavlink实例

Image

可以看到 mavsdk_server_musl_x86_64 应该是和仿真环境连接上了

前三步都是在VMware虚拟机中运行的

第四步:根据mavsdk编写Java程序,使用官方示例

https://github.com/mavlink/MAVSDK-Java/blob/main/examples/java-client/src/main/java/io/mavsdk/example/TakeoffAndLand.java

public class UAVClient {

public static void main(String[] args) {
    // 先创建 System 对象
    io.mavsdk.System drone = new io.mavsdk.System("192.168.245.137",50051);

    CountDownLatch latch = new CountDownLatch(1);


    drone.getAction().arm()
            .doOnComplete(() -> System.out.println("Arming..."))
            .doOnError(throwable -> System.out.println("Failed to arm: "
                    + ((Action.ActionException) throwable).getCode()))
            .andThen(drone.getAction().takeoff()
                    .doOnComplete(() -> System.out.println("Taking off..."))
                    .doOnError(throwable -> System.out.println("Failed to take off: "
                            + ((Action.ActionException) throwable).getCode())))
            .delay(5, TimeUnit.SECONDS)
            .andThen(drone.getAction().land()
                    .doOnComplete(() -> System.out.println("Landing..."))
                    .doOnError(throwable -> System.out.println("Failed t" +
                            "o land: "
                            + ((Action.ActionException) throwable).getCode())))
            .subscribe(latch::countDown, throwable -> latch.countDown());

    try {
        latch.await();
    } catch (InterruptedException ignored) {
        // This is expected
    }
}

}

结果:

Java程序没有任何打印信息,阻塞住了:

Image Image

打印了这个日志后,无人机没有任何反应:

Image

有谁懂吗,帮忙看看

ButyAfter avatar Sep 15 '25 10:09 ButyAfter

Seems like it fails to takeoff because of this: "Preflight Fail: No connection to the GCS".

JonasVautherin avatar Sep 15 '25 10:09 JonasVautherin

Preflight Fail: 但是用commander takeoff命令是可以起飞的 Image

ButyAfter avatar Sep 15 '25 11:09 ButyAfter

In your output, first it was failing ("Arming denied: Resolve system health failures first") and later it worked ("Takeoff detected").

Did you try running your MAVSDK script after commander takeoff succeeded? E.g. do commander land and then run your MAVSDK script.

JonasVautherin avatar Sep 15 '25 12:09 JonasVautherin

在您的输出中,它首先失败(“拒绝布防:首先解决系统健康故障”),然后成功(“检测到起飞”)。

成功后,你尝试运行MAVSDK脚本了吗commander takeoff?例如,执行“do” commander land,然后运行MAVSDK脚本。

第一次执行commander takeoff的时候我没有启动./mavsdk_server_musl_x86_64,所以报错:‘WARN [commander] Arming denied: Resolve system health failures first’.

第二次,我启动了mavsdk_server_musl_x86_64,之后再执行commander takeoff命令,就可以起飞。

ButyAfter avatar Sep 15 '25 13:09 ButyAfter

Right. mavsdk_server_musl_x86_64 will connect MAVSDK to the drone, and it will behave as a ground control station (GCS). So it makes sense that commander takeoff fails before, and succeeds after MAVSDK is connected 👍.

What does your Java code print? Does it print an error? Does it at least print "Arming...", from this line:

.doOnComplete(() -> System.out.println("Arming..."))

And are you sure that 192.168.245.137 is the IP of the machine running mavsdk_server_musl_x86_64, and that 50051 is the port on which mavsdk_server_musl_x86_64 is listening? I'm referring to this line:

io.mavsdk.System drone = new io.mavsdk.System("192.168.245.137",50051);

Also can you show the output of running mavsdk_server_musl_x86_64? This:

$ ./mavsdk_server_musl_x86_64

JonasVautherin avatar Sep 15 '25 21:09 JonasVautherin

对了。mavsdk_server_musl_x86_64它会将 MAVSDK 连接到无人机,无人机将充当地面控制站 (GCS)。所以commander takeoff之前失败,之后成功,这很正常👍。

你的 Java 代码打印了什么?它会打印错误吗?它至少会从这一行打印“Arming...”吗?

.doOnComplete(() -> System.out.println("Arming..."))

你确定这192.168.245.137是正在运行的机器的IP地址吗mavsdk_server_musl_x86_64?这50051是正在监听的端口吗mavsdk_server_musl_x86_64?我指的是下面这行:

io.mavsdk.System drone = new io.mavsdk.System("192.168.245.137",50051);

另外,你能显示运行的输出mavsdk_server_musl_x86_64吗?这个:

$ ./mavsdk_server_musl_x86_64

I'm very sorry that we have a time difference. I was already asleep at that time and now I'm at work.

以下是运行 $ ./mavsdk_server_musl_x86_64 的输出:

Image

Java代码都没有任何打印,只是阻塞住:

Image

是的192.168.245.137是运行mavsdk_server_musl_x86_64 机器的IP,否则应该也不会收到MAVLink: info: Armed by external command 吧:

Image

ButyAfter avatar Sep 16 '25 01:09 ButyAfter

I'm very sorry that we have a time difference. I was already asleep at that time and now I'm at work.

No worries at all 😉.

  • It looks like mavsdk_server_musl_x86_64 detects the drone properly. It means that the MAVLink messages from the drone reach MAVSDK. ✅
  • Apparently, the "arm" function is received by the drone (at 09:20:21). It means that the drone receives MAVLink messages from MAVSDK. ✅
  • "Arming..." is not printed in Java. It feels like MAVSDK never receives an ACK for the arm() command 🤔.
  • At 09:20:32, the drone disarms because it did not receive more commands afer arm().

Can we check that the drone setup works properly? Can you connect QGroundControl to it and arm/takeoff?

JonasVautherin avatar Sep 16 '25 08:09 JonasVautherin

很抱歉我们有时差,我当时已经睡着了,现在正在上班。

完全不用担心😉。

  • 看起来mavsdk_server_musl_x86_64无人机检测正确。这意味着无人机发送的 MAVLink 消息已到达 MAVSDK。✅
  • 显然,“arm”函数已被无人机接收(时间:09:20:21)。这意味着无人机收到了来自 MAVSDK 的 MAVLink 消息。✅
  • Java 中没有打印“Arming...”。感觉 MAVSDK 从未收到该arm()命令的 ACK 🤔。
  • 09:20:32,无人机因未收到更多指令而解除武装arm()

我们可以检查一下无人机设置是否正常吗?您能连接 QGroundControl 并启动/起飞吗?

我已经不想用mavsdk-java了,我发现mavsdk-python中会自动启动mavsdk-server,而且不会出现java的这个问题,但是又因为项目需要用java,所以我现在的想法是用mavsdk-python封装成http服务给java调用了。不知道这样好不好,先试试吧

ButyAfter avatar Sep 17 '25 01:09 ButyAfter

That's your choice, but I think it is a bit convoluted 🙈. MAVSDK-Java works: it is used by some people (on Android, but also on Desktop). The only thing you gain with MAVSDK-Python is that it runs mavsdk_server for you, but at the cost of writing your own abstraction to call it from Java 🤔.

Did you try connecting with QGroundControl to see if your drone simulation works properly?

Also note that you must use the version of MAVSDK-Java that corresponds to your mavsdk_server. Here your mavsdk_server is v3.10.1, which corresponds to https://github.com/mavlink/MAVSDK-Java/releases/tag/3.10.1.

JonasVautherin avatar Sep 17 '25 09:09 JonasVautherin

确实会比较复杂了,希望后面能够解决,好让我能嵌入到java中使用,我也觉得MAVSDK-Java应该很成熟了,但是就是很奇怪。因为一时解决不了,感觉没有做错的地方。也没有人有一样的情况。

是的我mavsdk-java用的也是3.10.1,用的是maven依赖:

  <groupId>io.mavsdk</groupId>
  <artifactId>mavsdk</artifactId>
  <version>3.10.1</version>
Image

我创建了一条mavlink实例,然后QGroundControl 似乎连接不上:

Image Image Image

ButyAfter avatar Sep 18 '25 01:09 ButyAfter

是的我mavsdk-java用的也是3.10.1,用的是maven依赖:

Ok this looks good 👍

我创建了一条mavlink实例,然后QGroundControl 似乎连接不上:

I think that the server address is wrong. I think you want to set "14550" into the "Port" field above, and nothing in the "Server Addresses (optional)".

The way it usually works is that PX4 SITL sends MAVLink over UDP on port 14550. The ground station (QGroundControl or MAVSDK) has to listen to port 14550.

Try to connect QGroundControl, and then the next step will be to see if you can takeoff and land from QGroundControl.

JonasVautherin avatar Sep 18 '25 11:09 JonasVautherin

是我的mavsdk-java用的也是3.10.1,用的是maven依赖:

好的,看起来不错👍

我创建了一个mavlink实例,然后QGroundControl似乎连接不上:

我认为服务器地址错误。我认为您应该在上面的“端口”字段中输入“14550”,而在“服务器地址(可选)”中什么都不填。

其通常工作方式是 PX4 SITL 通过端口 14550 上的 UDP 发送 MAVLink。地面站(QGroundControl 或 MAVSDK)必须监听端口 14550。

尝试连接 QGroundControl,然后下一步将查看您是否可以从 QGroundControl 起飞和降落。

我发现了一个很重要的问题,应该也是进步了。

public class UAVClient {

public static void main(String[] args) throws Exception {
    io.mavsdk.System drone = new io.mavsdk.System("192.168.245.1", 50051);
    System.out.println("Starting example: takeoff and land...");

    CountDownLatch latch = new CountDownLatch(1);

    drone.getAction().arm()
            .subscribe(
                    () -> { System.out.println("Arm OK"); latch.countDown(); },
                    err -> { System.out.println("Arm error: " + err); latch.countDown(); }
            );

    drone.getAction().takeoff()
            .subscribe(
                    () -> { System.out.println("Take Off OK"); latch.countDown(); },
                    err -> { System.out.println("Take Off error: " + err); latch.countDown(); }
            );

    latch.await();
}

}

我使用这段代码,无人机可以正常的解锁arm以及起飞,下面是PX4仿真的输出:

Image

但是java端会输出报错:

Image

目前看来mavsdk-java --> mavsdk-server --> PX4 这条路应该是通的。但是反过来的时候好像出现点问题导致上面这个报错的输出。很疑惑

ButyAfter avatar Sep 19 '25 09:09 ButyAfter

我去,我使用Gradle构建工具后,再用你们的例子可以正常执行! https://github.com/mavlink/MAVSDK-Java/blob/main/examples/java-client/src/main/java/io/mavsdk/example/TakeoffAndLand.java

这难道是因为maven和Gradle中的mavsdk-java的代码不一样吗

ButyAfter avatar Sep 19 '25 09:09 ButyAfter

我去,我使用Gradle构建工具后,再用你们的例子可以正常执行!

Oh that's great! 🎉

这难道是因为maven和Gradle中的mavsdk-java的代码不一样吗

It's exactly the same artifact on Maven Central 🤔.

The "io.grpc.StatusRuntimeException: CANCELLED" suggests that there is an issue with the connection between MAVSDK-Java and mavsdk_server.

Could it be that you have an older MAVSDK-Java in your maven cache? And switching to gradle forced it to download the correct version of MAVSDK-Java?

JonasVautherin avatar Sep 19 '25 12:09 JonasVautherin