WPIRoboticsProjects / GRIP

Program for rapidly developing computer vision applications
http://wpiroboticsprojects.github.io/GRIP
Other
377 stars 107 forks source link

Support Raspberry Pi #366

Closed ThomasJClark closed 7 years ago

ThomasJClark commented 8 years ago

It would be cool if GRIP ran on a Raspberry Pi. To do this, we need:

GRIP would likely only work in headless mode (I don't think JavaFX is supported on arm/linux)

bathtubed commented 8 years ago

Same exact thing happens for me. @vScourge Can you try getting Network Tables to publish?

ThadHouse commented 8 years ago

Does anyone have an Axis Ethernet camera to use for testing? Our team uses them instead of the USB cameras, so I can't help camera capture issues.

bathtubed commented 8 years ago

I have an mpjeg stream I can generate but I haven't been able to get that to work with GRIP normally, let alone on a Pi

vScourge commented 8 years ago

@EdWard680 I had left my publish step out to keep it simple, but putting it back in it now ends with this error:

SEVERE: NetworkTables: TCPConnector.cpp:157 select() to  port 1735 error 111 - Connection refused

... which isn't too surprising since I don't have a RoboRio running on this network yet? I can try that but maybe not until tomorrow.

bathtubed commented 8 years ago

You don't have to, but in order to test it you could start a Network Table server on your computer using Eclipse > WPILib > Outline Viewer and then tell GRIP to connect to that.

multiplemonomials commented 8 years ago

We were able to get GRIP capturing images and publishing over networktables using a Beaglebone Black and an Axis M1013. When I tried the only USB camera we had on a Linux desktop, GRIP said it didn't support the color format.

bathtubed commented 8 years ago

@multiplemonomials Can you upload the core.jar you used?

multiplemonomials commented 8 years ago

As I linked in an earlier post, https://www.dropbox.com/s/7iueslu26avp7d6/GRIP-archlinuxarm-deployable.jar?dl=0

This needs the libstdc++.so

bathtubed commented 8 years ago

My mistake. I thought those were just the dependencies

multiplemonomials commented 8 years ago

Hey, waitaminute!
@ThadHouse, you said in an earlier post that you got an error about the symbol _ZdlPvj. I just realized, that's a mangled c++ name, and it unmangles to

 operator delete(void*, unsigned int)
ThadHouse commented 8 years ago

Hmm. So I wonder why it couldn't find delete? If I compile something on my pi physically with GCC 4.9.2, it works, and the GCC 5 cross compiler works as log as the libstdc++.so is loaded, so I wonder where delete would be located for the compiler you built.

multiplemonomials commented 8 years ago

Looking at the files, I get

➜  build  arm-linux-gnueabihf-nm /usr/arm-linux-gnueabihf/oldc++/lib/libstdc++.so | grep _Zdl | c++filt
00050e9c T operator delete(void*)
00050ec0 T operator delete(void*, std::nothrow_t const&)
0006956c t operator delete(void*, void*)
➜  build  arm-linux-gnueabihf-nm /usr/arm-linux-gnueabihf/lib/libstdc++.so | grep _Zdl | c++filt
0006e9b4 T operator delete(void*)
0006e9b8 T operator delete(void*, unsigned int)
0006e9bc T operator delete(void*, std::nothrow_t const&)

In other words, the signature of delete is different between the two files. From the one you took from your Pi:

➜  build  strings ~/Downloads/libstdc++.so.6.0.20 | grep _Zdl | c++filt
operator delete(void*)
operator delete(void*, std::nothrow_t const&)

operator delete(void*, unsigned int) is missing, which would explain the error.

ThadHouse commented 8 years ago

Ah. So it would require a libstdc++.so.6 anyway. So no point in doing the custom GCC 4.9-GCC 5 mix. If we have to have the library, we'll have to provide a custom .so anyway, and can just use the stock arm-linux-gnueabihf gcc.

multiplemonomials commented 8 years ago

Looks like this function is called a "placement delete" and is relatively new. See here. I commented its declaration out in the headers and rebuilt ntcore. No change. Still working on it.

ThadHouse commented 8 years ago

One thing that potentially does help us is that the newest ntcore, if it fails to load the library built into the jar, it will attempt to load a libntcore.so from the current directory. So that means we might not have to have separate jars, at least for ntcore. We would have to have them still for OpenCV I think however.

bathtubed commented 8 years ago

I was able to get GRIP "processing" (publishing the frame rate of) an MPJEG stream on my Pi 2

vScourge commented 8 years ago

@EdWard680 Awesome. What camera are you using? We're giving up on USB and trying an Axis tonight, see if we have better luck. Are you using any binaries different from what's been posted here earlier?

bathtubed commented 8 years ago

I posted the jar I compiled and I'm using the libntcore.so and the libstdc++.so posted most recently above. I had the same USB webcam problem you had, which is worth still investigating since I only get that issue on the Pi. I used this program to stream an mpjeg stream from the Pi. It supports using a USB camera or the raspberry pi camera with a lot of configuration potential. Once you do that it's easy to view the stream in a browser, in Smart Dash, and in the GRIP previewer.

I tested it with an mpjeg stream generated from the raspberry pi camera, as well as one generated from the usb camera I'm using (ps3 eye) at the same quality and it worked great. I'm not sure how fast it actually is yet, as I haven't tried a vision algo yet

multiplemonomials commented 8 years ago

OK, I think I figured out how to fix the dreaded _ZdlPvj issue. It may in fact have been an issue with my system headers. In new, I replaced

inline void operator delete(void*, void*) _GLIBCXX_USE_NOEXCEPT { }

with

inline void operator delete(void*, unsigned int) _GLIBCXX_USE_NOEXCEPT { }

Now everything more or less works. I got a libntcore.so that doesn't use _ZdlPvj. @ThadHouse , try this out: libntcore.so.zip

vScourge commented 8 years ago

@EdWard680 Were you also running GRIP on the Pi? We're running mjpeg-streamer now (with -b, to run in background) and it seems to be using the USB camera (light is on). We also have GRIP running on the Pi but it can't find the stream. We're using "localhost:8080" but the error says it's expecting the stream at "http://localhost:8080/mjpg/video.mjpg". GRIP fails saying that server is returning response 400.

We're looking for an option to change the output address in mjpeg-streamer, but no luck so far.

bathtubed commented 8 years ago

I was running GRIP on the Pi. I was running it with mjpg_streamer -o "output_http.so -w ./www -p 1180" -i "input_uvc -y -n -f 15 -r 640x480" This allows you to access the stream at http://<pi-address>:1180/?action=stream You should be able to view it in your browser, and you should be able to see it in GRIP preview by adding that as an IP camera. It should also work on the Pi. The address it's expecting is the one used by Axis, as long as you put the whole url in it overrides it I believe.

vScourge commented 8 years ago

@EdWard680 Great, that did the trick, thank you very much. We're just down to some NetworkTable errors, since the robot isn't connected yet.

ThadHouse commented 8 years ago

@multiplemonomials I still get the same error with that latest library too.

multiplemonomials commented 8 years ago

What? How can that be? Are you sure you're trying the right file? According to nm, that library doesn't ever reference _ZdlPvj.

I rebuilt all of the other libraries as well. The new GRIP jar, with optimizations enabled so it should run much faster, is here.

ThadHouse commented 8 years ago

Hmm. It must have extracted wrong. Now it attempts to load correctly, and nm shows now reference, however it immediately SegFaults on startup. Give me a minute to try and debug why.

ThadHouse commented 8 years ago

Ok it gives the error I received when trying to cross compile with GCC 4.9. Program received signal SIGILL, Illegal instruction.

ThadHouse commented 8 years ago

So compiling it native on my Pi with GCC 4.9 does work. I wonder if there's a bug in the GCC 4.9 cross compiler.

multiplemonomials commented 8 years ago

Wait, why is that a segfault?

ThadHouse commented 8 years ago

I don't know. When running code without gdb, it just prints Segmentation Fault and quits. Then if I run under GDB, thats when it shows that the program received SIGILL.

multiplemonomials commented 8 years ago

You're just running ntcore, right? Not GRIP?

ThadHouse commented 8 years ago

Yeah thats just getting ntcore working. A super simple program. Just linking to the so, and initializing NetworkTables.

multiplemonomials commented 8 years ago

You're using a Pi 2, right? I'm going to try to compile without NEON.

ThadHouse commented 8 years ago

Yeah its a Pi 2.

multiplemonomials commented 8 years ago

OK, try this: libntcore-test2.so.zip

ThadHouse commented 8 years ago

Same error.

multiplemonomials commented 8 years ago

This one? libntcore-test3.so.zip

ThadHouse commented 8 years ago

That one works! What was the trick?

multiplemonomials commented 8 years ago

That was compiled using the optimization flags for a rasberry pi 1. Are you ABSOLUTELY, POSITIVELY SURE that you have a pi 2?

multiplemonomials commented 8 years ago

Try running

uname -m

on the pi.

ThadHouse commented 8 years ago

It's definitely a Pi 2. ArmV7. The Pi 1 was V6. However I know that the raspbian on the Pi 2 was designed to run Pi 1 binaries, so maybe even it requires those flags to work. The GCC 5 library working with only the libstdc++.so makes even less sense if that is the case however.

multiplemonomials commented 8 years ago

I could make 2 separate builds: one for the Pi 1 and the Pi 2 on Raspbian, and one for the Pi 2 on any other distro and the Beaglebone Try this one: libntcore-test4.so.zip

ThadHouse commented 8 years ago

That download brings back the segmentation fault. Testing the builds on my BBB running debian to see if it has the same issue.

I'll be able to test that tomorrow on my Pi 1. But getting ntcore and GRIP working on a Pi 1 is going to be a lost cause anyway, as they are guaranteed to be too slow to actually work.

ThadHouse commented 8 years ago

So builds 2 and 4 work properly on my BBB. Build 3 does not.

multiplemonomials commented 8 years ago

OK, this one is with

-march=armv6j -mtune=generic-armv7-a -mfpu=vfp

libntcore-test5.so.zip

(the one that worked was with -mcpu-armv6j -mfpu=vfp)

multiplemonomials commented 8 years ago

Build 1 was with -mfpu=neon, so I guess that's out. What's more concerning is that apparently the Pi and Beaglebone are completely incompatible.

ThadHouse commented 8 years ago

Build 5 worked on Pi 2, but not on BBB

ThadHouse commented 8 years ago

Build 1 works on my BBB too, which isn't surprising as I know the BBB supports neon. Thought the Pi 2 did as well.

multiplemonomials commented 8 years ago

OK, this one is with -march=armv7-a -mfpu=neon-vfpv4. According to this thread, that should work on a Pi 2. libntcore-test6.so.zip

Also, what happened when you tried to run build 5 on the BBB?

ThadHouse commented 8 years ago

Build 5 had the Illegal instruction error on the BBB.

Build 6 has the Illegal instruction error on the Pi 2, and runs on the BBB.

multiplemonomials commented 8 years ago

Something is really weird here. That command comes from the raspberry pi forums. Is your Pi up to date? Maybe you should see if a different distro, like Arch, fixes it. I'll try one more time.