eProsima / Fast-CDR

eProsima FastCDR library provides two serialization mechanisms. One is the standard CDR serialization mechanism, while the other is a faster implementation of it. Looking for commercial support? Contact info@eprosima.com
Apache License 2.0
142 stars 100 forks source link

FastCdr cannot deserialize PointCloud2 #236

Closed Heyangq closed 3 weeks ago

Heyangq commented 3 weeks ago

This is my main:

int main() { sensor_msgs::msg::PointCloud2 msg; msg.header().frame_id("map"); msg.height(1); msg.width(20000); sensor_msgs::msg::PointField field_x; field_x.name("x"); field_x.offset(0); field_x.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_x.count(1); sensor_msgs::msg::PointField field_y; field_y.name("y"); field_y.offset(4); field_y.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_y.count(1); sensor_msgs::msg::PointField field_z; field_z.name("z"); field_z.offset(8); field_z.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_z.count(1); msg.fields({field_x, field_y, field_z}); msg.is_bigendian(false); msg.point_step(12); msg.row_step(msg.point_step() msg.width()); msg.is_dense(true); std::vector points; float point_x=0.0, point_y=0.0, point_z=0.0; for(int i=0; i<20000; ++i) { point_x += 0.01; point_y += 0.01; point_z += 0.01; points.push_back(point_x); points.push_back(point_y); points.push_back(point_z); } msg.data().resize(points.size() sizeof(float)); memcpy(&msg.data()[0], &points[0], msg.data().size());

eprosima::fastcdr::CdrSizeCalculator cal(eprosima::fastcdr::CdrVersion::XCDRv2); size_t current_alignment = 0; auto size = calculate_serialized_size(cal, msg, current_alignment);

char* buffer = new char[size+10]; eprosima::fastcdr::FastBuffer fast_buffer(buffer, size+10); eprosima::fastcdr::Cdr cdr(fast_buffer); serialize(cdr, msg);

sensor_msgs::msg::PointCloud2 msg2; deserialize(cdr, msg2); std::cout << msg2.data().size() << std::endl; delete[] buffer; return 0; }

I used fastddsgen to generate PointCloud2CdrAux

// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.

/*!

ifndef _FAST_DDS_GENERATED_SENSOR_MSGS_MSG_POINTCLOUD2CDRAUXIPP

define _FAST_DDS_GENERATED_SENSOR_MSGS_MSG_POINTCLOUD2CDRAUXIPP

include "PointCloud2CdrAux.hpp"

include <fastcdr/Cdr.h>

include <fastcdr/CdrSizeCalculator.hpp>

include <fastcdr/exceptions/BadParamException.h>

using namespace eprosima::fastcdr::exception;

namespace eprosima { namespace fastcdr {

template<> eProsima_user_DllExport size_t calculate_serialized_size( eprosima::fastcdr::CdrSizeCalculator& calculator, const sensor_msgs::msg::PointCloud2& data, size_t& current_alignment) { using namespace sensor_msgs::msg;

static_cast<void>(data);

eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
                            eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
                            eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
                            eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
                            current_alignment)};

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
            data.header(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
            data.height(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2),
            data.width(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(3),
            data.fields(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(4),
            data.is_bigendian(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(5),
            data.point_step(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(6),
            data.row_step(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(7),
            data.data(), current_alignment);

    calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(8),
            data.is_dense(), current_alignment);

calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);

return calculated_size;

}

template<> eProsima_user_DllExport void serialize( eprosima::fastcdr::Cdr& scdr, const sensor_msgs::msg::PointCloud2& data) { using namespace sensor_msgs::msg;

eprosima::fastcdr::Cdr::state current_state(scdr);
scdr.begin_serialize_type(current_state,
        eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
        eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
        eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);

scdr
    << eprosima::fastcdr::MemberId(0) << data.header()
    << eprosima::fastcdr::MemberId(1) << data.height()
    << eprosima::fastcdr::MemberId(2) << data.width()
    << eprosima::fastcdr::MemberId(3) << data.fields()
    << eprosima::fastcdr::MemberId(4) << data.is_bigendian()
    << eprosima::fastcdr::MemberId(5) << data.point_step()
    << eprosima::fastcdr::MemberId(6) << data.row_step()
    << eprosima::fastcdr::MemberId(7) << data.data()
    << eprosima::fastcdr::MemberId(8) << data.is_dense()

; scdr.end_serialize_type(current_state); }

template<> eProsima_user_DllExport void deserialize( eprosima::fastcdr::Cdr& cdr, sensor_msgs::msg::PointCloud2& data) { using namespace sensor_msgs::msg;

cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
        eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
        eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
        [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
        {
            bool ret_value = true;
            switch (mid.id)
            {
                                    case 0:
                                            dcdr >> data.header();
                                        break;

                                    case 1:
                                            dcdr >> data.height();
                                        break;

                                    case 2:
                                            dcdr >> data.width();
                                        break;

                                    case 3:
                                            dcdr >> data.fields();
                                        break;

                                    case 4:
                                            dcdr >> data.is_bigendian();
                                        break;

                                    case 5:
                                            dcdr >> data.point_step();
                                        break;

                                    case 6:
                                            dcdr >> data.row_step();
                                        break;

                                    case 7:
                                            dcdr >> data.data();
                                        break;

                                    case 8:
                                            dcdr >> data.is_dense();
                                        break;

                default:
                    ret_value = false;
                    break;
            }
            return ret_value;
        });

}

void serialize_key( eprosima::fastcdr::Cdr& scdr, const sensor_msgs::msg::PointCloud2& data) { using namespace sensor_msgs::msg;

static_cast<void>(scdr);
static_cast<void>(data);

}

} // namespace fastcdr } // namespace eprosima

endif // _FAST_DDS_GENERATED_SENSOR_MSGS_MSG_POINTCLOUD2CDRAUXIPP

Serialization is normal, but my deserialization failed, I hope to get to the root of the problem, thanks!

Heyangq commented 3 weeks ago

If I'm doing this as a wrong example, I want to have a correct example that will allow me to serialize and deserialize PointCloud2

Heyangq commented 3 weeks ago

auto size = calculate_serialized_size(cal, msg, current_alignment);

char* buffer = new char[size+10]; eprosima::fastcdr::FastBuffer fast_buffer(buffer, size+10); eprosima::fastcdr::Cdr cdr(fast_buffer); serialize(cdr, msg);

When my buffer does not use size+10, but uses the calculated size, he will report an error, why?

terminate called after throwing an instance of 'eprosima::fastcdr::exception::NotEnoughMemoryException' what(): Not enough memory in the buffer stream Aborted (core dumped)

It only fires when deserialize, and my serialization uses (FastBuffer = size) as normal

Heyangq commented 3 weeks ago

I found my problem rest is required after serialization, sorry int main() { sensor_msgs::msg::PointCloud2 msg; msg.header().frame_id("map"); msg.height(1); msg.width(20000); sensor_msgs::msg::PointField field_x; field_x.name("x"); field_x.offset(0); field_x.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_x.count(1); sensor_msgs::msg::PointField field_y; field_y.name("y"); field_y.offset(4); field_y.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_y.count(1); sensor_msgs::msg::PointField field_z; field_z.name("z"); field_z.offset(8); field_z.datatype(sensor_msgs::msg::PointField_Constants::FLOAT32); field_z.count(1); msg.fields({field_x, field_y, field_z}); msg.is_bigendian(false); msg.point_step(12); msg.row_step(msg.point_step() msg.width()); msg.is_dense(true); std::vector points; float point_x=0.0, point_y=0.0, point_z=0.0; for(int i=0; i<20000; ++i) { point_x += 0.01; point_y += 0.01; point_z += 0.01; points.push_back(point_x); points.push_back(point_y); points.push_back(point_z); } msg.data().resize(points.size() sizeof(float)); memcpy(&msg.data()[0], &points[0], msg.data().size());

eprosima::fastcdr::CdrSizeCalculator cal(eprosima::fastcdr::CdrVersion::XCDRv2); size_t current_alignment = 0; auto size = calculate_serialized_size(cal, msg, current_alignment);

char* buffer = new char[size]; eprosima::fastcdr::FastBuffer fast_buffer(buffer, size); eprosima::fastcdr::Cdr cdr(fast_buffer); serialize(cdr, msg); /////////////////////////////////// cdr.reset(); ///////////////////////////////////

sensor_msgs::msg::PointCloud2 msg2; deserialize(cdr, msg2); std::cout << msg2.data().size() << std::endl; delete[] buffer; return 0; }