Giter Site home page Giter Site logo

crazyflie-link-cpp's Introduction

Crazyflie C++ Link

Dependencies

sudo apt install -y libusb-1.0-0-dev

This relies on pybind11, which is a submodule, so don't forget to

git submodule init 
git submodule update

Build C++ lib and examples

mkdir build
cd build
cmake ..
make

The library can be tested using the included example applications, e.g.,:

./example_scan

Build and install development version of the python binding

Building the python binding requires python>=3.6, cmake and Ninja. Ninja and CMake can be installed with pip on Windows and Mac (pip install cmake ninja), or using apt-get on Ubuntu/debian (apt-get install cmake ninja-build).

The following command builds the binding and register it in development mode (ie. as a link) in python.

python3 setup.py develop --user

The library can be tested using the included example scripts, e.g.,:

python3 examples/scan.py

To Do

  • add new test that uses echoDelay
  • add broadcast support
    • support send2PacketsNoAck
  • integrate in Crazyflie_cpp and crazyflie_tools
  • Hot Plug support (Linux/Mac only)

crazyflie-link-cpp's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

crazyflie-link-cpp's Issues

Sleep vs. yield in CrazyradioThread

We had a number of instances where it seems much better to use a short sleep rather than yield in https://github.com/bitcraze/crazyflie-link-cpp/blob/master/src/CrazyradioThread.cpp#L131-L132

I couldn't find an issue on the C++ side, i.e., the yield does not seem to cause a deadlock. However, it will issue USB requests much more rapidly.

@ataffanel For both Crazyradio PA and Crazyradio2 firmwares, is there a potential race condition between the vendor requests (to configure the radio with a different address etc.) and the send/receive endpoints?

In other words, if I send a sequence of:
libusb_control_transfer (e.g. setAddress 1)
libusb_bulk_transfer (e.g., sendPacket)
libusb_control_transfer (e.g. setAddress 2)

is it possible that the bulk_transfer uses the configuration from the second libusb_control_transfer rather than the first?

Handling of Commander Packets

This is a discussion to decide on how to properly handle packets on ports CRTP_PORT_SETPOINT and CRTP_PORT_SETPOINT_GENERIC. Messages to those ports are real-time commands (such es desired roll/pitch angles). As such, they should not be repeated even if they don't make it to the CF. Ideally, we would also only keep a queue of size 1, i.e., we should never send "old" commands, just in order to flush out our queue. Options:

  1. Add a new single-CF address that works similar to the current broadcasts. This requires a (NRF) firmware change, a small change here, and minor changes for users of crazyflie-link-cpp. We could also add an option in this library to keep the queue size to 1 and to give all broadcasts highest priority.
  2. Add a flag in the Packet data structure to disable retry, i.e., we don't need any firmware changes. The downside is that we still use safelink in that case, which could reject a packet of host and CF are out-of-sync. To keep the queue size to 1, we would need special handling for the two ports mentioned above.

Test case: a client application that sends setpoints at a very high rate (e.g., 1 kHz), should still be able to fly the Crazyflie well.

@ataffanel: It would be nice to get your thoughts on this.

Why not make crazyflie-crtp-cpp a separate repository and add it as a submodule to this repo?

I'm currently working with a college on a project with Crazyflies in which we were given the task of creating a c++ version of the crazyflie-lib-python repository which is what we have been doing for the last few months. You can checkout the repo here.

We started working on this project once we saw that you have created this repository whose purpose is linking the python lib with crtp implementations in c++ code in order to improve the library's performance. We decided to fork your repository to add more functionality to it (which seems now like it was a bad idea) especially functions dealing with Log, Param and AppChannel communication with the crazyflie.

We are close to finishing this project of ours but we don't want it to be detached from your project, so that in case you update your code our project will also receive the updates. To do this we are planning to add your repo as a submodule, however a little digging into the matter revealed that this is quite difficult because of the python bindings.

I'm writing all this in part, to update you with what we are doing with the repo whose link I attached above, since we realised that it must look quite confusing (badly named and still in development). Nevertheless, the main reason I am writing this issue is because I would suggest to you to separate this repo into two repos, one being the "crazyflie-crtp-cpp" which is written in c++ which has nothing to do with python whatsoever but instead is the plain implementation of the crtp in c++ and the other which will include crazyflie-crtp-cpp as a submodule, which will add the py-bindings.

This would be very helpful to us, but it would probably help whoever in the future will be willing to adapt crazyflie-crtp-cpp for himself, to write his own crazyflie lib in c++, or for adding bindings for other languages like rust or what not.

I'm very eager to hear your response to what I have written, and am sorry in advance if it will take me long to respond to you like last time.

Crash when accessing Crazyradio with libusb-win32 driver

On Windows, the documented driver to use with the Crazyflie is "libusb-win32". This is a libusb0 driver and, as far as I understand, libusb1 is not compatible with it.

Libusb1, which is used by this lib, is compatible with the WinUSB driver.

The problem is that, when a radio is installed with a libusb-win32 driver, it is detected by libusb1 but as soon as it is accessed it crashes the program (be it one of the example or the full python). When running the scan example I get this exception:

Exception thrown at 0x00007FF8EED53416 (ntdll.dll) in example_scan.exe: 0xC0000005: Access violation writing location 0x000000FDFDFDFD30.

On the same machine the example works when the Crazyradio has the WinUSB driver installed.

This behavior can be observed using pyusb on python will libusb1 backend as well so it seems to be a problem in libusb1. Oddly enough, visualstudio does not give me a backtrace that touches our code or libusb:
image

In order to use this link implementation from the Crazyflie python lib on Windows we need to get the users to transition from libusb-win32 to WinUSB, for example by displaying an error message if a Crazyradio with libusb-win32 driver is detected. To do so we need to solve this bug.

Builds not working for python 3.10 and 3.11

I tried to bump up the build script to build for python 3.10 and 3.11, but it does not work as expected.
3.10 works on mac and linux, but not on windows. 3.11 does not work on any platform.

Swarm Control & Broadcasting

This discussion is carried over from this forum post

Most of the context for my project is in the forum post above, but I'll summarize here as well:
I've forked this repository (as well as crazyflie-lib-python) with the goal of adding support for broadcasting to multiple drones, similar to the way the crazyswarm project works, and using that to build a swarm controller application. I'm currently running into issues where the drones don't seem to be responding to the broadcasted commands I'm attempting to send.

As mentioned in the forum post, I'm testing with the following setup:

  • Two drones, one at uri radio://0/55/2M/E7E7E7E7E7 and one at radio://0/55/2M/E7E7E7E7E8, both flashed with the latest firmware (including the latest nrf firmware)
  • A Crazyradio PA dongle, flashed with firmware I built from the latest commit on crazyradio-firmware

I'm trying to broadcast to the drones by opening a link at "broadcast address" radio://0/55/2M/FFE7E7E7E7, and sending out high level commander packets for takeoff/land commands, but the drones do not respond to these commands. As I was learning in the forum post, there's a command to enable "noAck" mode for the radio, which I'm likely missing, and opening a link to the broadcast address manually might not be the right way to go about it, so I'm looking for some pointers on what I should be doing to implement this functionality.

Broadcast and console example not working consistently

When running ./example_broadcast_and_console it looks like the broadcasts are not sent out consistently, i.e., the motors often do not start/stop spinning, even though ./example_broadcast works fine. This is even true if #30 is applied. The issue happens more frequently with Crazyradio2 compared to Crazyradio PA.

This is a high-impact issue for Crazyswarm2, which heavily relies on (reliable) broadcasts.

Bootloader very slow when using cpp link

When using the cpp link, bootloading a Crazyflie is very slow:

$ time make cload
Python:
real    0m31.702s
user    0m3.389s
sys     0m1.176s
CPP:
real    4m42.991s
user    0m7.673s
sys     0m18.203s

The behavior seems to come from send packet that can either take 1 seconds or run in quick bursts of ~30 packets. This looks like mutex contension so I tried commenting this mutex lock:

const std::lock_guard<std::mutex> lock(con->queue_send_mutex_);
. Doing so solves the problem, I can then bootloader as fast as with the python link.

Why does this mutex exists? I though there was only one thread accessing each radio which means that radio access would not need to be protected by a lock. I will continue investigating, tell me if you have any though @whoenig.

Warnings when compiling Python bindings on macOS + clang 12.0.0

I'm getting the following warnings while compiling the Python bindings on macOS:

ld: warning: direct access in function 'pybind11_init_cflinkcpp(pybind11::module_&)' from file '/tmp/lto.o' to global weak symbol 'bitcraze::crazyflieLinkCpp::Packet::valid() const' from file 'libcrazyflieLinkCpp.a(Connection.cpp.o)' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in function 'pybind11_init_cflinkcpp(pybind11::module_&)' from file '/tmp/lto.o' to global weak symbol 'bitcraze::crazyflieLinkCpp::Packet::port() const' from file 'libcrazyflieLinkCpp.a(Connection.cpp.o)' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
ld: warning: direct access in function 'char const* std::__1::__find_end<bool (*)(char, char), char const*, char const*>(char const*, char const*, char const*, char const*, bool (*)(char, char), std::__1::random_access_iterator_tag, std::__1::random_access_iterator_tag)' from file '/tmp/lto.o' to global weak symbol 'std::__1::char_traits<char>::eq(char, char)' from file 'libcrazyflieLinkCpp.a(Connection.cpp.o)' means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

The Python bindings seems to work fine, though, at least I could definitely run the console example without problems so I'm not sure this is something to worry about.

Benchmark example does not work for me

When I run the benchmark I seem to end up in an inf. loop.

build$ ./example_benchmark
[never seem to end]

The program never leaves the loop in run():

        // empty receiver queue
        while (true)
        {
            Packet p = con.recv(100);
            if (!p)
            {
                break;
            }
        }

Is there something I am missing? I have changed the address in the source:

 int main()
 {
     // std::vector<std::string> uris({"radio://*/80/2M/E7E7E7E7E7", "radio://*/90/2M/E7E7E7E7E7"});
-    std::vector<std::string> uris({"radio://*/80/2M/E7E7E7E7E7"});
+    std::vector<std::string> uris({"radio://0/80/2M/DEADBEEF"});

Client uses old param API error

Hello bitcraze,
I'm have a crazyflie 2.0 and used this documentation for the basis of the program bellow.

Client uses old param API error

I recieved the message displayed above from the console after trying to get the next toc element using the following code:

Connection con("usb://0");

// empty receiver queue
while (true)
{
    Packet p = con.recv(100);
    if (!p)
    {
        break;
    }
}
Packet p;
p.setPort(2);   
p.setChannel(0); 
int getNextTocElementCode = 1;
p.setPayloadSize(sizeof(uint32_t));
std::memcpy(p.payload(), &getNextTocElementCode, sizeof(getNextTocElementCode));

con.send(p);
Packet p_recv;
do
{
    p_recv = con.recv(0);
    if(p_recv.port()==0)
        std::cout << p_recv.payload() << std::endl;

} while (p_recv.port() != 2);
std::cout << p_recv << std::endl;

The code above is trying to receive an element from the TOC but instead it receives an error which is directed to the console, followed by a packet that doesn't correspond to the protocol stated in the Bitcraze documentation:

Packet(channel=0,port=2,safelinkUp=0,safelinkDown=0,data=1 214 70 138 110 185 ,seq=4)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.