kauailabs / navxmxp

Robotics Navigation Sensors. NavX-MXP designed for the National Instruments RoboRIO & FIRST FRC Robotics. Navx-MIcro designed for Android-based FIRST FTC Robots
MIT License
105 stars 87 forks source link

Windows AHRS support #91

Open jnoyola opened 4 years ago

jnoyola commented 4 years ago

I'm not sure if I'm doing something wrong or if the Sim support broke everything. After the Sim support additions, every time I construct an AHRS object, it always uses a SimDevice: navX-Sensor SimDevice created.

When I look through the library code, it looks like it only uses a Serial port if m_simDevice is NULL. And the first thing it always does in the constructor's initialization list is initialize m_simDevice. I use C++, but it appears to have the same logic for Java.

Am I doing something wrong or is this a bug?

kauailabs commented 4 years ago

We tested C++ serial (both TTL UART and USB and didn’t see a problem. As long as you are compiling for RoboRIO SimDevice should be null. Can you be more specific about what’s not working? Can you post a console log that shows the trace of activity?

jnoyola commented 4 years ago

Ok maybe it is me then. I'll adjust the title. I guess the issue is that I can't select the navx on this computer, and maybe it falls back to a SimDevice, and I assumed it was a bug with the sim support because I don't see how the code bypasses the SimDevice in real cases.

So navXUI is able to find the navX on COM4. How can I initialize this with an AHRS object?

kauailabs commented 4 years ago

I don't see how the code bypasses the SimDevice in real cases.

In the real case (compiling for a RoboRIO, running on a RoboRIO), the if(simDevice) clause returns false. For the simulation on windows desktop case, if(simDevice) evaluates to true.

This sleight-of-hand occurs because the WPI Library SimDevice class overrides the bool() operator. You can see the header file for SimDevice here, and in it you'll see the bool operator:

https://github.com/wpilibsuite/allwpilib/blob/master/hal/src/main/native/include/hal/SimDevice.h

I guess the issue is that I can't select the navx on this computer So navXUI is able to find the navX on COM4. How can I initialize this with an AHRS object?

To actually communicate with the navX-sensor via the AHRS class, the robot code you are developing must run on the Roborio. And the navX-sensor must be connected to the RoboRIO via USB. And you need to instantiate the navX-sensor in your RoboRIO C++ code like this:

ahrs = new AHRS(SerialPort::Port::kUSB); 

Is that what you are currently attempting?

jnoyola commented 4 years ago

the WPI Library SimDevice class overrides the bool() operator

Ahh I see. Sorry I missed that.

ahrs = new AHRS(SerialPort::Port::kUSB);

That’s the code I have, but I’m running it on a PC with the navX plugged into the PC’s USB. (It’ll be a RPi on the robot.) I thought we had it working this way 2 years ago, which is why I was too quick to assume there was a bug and dint provide all the details. Is there something specific to it running on the RoboRIO rather than any PC?

kauailabs commented 4 years ago

Since it’s the middle of FRC season, I assume you are trying to write a robot program that runs on a RoboRIO to communicate over uSB with a navX-MXP. And so you’d want to write something like what’s in this example: https://pdocs.kauailabs.com/navx-mxp/examples/rotate-to-angle-2/

Can we take a step back - and can you give me a 10,000 foot view of what you are trying to accomplish?

kauailabs commented 4 years ago

If you want to communicate over USB to navX-sensor from Rpi, you can use the Linux version of the AHRS class mentioned here: https://pdocs.kauailabs.com/navx-mxp/software/linux-library/

jnoyola commented 4 years ago

Not on the RoboRIO. Just a C++ program that can run on a Windows PC or Linux Raspberry Pi. For Linux we’ll use that library.

What about via USB on a Windows PC? navXUI doesn’t appear to be using AHRS in the same way, but it works correctly.

kauailabs commented 4 years ago

What about via USB on a Windows PC?

There is no AHRS class supported on a Windows PC (except for the FRC library in simulate mode, which doesn't actually talk to the sensor.

We've never had anyone desire access to the AHRS interface on windows.

Note that there is support for saving sensor data to file in navXUI, you might find that helpful.

Ok to close out this issue?

jnoyola commented 4 years ago

Ah darn. So how does navXUI access the navX via USB on Windows? I could try to do it the same way.

kauailabs commented 4 years ago

NavX UI uses custom protocol code. The protocol is documented here: https://pdocs.kauailabs.com/navx-mxp/advanced/serial-protocol/

Simplest thing is most like to port Linux AHRS class to Windows.

jnoyola commented 4 years ago

Oh ok, I thought it would use the same library. I could look into porting the Linux class.

Do you know what it is about the WPILib version that only works on the RoboRIO? I don’t usually work with WPILib, but I assumed it just had general serial port classes. Most of the library seems to work anywhere, but maybe IO is specific to the RoboRIO.

kauailabs commented 4 years ago
jnoyola commented 4 years ago

Ok, thanks. I might look into it in the off-season then. I’m surprised more teams don’t do development on different platforms.

jnoyola commented 4 years ago

I wonder if something like this is an option, patching serial ports to work cross-platform rather than porting the whole Linux library. Haven’t looked into it much yet, but I’ll do more research later.

WPILib's serial port implementation is based around the RoboRIO's Linux OS with a patch, so trying to run Serial Ports on Windows, Mac and most Linux platforms in simulation just plain won't work, and will probably crash. A lot. To try and get the most rock-solid support for serial ports possible, we're using the 'jssc' library to ensure we get native support on all platforms.

https://github.com/Open-RIO/Cereal

EDIT: Doesn't seem like a viable option. And in any case, having a Windows analogue to the Linux library is probably more useful than a Windows patch for the RoboRIO version.

kauailabs commented 4 years ago

in any case, having a Windows analogue to the Linux library is probably more useful than a Windows patch for the RoboRIO version.

I believe it depends what the use case really is - anything you can do to help clarify what you are really trying to accomplish will help. Two possibilities exist:

1) Allow the WPI Library simulation to actually interact with a physical navX-Sensor that happens to be connected to the sensor via USB on WIndows.

2) Allow code that uses the AHRS class to directly access the navX-Sensor on Windows when it is connected via USB. But why? How would this be useful?

Please take the time to review these two cases, and indicate which is the case you are envisioning - and exactly why this is important to you. It's not clear if your use case is 1), or 2), or something else. If we can make this clear, we can provide guidance and help.

jnoyola commented 4 years ago

I envision # 2.

Like I said, I want to write a C++ program that will run on a Raspberry Pi (Linux) and connect to the navX-Sensor via USB. Thus the competition code will need to use the Linux library, not the RoboRIO library. And since we develop with Windows, I would like code that uses the AHRS class to directly access the navX-Sensor on Windows when it is connected via USB. Let me know if that's still unclear.

kauailabs commented 4 years ago

And since we develop with Windows, I would like code that uses the AHRS class to directly access the navX-Sensor on Windows when it is connected via USB. Let me know if that's still unclear.

Why not simply write the code on the raspberry Pi directly? That seems like the simplest thing that could possibly work - and it already is available. And windows and Linux are different enough that it will need to be debugged on both platforms.

jnoyola commented 4 years ago

Why not simply write the code on the raspberry Pi directly?

A variety of reasons. We're far more limited on number of Raspberry Pis than laptops. Doing anything on the Pi can be slower for hardware reasons, and development on Linux in general can be slower and less familiar for our team than Windows. We also have higher-end Windows laptops already running the Gazebo simulator and would like to be able to swap in and out our mocks with physical sensors when possible.

I understand that the Linux library is already available and certainly a decent option for our development, but I wanted to get a sense of what's available on Windows and if it would be possible to get full functionality.

jnoyola commented 4 years ago

I think I should have a PR out tonight.

kauailabs commented 4 years ago

Thanks for the heads up, sounds great. I’ll set aside some time to review it.

jnoyola commented 4 years ago

@kauailabs I have a design question for you while I'm working on this. tl;dr at the bottom.

The Linux SerialPort reads, writes, and waits synchronously. Note that it reads 1 character at a time.

In Windows, "waiting for data or timeout" must be an asynchronous wait. Unfortunately the comms port must be opened with all operations synchronous or all operations asynchronous, which gives me some concern. I see two options here:

  1. The comms port is opened with asynchronous operations. The read, write, and wait methods can be synchronous abstractions over the OS calls. The one concern here is that reading 1 character at a time might be slower if we now have to read and then check the result of each character.
  2. The comms port is opened with synchronous operations. Read and write can be the standard synchronous calls. Since a synchronous wait can't take a timeout, it would wait indefinitely. Thus instead we just perform a static sleep. This, of course, might oversleep.

tl;dr Under standard behavior for the navX, is it better to have slightly slower reads but always wake up early if there's data, or to optimize reads but always sleep a fixed amount?

My instinct is to go with option 1 unless there is a very large number of bytes read per sleep cycle.

jnoyola commented 4 years ago

Hopefully option 1 sounds good to you, since that's what I went with. It works well so far!

https://github.com/FRC900/navXTimeSync/pull/4