Skip to content

Commit

Permalink
add nested array
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-du-car committed Aug 12, 2024
1 parent c0a8838 commit 14de679
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 98 deletions.
15 changes: 15 additions & 0 deletions src/tmx/Messages/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,18 @@ SET (TMXMESSAGES_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
INSTALL (DIRECTORY include
DESTINATION . COMPONENT ${PROJECT_NAME}
FILES_MATCHING PATTERN "*.h*")

#############
## Testing ##
#############
enable_testing()

set(BINARY ${PROJECT_NAME}_test)

file(GLOB_RECURSE TEST_SOURCES LIST_DIRECTORIES false test/*.h test/*.cpp)

add_executable(${BINARY} ${TEST_SOURCES})

add_test(NAME ${BINARY} COMMAND ${BINARY})

target_link_libraries(${BINARY} PUBLIC ${TMXAPI_LIBRARIES} gtest)
8 changes: 4 additions & 4 deletions src/tmx/Messages/include/Covariance.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ namespace tmx
namespace messages
{
typedef struct Covariance{
std::string value;
double value;
Covariance(){};
Covariance( std::string value):value(value){};
Covariance(double value):value(value){};
static message_tree_type to_tree(const Covariance& cov){
message_tree_type tree;
tree.put("", cov.value);
tree.put("",cov.value);
return tree;
}
static Covariance from_tree(const message_tree_type& tree){
Covariance cov;
cov.value = tree.get<std::string>("");
cov.value = tree.get<double>("");
return cov;
}
} Covariance;
Expand Down
28 changes: 14 additions & 14 deletions src/tmx/Messages/include/SensorDetectedObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,34 @@ namespace tmx

// TODO: Convert this member variable to std::attributes and handle nested object and arrays. (see [CloudHeartbeatMessage.h](./CloudHearbeatMessage.h) array_attribute )
//Flag to indicate whether sensor detected object is simulated.
std_attribute(this->msg, bool, ISSimulated, false,);
std_attribute(this->msg, bool, isSimulated, false,);
// Classification of detected object.
std_attribute(this->msg, std::string, Type, "",);
std_attribute(this->msg, std::string, type, "",);
// Confidence of type classification
std_attribute(this->msg, double, Confidence, 0.0,);
std_attribute(this->msg, double, confidence, 0.0,);
// Unique indentifier of sensor reporting detection.
std_attribute(this->msg, std::string, SensorId, "", );
std_attribute(this->msg, std::string, sensorId, "", );
// String describing projection used to convert cartesian data to WGS84 data.
std_attribute(this->msg, std::string, ProjString, "", );
std_attribute(this->msg, std::string, projString, "", );
// Unique identifier of detected object.
std_attribute(this->msg, int, ObjectId, 0, );
std_attribute(this->msg, int, objectId, 0, );


object_attribute(Position, Position);
array_attribute(Covariance, PositionCovariance);
object_attribute(Position, position);
two_dimension_array_attribute(Covariance, positionCovariance);
//Linear velocity in meter per second
object_attribute(Velocity, Velocity);
object_attribute(Velocity, velocity);
//Covariance associated with linear velocity.
array_attribute(Covariance, VelocityCovariance);
two_dimension_array_attribute(Covariance, velocityCovariance);
//Angular velocity in radians per second.
object_attribute(Velocity, AngularVelocity);
object_attribute(Velocity, angularVelocity);
//Covariance associated with angular velocity.
array_attribute(Covariance, AngularVelocityCovariance);
two_dimension_array_attribute(Covariance, angularVelocityCovariance);

// Epoch time in milliseconds.
// long timestamp = 0;
std_attribute(this->msg, long, Timestamp, 0, );
object_attribute(Size, Size);
std_attribute(this->msg, long, timestamp, 0, );
object_attribute(Size, size);

};

Expand Down
108 changes: 108 additions & 0 deletions src/tmx/Messages/test/SensorDetectedObjectTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <gtest/gtest.h>
#include "SensorDetectedObject.h"

namespace tmx::messages{
class SensorDetectedObjectTest : public testing::Test{
protected:
std::shared_ptr<SensorDetectedObject> tmxSdsmPtr;
SensorDetectedObjectTest(){
tmxSdsmPtr = std::make_shared<SensorDetectedObject>();
}
void SetUp() override {
tmxSdsmPtr->set_isSimulated(false);
Position pos(1.0, 2.3, 2.0);
tmxSdsmPtr->set_position(pos);
tmxSdsmPtr->set_projString("+proj=tmerc +lat_0=38.95197911150576 +lon_0=-77.14835128349988 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +geoidgrids=egm96_15.gtx +vunits=m +no_defs");
tmxSdsmPtr->set_timestamp(12222222222);
tmxSdsmPtr->set_sensorId("SomeID");
tmxSdsmPtr->set_type("Car");
tmxSdsmPtr->set_confidence(0.7);
tmxSdsmPtr->set_objectId(123);

Velocity vel(1.0, 0.3, 2.0);
tmxSdsmPtr->set_velocity(vel);
tmxSdsmPtr->set_angularVelocity(vel);

std::vector<Covariance> covs {
Covariance(12),
Covariance(11),
Covariance(13),
Covariance(14),
Covariance(15)
};
int covarianceSize = 3;
std::vector<std::vector<Covariance>> covs2d;
for(int i=0; i<covarianceSize; i++){
covs2d.push_back(covs);
}
tmxSdsmPtr->set_positionCovariance(covs2d);
tmxSdsmPtr->set_velocityCovariance(covs2d);
tmxSdsmPtr->set_angularVelocityCovariance(covs2d);
}
};

TEST_F(SensorDetectedObjectTest, attributes){
EXPECT_EQ(false, tmxSdsmPtr->get_isSimulated());
EXPECT_EQ(0.7, tmxSdsmPtr->get_confidence());
EXPECT_EQ("SomeID", tmxSdsmPtr->get_sensorId());
EXPECT_EQ(12222222222, tmxSdsmPtr->get_timestamp());
EXPECT_EQ(123, tmxSdsmPtr->get_objectId());
EXPECT_EQ("+proj=tmerc +lat_0=38.95197911150576 +lon_0=-77.14835128349988 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +geoidgrids=egm96_15.gtx +vunits=m +no_defs", tmxSdsmPtr->get_projString());
EXPECT_EQ(1.0, tmxSdsmPtr->get_position().x);
EXPECT_NEAR(2.3, tmxSdsmPtr->get_position().y, 0.01);
EXPECT_EQ(2.0, tmxSdsmPtr->get_position().z);
EXPECT_EQ(1.0, tmxSdsmPtr->get_velocity().x);
EXPECT_NEAR(0.3, tmxSdsmPtr->get_velocity().y, 0.01);
EXPECT_EQ(2.0, tmxSdsmPtr->get_velocity().z);
EXPECT_EQ(1.0, tmxSdsmPtr->get_angularVelocity().x);
EXPECT_NEAR(0.3, tmxSdsmPtr->get_angularVelocity().y, 0.01);
EXPECT_EQ(2.0, tmxSdsmPtr->get_angularVelocity().z);
EXPECT_EQ(3, tmxSdsmPtr->get_positionCovariance().size());
EXPECT_EQ(3, tmxSdsmPtr->get_angularVelocityCovariance().size());
EXPECT_EQ(3, tmxSdsmPtr->get_velocityCovariance().size());
}

TEST_F(SensorDetectedObjectTest, to_string){
std::string expectedStr = "{\"isSimulated\":\"0\",\"position\":{\"x\":\"1\",\"y\":\"2.2999999999999998\",\"z\":\"2\"},\"projString\":\"+proj=tmerc +lat_0=38.95197911150576 +lon_0=-77.14835128349988 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +geoidgrids=egm96_15.gtx +vunits=m +no_defs\",\"timestamp\":\"12222222222\",\"sensorId\":\"SomeID\",\"type\":\"Car\",\"confidence\":\"0.69999999999999996\",\"objectId\":\"123\",\"velocity\":{\"x\":\"1\",\"y\":\"0.29999999999999999\",\"z\":\"2\"},\"angularVelocity\":{\"x\":\"1\",\"y\":\"0.29999999999999999\",\"z\":\"2\"},\"positionCovariance\":[[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"]],\"velocityCovariance\":[[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"]],\"angularVelocityCovariance\":[[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"],[\"12\",\"11\",\"13\",\"14\",\"15\"]]}\n";
EXPECT_EQ(expectedStr, tmxSdsmPtr->to_string());
}

TEST_F(SensorDetectedObjectTest, deserialize){
auto tmxSdsmPtr2 = std::make_shared<SensorDetectedObject>();
std::string expectedStr = "{\"isSimulated\":1,\"type\":\"CAR\",\"confidence\":1.0,\"sensorId\":\"IntersectionLidar\",\"projString\":\"+proj=tmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +geoidgrids=egm96_15.gtx +vunits=m +no_defs\",\"objectId\":207,\"position\":{\"x\":-5.021,\"y\":64.234,\"z\":-10.297},\"positionCovariance\":[[0.04000000000000001,0.0,0.0],[0.0,0.04000000000000001,0.0],[0.0,0.0,0.04000000000000001]],\"velocity\":{\"x\":0.0,\"y\":0.0,\"z\":0.0},\"velocityCovariance\":[[0.04000000000000001,0.0,0.0],[0.0,0.04000000000000001,0.0],[0.0,0.0,0.04000000000000001]],\"angularVelocity\":{\"x\":0.0,\"y\":-0.0,\"z\":-0.0},\"angularVelocityCovariance\":[[0.010000000000000002,0.0,0.0],[0.0,0.010000000000000002,0.0],[0.0,0.0,0.010000000000000002]],\"size\":{\"length\":2.257,\"height\":1.003,\"width\":0.762},\"timestamp\":110200}";
tmxSdsmPtr2->set_contents(expectedStr);
EXPECT_EQ(expectedStr, tmxSdsmPtr2->to_string());
EXPECT_EQ(true, tmxSdsmPtr2->get_isSimulated());
EXPECT_EQ(-5.021, tmxSdsmPtr2->get_position().x);
EXPECT_NEAR(64.234, tmxSdsmPtr2->get_position().y, 0.01);
EXPECT_EQ(-10.297, tmxSdsmPtr2->get_position().z);
EXPECT_EQ("CAR", tmxSdsmPtr2->get_type());
EXPECT_EQ(1.0, tmxSdsmPtr2->get_confidence());
EXPECT_EQ("IntersectionLidar", tmxSdsmPtr2->get_sensorId());
EXPECT_EQ("+proj=tmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +geoidgrids=egm96_15.gtx +vunits=m +no_defs", tmxSdsmPtr2->get_projString());
EXPECT_EQ(207, tmxSdsmPtr2->get_objectId());
EXPECT_EQ(0.0, tmxSdsmPtr2->get_velocity().x);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_velocity().y);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_velocity().z);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_angularVelocity().x);
EXPECT_EQ(-0.0, tmxSdsmPtr2->get_angularVelocity().y);
EXPECT_EQ(-0.0, tmxSdsmPtr2->get_angularVelocity().z);
EXPECT_EQ(2.257, tmxSdsmPtr2->get_size().length);
EXPECT_EQ(1.003, tmxSdsmPtr2->get_size().height);
EXPECT_EQ(0.762, tmxSdsmPtr2->get_size().width);
EXPECT_EQ(110200, tmxSdsmPtr2->get_timestamp());

EXPECT_EQ(3, tmxSdsmPtr2->get_positionCovariance().size());
EXPECT_EQ(3, tmxSdsmPtr2->get_angularVelocityCovariance().size());
EXPECT_EQ(3, tmxSdsmPtr2->get_velocityCovariance().size());

EXPECT_NEAR(0.04,tmxSdsmPtr2->get_positionCovariance().begin()->begin()->value, 0.0001);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_positionCovariance().begin()->back().value);

EXPECT_NEAR(0.04, tmxSdsmPtr2->get_velocityCovariance().begin()->begin()->value, 0.0001);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_velocityCovariance().begin()->back().value);

EXPECT_NEAR(0.01, tmxSdsmPtr2->get_angularVelocityCovariance().begin()->begin()->value, 0.0001);
EXPECT_EQ(0.0, tmxSdsmPtr2->get_angularVelocityCovariance().begin()->back().value);
}
}
2 changes: 1 addition & 1 deletion src/tmx/Messages/test/TestTimeSyncMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace tmx::messages {

TEST(TestTimeSyncMessage, to_string) {
TimeSyncMessage msg(20, 30);
std::string json = "{ \"timestep\":20, \"seq\":30}";
std::string json = "{\"timestep\":\"20\",\"seq\":\"30\"}\n";
EXPECT_EQ( json, msg.to_string());
}
}
64 changes: 64 additions & 0 deletions src/tmx/TmxApi/tmx/messages/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
void add_to_##NAME(ELEMENT element) { add_array_element<ELEMENT>(#NAME, element); } \
void erase_##NAME() { erase_array(#NAME); }


#define two_dimension_array_attribute(ELEMENT, NAME) \
std::vector<std::vector<ELEMENT>> get_##NAME () { return get_two_dimension_array<ELEMENT>(#NAME); } \
void set_##NAME(std::vector<std::vector<ELEMENT>> array) { return set_two_dimension_array<ELEMENT>(#NAME, array); }

#define object_attribute(ELEMENT, NAME) \
ELEMENT get_##NAME() {return get_object<ELEMENT>(#NAME); } \
void set_##NAME(ELEMENT obj) {return set_object<ELEMENT>(#NAME, obj); } \
Expand Down Expand Up @@ -407,6 +412,65 @@ class tmx_message {
tree.get().push_back(typename message_tree_type::value_type("", Element::to_tree(element)));
}

/**
* Get the entire contents of a two dimension array field as a vector.
* Note that the template Element type must contain methods with the following signatures:
* - static Element from_tree(message_tree_type&)
* - static message_tree_type to_tree(Element element)
* @param The name of the array field.
* @returns A two dimension array of all array elements.
*/
template <class Element>
std::vector<std::vector<Element>> get_two_dimension_array(std::string arrayName)
{
std::vector<std::vector<Element>> ret;
boost::optional<boost::property_tree::ptree&> tree = this->as_tree(arrayName);
if(tree)
{
for(auto& outer_pair: tree.get()){
std::vector<Element> temp;
for(auto& inner_pair: outer_pair.second){
Element element = Element::from_tree(inner_pair.second);
temp.push_back(element);
}
ret.push_back(temp);
}
}
return ret;
}

/**
* Set the entire contents of a two dimension array field.
* Note that the template Element type must contain methods with the following signatures:
* - static Element from_tree(message_tree_type&)
* - static message_tree_type to_tree(Element element)
* @param The name of the array field.
* @param array A two dimenstion array containing all elements to set.
*/
template <class Element>
void set_two_dimension_array(std::string arrayName, std::vector<std::vector<Element>> array)
{
erase_array(arrayName);
boost::optional<boost::property_tree::ptree &> tree = this->as_tree(arrayName);
if (!tree)
{
// Add the empty array
message_tree_type emptyTree;
this->as_tree().get().add_child(arrayName, emptyTree);
tree = this->as_tree(arrayName);
}

for(auto& nested_array: array){
boost::property_tree::ptree subtree;
//Populate nested array
for(auto& element: nested_array){
subtree.push_back(typename message_tree_type::value_type("", Element::to_tree(element)));
}
//Add nested array
tree.get().push_back(typename message_tree_type::value_type("", subtree));
}
}

/***
* @brief Get the content of an object fields
* @param Name of the object
Expand Down
79 changes: 0 additions & 79 deletions src/tmx/TmxUtils/test/SensorDetectedObjectTest.cpp

This file was deleted.

0 comments on commit 14de679

Please sign in to comment.