Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(WITH_VISUALIZATION ON CACHE BOOL "Enable Visualization module")
set(WITH_RELATIVE_KINEMATICS OFF CACHE BOOL "Enable RelativeKinematics module")
set(WITH_DIRECT_CONTROL ON CACHE BOOL "Enable DirectControl module")
set(WITH_OBJECT_MONITORING OFF CACHE BOOL "Enable ObjectMonitoring module")
set(WITH_BACK_TO_START ON CACHE BOOL "Enable BackToStart module")

set(ENABLE_TESTS ON CACHE BOOL "Enable testing on build")

Expand Down Expand Up @@ -49,6 +50,9 @@ endif()
if(WITH_OBJECT_MONITORING)
list(APPEND ENABLED_MODULES ObjectMonitoring)
endif()
if(WITH_BACK_TO_START)
list(APPEND ENABLED_MODULES BackToStart)
endif()
if(WITH_RELATIVE_KINEMATICS)
list(APPEND ENABLED_MODULES RelativeKinematics)
set(WITH_OBJECT_CONTROL OFF)
Expand Down
5 changes: 5 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ include(GNUInstallDirs)

add_library(${MAESTRO_COMMON_TARGET} SHARED
${CMAKE_CURRENT_SOURCE_DIR}/trajectory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/objectconfig.cpp
)

target_link_libraries(${MAESTRO_COMMON_TARGET}
Expand All @@ -30,6 +31,10 @@ target_include_directories(${MAESTRO_COMMON_TARGET} PUBLIC
set_property(TARGET ${MAESTRO_COMMON_TARGET} APPEND PROPERTY
PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/trajectory.hpp
)

set_property(TARGET ${MAESTRO_COMMON_TARGET} APPEND PROPERTY
PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/objectconfig.hpp
)
set_property(TARGET ${MAESTRO_COMMON_TARGET} APPEND PROPERTY
PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/regexpatterns.hpp
)
Expand Down
254 changes: 254 additions & 0 deletions common/objectconfig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#include "objectconfig.hpp"
#include "util.h"

ObjectConfig::ObjectConfig() {
origin.latitude_deg = origin.longitude_deg = origin.altitude_m = 0.0;
origin.isLongitudeValid = origin.isLatitudeValid = origin.isAltitudeValid = false;
}

ObjectConfig::ObjectConfig(const ObjectConfig&& other) :
objectFile(other.objectFile),
transmitterID(other.transmitterID),
injectionMap(other.injectionMap),
isAnchorObject(other.isAnchorObject),
isOSICompatible(other.isOSICompatible),
trajectory(other.trajectory),
origin(other.origin)
{

}

std::string ObjectConfig::toString() const {
char ipAddr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ip_addr, ipAddr, sizeof (ipAddr));
std::string retval = "";

std::string idsString;
for(auto id: injectionMap.targetIDs) {
idsString += std::to_string(id) + " ";
}

retval += "Object ID: " + std::to_string(transmitterID)
+ ", IP: " + ipAddr + ", Trajectory: " + trajectory.name.c_str()
+ ", Turning diameter: " + std::to_string(turningDiameter) + ", Max speed: " + std::to_string(maximumSpeed)
+ ", Object file: " + objectFile.filename().string() + ", Anchor: " + (isAnchorObject? "Yes":"No")
+ ", OSI compatible: " + (isOSICompatible? "Yes":"No")
+ ", Injection IDs: " + idsString;
return retval;
}

void ObjectConfig::parseConfigurationFile(
const fs::path &objectFile) {

char setting[100];
int result;
char path[MAX_FILE_PATH];

UtilGetTrajDirectoryPath(path, sizeof (path));

// Get IP setting
if (UtilGetObjectFileSetting(OBJECT_SETTING_IP, objectFile.c_str(),
objectFile.string().length()+1, setting,
sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find IP setting in file " + objectFile.string());
}
result = inet_pton(AF_INET, setting, &this->ip_addr);
if (result == -1) {
using namespace std;
throw system_error(make_error_code(static_cast<errc>(errno)));
}
else if (result == 0) {
throw std::invalid_argument("Address " + std::string(setting)
+ " in object file " + objectFile.string()
+ " is not a valid IPv4 address");
}

// Get ID setting
if (UtilGetObjectFileSetting(OBJECT_SETTING_ID, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find ID setting in file " + objectFile.string());
}
char *endptr;
uint32_t id = static_cast<uint32_t>(strtoul(setting, &endptr, 10));

if (endptr == setting) {
throw std::invalid_argument("ID " + std::string(setting) + " in file "
+ objectFile.string() + " is invalid");
}
this->transmitterID = id;

// Get anchor setting
if (UtilGetObjectFileSetting(OBJECT_SETTING_IS_ANCHOR, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
this->isAnchorObject = false;
}
else {
this->isAnchorObject = this->isSettingTrue(setting);
}

// Get trajectory file setting
if (UtilGetObjectFileSetting(OBJECT_SETTING_TRAJ, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find trajectory setting in file " + objectFile.string());
}

fs::path trajFile(std::string(path) + std::string(setting));
if (!fs::exists(trajFile)) {
throw std::invalid_argument("Configured trajectory file " + std::string(setting)
+ " in file " + objectFile.string() + " not found");
}
this->trajectory.initializeFromFile(setting);
LogMessage(LOG_LEVEL_DEBUG, "Loaded trajectory with %u points", trajectory.points.size());

// Get origin settings
this->origin = {};
if (UtilGetObjectFileSetting(OBJECT_SETTING_ORIGIN_LATITUDE, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) != -1) {
origin.latitude_deg = strtod(setting, &endptr);
if (setting != endptr) {
origin.isLatitudeValid = true;
}
}

if (UtilGetObjectFileSetting(OBJECT_SETTING_ORIGIN_LONGITUDE, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) != -1) {
origin.longitude_deg = strtod(setting, &endptr);
if (setting != endptr) {
origin.isLongitudeValid = true;
}
}

if (UtilGetObjectFileSetting(OBJECT_SETTING_ORIGIN_ALTITUDE, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) != -1) {
origin.altitude_m = strtod(setting, &endptr);
if (setting != endptr) {
origin.isAltitudeValid = true;
}
}

if (origin.isAltitudeValid == origin.isLatitudeValid
&& origin.isLatitudeValid == origin.isLongitudeValid) {
if (!origin.isAltitudeValid) {
GeoPosition orig;
if (UtilReadOriginConfiguration(&orig) != -1) {
this->origin.latitude_deg = orig.Latitude;
this->origin.longitude_deg = orig.Longitude;
this->origin.altitude_m = orig.Altitude;
this->origin.isLatitudeValid = true;
this->origin.isLongitudeValid = true;
this->origin.isAltitudeValid = true;
}
else {
throw std::invalid_argument("No origin setting found");
}
}
}
else {
throw std::invalid_argument("Partial origin setting in file " + objectFile.string());
}

// Get Turning diameter
if (UtilGetObjectFileSetting(OBJECT_SETTING_TURNING_DIAMETER, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find Turning diameter setting in file " + objectFile.string());
}
Comment on lines +157 to +161

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should handle the absence of these parameters in a better way, such as having a variable showing it is unknown or similar, when it is not present in the config file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I agree. Will figure something out.

else {
char *endptr;
double val = strtod(setting, &endptr);

if (endptr == setting) {
throw std::invalid_argument("Turning diameter " + std::string(setting) + " in file "
+ objectFile.string() + " is invalid");
}
this->turningDiameter = val;
}

// Get Maximum speed
if (UtilGetObjectFileSetting(OBJECT_SETTING_MAX_SPEED, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find Max speed setting in file " + objectFile.string());
}
Comment on lines +174 to +178

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

else {
char *endptr;
double val = strtod(setting, &endptr);

if (endptr == setting) {
throw std::invalid_argument("Max speed " + std::string(setting) + " in file "
+ objectFile.string() + " is invalid");
}
this->maximumSpeed = val;
}

// Get OSI compatibility
if (UtilGetObjectFileSetting(OBJECT_SETTING_IS_OSI_COMPATIBLE, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
this->isOSICompatible = false;
}
else {
this->isOSICompatible = this->isSettingTrue(setting);
}

// Get Injector IDs
if (UtilGetObjectFileSetting(OBJECT_SETTING_INJECTOR_IDS, objectFile.c_str(),
objectFile.string().length(),
setting, sizeof (setting)) == -1) {
throw std::invalid_argument("Cannot find Injector IDs setting in file " + objectFile.string());
}
Comment on lines +201 to +205

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The injection map can be initialized to empty if the setting is not found


std::vector<int> ids;
std::string settingString(setting);
this->split(settingString, ',', ids);

this->injectionMap.numberOfTargets = ids.size();
this->injectionMap.sourceID = id;
this->injectionMap.isActive = true;
this->injectionMap.targetIDs.clear();

for (const auto& id : ids) {
LogMessage(LOG_LEVEL_DEBUG, "Injection ID %d", id);
this->injectionMap.targetIDs.push_back(id);
}

this->objectFile = objectFile;
}

template<size_t N>
bool ObjectConfig::isSettingTrue(char (&setting)[N]) {
if (setting[0] == '1' || setting[0] == '0') {
return setting[0] == '1';
}
else {
std::string settingString(setting);
for (char &c : settingString) {
c = std::tolower(c, std::locale());
}
if (settingString.compare("true") == 0) {
return true;
}
else if (settingString.compare("false") == 0) {
return false;
}
else {
throw std::invalid_argument("Setting " + settingString + " is invalid");
}
}
}

void ObjectConfig::split(std::string &str, char delim, std::vector<int> &out) {
size_t start;
size_t end = 0;

while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
end = str.find(delim, start);
out.push_back(stoi(str.substr(start, end - start)));
}
}
56 changes: 56 additions & 0 deletions common/objectconfig.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include <netinet/in.h>
#include "trajectory.hpp"

// GCC version 8.1 brings non-experimental support for std::filesystem
#if __GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ >= 1)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif

struct DataInjectionMap {
uint32_t sourceID;
unsigned int numberOfTargets;
std::vector<uint32_t> targetIDs;
bool isActive;
};

class ObjectConfig {
public:
ObjectConfig();
ObjectConfig(const ObjectConfig&&);

void parseConfigurationFile(const fs::path& file);

bool isAnchor() const { return isAnchorObject; }
bool isOSI() const { return isOSICompatible; }
DataInjectionMap getInjectionMap() const { return injectionMap; }
in_addr_t getIP(void) const { return ip_addr; }
double getMaximumSpeed() const { return maximumSpeed; }
GeographicPositionType getOrigin() const { return origin; }
Trajectory getTrajectory() const { return trajectory; }
uint32_t getTransmitterID() const { return transmitterID; }
double getTurningDiameter() const { return turningDiameter; }

std::string toString() const;

private:
fs::path objectFile;
bool isAnchorObject = false;
bool isOSICompatible = false;
in_addr_t ip_addr = 0;
double maximumSpeed = 0;
GeographicPositionType origin;
Trajectory trajectory;
uint32_t transmitterID = 0;
double turningDiameter = 0;
DataInjectionMap injectionMap;

template<size_t N>
bool isSettingTrue(char (&setting)[N]);
void split(std::string &str, char delim, std::vector<int> &out);
};
5 changes: 3 additions & 2 deletions core/inc/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ enum ObjectFileParameter {
OBJECT_SETTING_ORIGIN_LATITUDE,
OBJECT_SETTING_ORIGIN_LONGITUDE,
OBJECT_SETTING_ORIGIN_ALTITUDE,
OBJECT_SETTING_TURNING_RADIUS,
OBJECT_SETTING_MAX_SPEED
OBJECT_SETTING_TURNING_DIAMETER,
OBJECT_SETTING_MAX_SPEED,
OBJECT_SETTING_IS_OSI_COMPATIBLE
};


Expand Down
10 changes: 7 additions & 3 deletions core/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ static const char ObjectSettingNameInjectorIDs[] = "injectorIDs";
static const char ObjectSettingNameLatitude[] = "originLatitude";
static const char ObjectSettingNameLongitude[] = "originLongitude";
static const char ObjectSettingNameAltitude[] = "originAltitude";
static const char ObjectSettingNameTurningRadius[] = "turningRadius";
static const char ObjectSettingNameTurningDiameter[] = "turningDiameter";
static const char ObjectSettingNameMaxSpeed[] = "maxSpeed";
static const char ObjectSettingNameIsOSI[] = "isOsiCompatible";

/*------------------------------------------------------------
-- Local type definitions
Expand Down Expand Up @@ -3828,12 +3829,15 @@ char *UtilGetObjectParameterAsString(const enum ObjectFileParameter parameter,
case OBJECT_SETTING_ORIGIN_ALTITUDE:
outputString = ObjectSettingNameAltitude;
break;
case OBJECT_SETTING_TURNING_RADIUS:
outputString = ObjectSettingNameTurningRadius;
case OBJECT_SETTING_TURNING_DIAMETER:
outputString = ObjectSettingNameTurningDiameter;
break;
case OBJECT_SETTING_MAX_SPEED:
outputString = ObjectSettingNameMaxSpeed;
break;
case OBJECT_SETTING_IS_OSI_COMPATIBLE:
outputString = ObjectSettingNameIsOSI;
break;
default:
LogMessage(LOG_LEVEL_ERROR, "No matching configuration parameter for enumerated input");
outputString = "";
Expand Down
Loading