Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y liblzma-dev libtinyxml2-dev libjsoncpp-dev libcurl4-openssl-dev libssl-dev libasio-dev libfmt-dev
sudo apt-get install -y liblzma-dev libtinyxml2-dev nlohmann-json3-dev libcurl4-openssl-dev libssl-dev libasio-dev libfmt-dev
- name: Build with system dependencies
run: ./tools/build-with-system-deps.sh
- name: unit tests
Expand All @@ -385,7 +385,8 @@ jobs:
sudo apt-get update && sudo apt-get install -y \
python3-venv \
libasio-dev \
libfmt-dev
libfmt-dev \
nlohmann-json3-dev
- name: git permission workaround
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
Expand Down
52 changes: 0 additions & 52 deletions cpp/cmake/Modules/common/Findjsoncpp.cmake

This file was deleted.

4 changes: 2 additions & 2 deletions cpp/debian/control
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Source: mavsdk
Priority: optional
Maintainer: hcb <hcb@archaeopteryx>
Build-Depends: debhelper (>= 11), libjsoncpp-dev, libcurl4-openssl-dev, libtinyxml2-dev
Build-Depends: debhelper (>= 11), nlohmann-json3-dev, libcurl4-openssl-dev, libtinyxml2-dev
Standards-Version: 4.1.3
Section: libs
Homepage: https://mavsdk.mavlink.io/main/en/index.html
Expand All @@ -19,6 +19,6 @@ Description: MAVSDK API for Mavlink-controlled vehicles
Package: libmavsdk0
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}, libjsoncpp1, libcurl4, libtinyxml2-6a
Depends: ${shlibs:Depends}, ${misc:Depends}, libcurl4, libtinyxml2-6a
Description: MAVSDK API for Mavlink-controlled vehicles
This provides the runtime libraries for the mavsdk C++ library.
2 changes: 1 addition & 1 deletion cpp/examples/mavlink_direct_sender/sender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ int main(int argc, char** argv)
// On 3 segments we see an obstacle, the closest is at 7m.
//
// In a real application this JSON message content would of course be
// assembled manually, or using a json library like jsoncpp or nlohmann/json.
// assembled manually, or using a json library like nlohmann/json.
obstacle_distance.fields_json = R"({
"time_usec": 12345678,
"sensor_type": 3,
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/MAVSDKConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if(NOT @BUILD_SHARED_LIBS@)
endif()

find_dependency(Threads REQUIRED)
find_dependency(jsoncpp REQUIRED)
find_dependency(nlohmann_json REQUIRED)
find_dependency(picosha2 REQUIRED)
find_dependency(tinyxml2 REQUIRED)
find_dependency(mav REQUIRED)
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/mavsdk.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: MAVSDK
Description: API and library for MAVLink compatible systems written in C++17
Version: @MAVSDK_VERSION_STRING@
Requires.private: libcurl jsoncpp tinyxml2
Requires.private: libcurl nlohmann_json tinyxml2
Libs: -L"${libdir}" -lmavsdk
Cflags: -I"${includedir}" -I"${includedir}/mavsdk"
4 changes: 2 additions & 2 deletions cpp/src/mavsdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ add_library(mavsdk)

cmake_policy(SET CMP0076 NEW)

find_package(jsoncpp REQUIRED)
find_package(nlohmann_json REQUIRED)

find_package(tinyxml2 REQUIRED)

Expand All @@ -16,7 +16,7 @@ target_link_libraries(mavsdk
PUBLIC
${CMAKE_DL_LIBS}
PRIVATE
JsonCpp::JsonCpp
nlohmann_json::nlohmann_json
tinyxml2::tinyxml2
LibEvents::LibEvents
mav::mav
Expand Down
116 changes: 57 additions & 59 deletions cpp/src/mavsdk/core/libmav_conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "log.hpp"

#include <mav/Message.h>
#include <json/json.h>
#include <nlohmann/json.hpp>
#include <cmath>
#include <limits>
#include <vector>
Expand All @@ -12,34 +12,34 @@ namespace mavsdk {

bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
{
Json::Value json;
Json::Reader reader;
// Parse without exceptions (MAVSDK is built with -fno-exceptions); a parse
// error yields a discarded value instead of throwing.
auto json = nlohmann::json::parse(json_string, nullptr, false);

if (!reader.parse(json_string, json)) {
if (json.is_discarded() || !json.is_object()) {
LogErr("Failed to parse JSON: {}", json_string);
return false;
}

// Iterate through all JSON fields and set them in the libmav message
for (const auto& field_name : json.getMemberNames()) {
const Json::Value& field_value = json[field_name];

for (const auto& [field_name, field_value] : json.items()) {
// Convert JSON values to appropriate types and set in message
// libmav handles type casting based on field definition, so we just need to pass
// int64/uint64
if (field_value.isInt() || field_value.isInt64()) {
int64_t value = field_value.asInt64();
// int64/uint64. Check unsigned first since nlohmann stores non-negative
// integer literals as unsigned.
if (field_value.is_number_unsigned()) {
uint64_t value = field_value.get<uint64_t>();
auto result = msg.set(field_name, value);
if (result != ::mav::MessageResult::Success) {
LogWarn("Failed to set integer field {} = {}", field_name, value);
LogWarn("Failed to set unsigned integer field {} = {}", field_name, value);
}
} else if (field_value.isUInt() || field_value.isUInt64()) {
uint64_t value = field_value.asUInt64();
} else if (field_value.is_number_integer()) {
int64_t value = field_value.get<int64_t>();
auto result = msg.set(field_name, value);
if (result != ::mav::MessageResult::Success) {
LogWarn("Failed to set unsigned integer field {} = {}", field_name, value);
LogWarn("Failed to set integer field {} = {}", field_name, value);
}
} else if (field_value.isNull() || field_value.isDouble()) {
} else if (field_value.is_null() || field_value.is_number_float()) {
// Handle float/double values (including null -> NaN)
auto field_opt = msg.type().getField(field_name);
if (!field_opt) {
Expand All @@ -51,16 +51,16 @@ bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
::mav::MessageResult result = ::mav::MessageResult::FieldNotFound;

if (field.type.base_type == ::mav::FieldType::BaseType::FLOAT) {
if (field_value.isNull()) {
if (field_value.is_null()) {
result = msg.set(field_name, std::numeric_limits<float>::quiet_NaN());
} else {
result = msg.set(field_name, static_cast<float>(field_value.asFloat()));
result = msg.set(field_name, field_value.get<float>());
}
} else if (field.type.base_type == ::mav::FieldType::BaseType::DOUBLE) {
if (field_value.isNull()) {
if (field_value.is_null()) {
result = msg.set(field_name, std::numeric_limits<double>::quiet_NaN());
} else {
result = msg.set(field_name, field_value.asDouble());
result = msg.set(field_name, field_value.get<double>());
}
} else {
LogWarn("Field {} is not a float or double field", field_name);
Expand All @@ -71,14 +71,15 @@ bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
LogWarn(
"Failed to set float/double field {} = {}",
field_name,
(field_value.isNull() ? "null" : std::to_string(field_value.asDouble())));
(field_value.is_null() ? "null" : std::to_string(field_value.get<double>())));
}
} else if (field_value.isString()) {
auto result = msg.setString(field_name, field_value.asString());
} else if (field_value.is_string()) {
auto value = field_value.get<std::string>();
auto result = msg.setString(field_name, value);
if (result != ::mav::MessageResult::Success) {
LogWarn("Failed to set string field {} = {}", field_name, field_value.asString());
LogWarn("Failed to set string field {} = {}", field_name, value);
}
} else if (field_value.isArray()) {
} else if (field_value.is_array()) {
// Handle array fields with proper type detection
auto array_size = field_value.size();

Expand All @@ -101,91 +102,89 @@ bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
case ::mav::FieldType::BaseType::UINT8: {
std::vector<uint8_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<uint8_t>(elem.asUInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<uint8_t>(elem.get<uint64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::UINT16: {
std::vector<uint16_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<uint16_t>(elem.asUInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<uint16_t>(elem.get<uint64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::UINT32: {
std::vector<uint32_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<uint32_t>(elem.asUInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<uint32_t>(elem.get<uint64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::UINT64: {
std::vector<uint64_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
for (const auto& elem : field_value) {
vec.push_back(
elem.isNumeric() ? static_cast<uint64_t>(elem.asUInt64()) : 0);
elem.is_number() ? static_cast<uint64_t>(elem.get<uint64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::INT8: {
std::vector<int8_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<int8_t>(elem.asInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<int8_t>(elem.get<int64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::INT16: {
std::vector<int16_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<int16_t>(elem.asInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<int16_t>(elem.get<int64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::INT32: {
std::vector<int32_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<int32_t>(elem.asInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<int32_t>(elem.get<int64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::INT64: {
std::vector<int64_t> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<int64_t>(elem.asInt64()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<int64_t>(elem.get<int64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
}
case ::mav::FieldType::BaseType::FLOAT: {
std::vector<float> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
if (elem.isNumeric()) {
vec.push_back(static_cast<float>(elem.asFloat()));
for (const auto& elem : field_value) {
if (elem.is_number()) {
vec.push_back(elem.get<float>());
} else {
// For non-numeric values (including null), use NaN
vec.push_back(std::numeric_limits<float>::quiet_NaN());
Expand All @@ -197,10 +196,9 @@ bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
case ::mav::FieldType::BaseType::DOUBLE: {
std::vector<double> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
if (elem.isNumeric()) {
vec.push_back(elem.asDouble());
for (const auto& elem : field_value) {
if (elem.is_number()) {
vec.push_back(elem.get<double>());
} else {
// For non-numeric values (including null), use NaN
vec.push_back(std::numeric_limits<double>::quiet_NaN());
Expand All @@ -212,9 +210,9 @@ bool json_to_libmav_message(const std::string& json_string, mav::Message& msg)
case ::mav::FieldType::BaseType::CHAR: {
std::vector<char> vec;
vec.reserve(array_size);
for (Json::ArrayIndex i = 0; i < array_size; ++i) {
const auto& elem = field_value[i];
vec.push_back(elem.isNumeric() ? static_cast<char>(elem.asInt()) : 0);
for (const auto& elem : field_value) {
vec.push_back(
elem.is_number() ? static_cast<char>(elem.get<int64_t>()) : 0);
}
result = msg.set(field_name, vec);
break;
Expand Down
Loading
Loading