Is it possible to convert from a json to a structure with boost-json,
boost-describe if some fields are missing in the json or it has some extra
unneeded fields. In other words to make the json parser a bit more flexible.
The example is taken from https://www.boost.org/doc/libs/1_81_0/libs/describe/doc/html/describe.html#example_from_json with some modification and the templates are removed as I understood they are part of the headers right now.
Here is the code example:
#include <iostream>
#include <boost/describe.hpp>
#include <boost/json/src.hpp>
using namespace std;
struct A {
optional<int> x;
optional<string> y;
};
BOOST_DESCRIBE_STRUCT(A, (), (x, y))
int main()
{
try {
auto json_val = boost::json::parse(R"({"x":5,"y":"Hello world!"})");
auto a = boost::json::value_to<A>(json_val);
cout << "a.x=" << *a.x << ", a1.y=" << *a.y << endl;
}
catch (exception& e) {
cout << e.what() << endl;
}
// error
try {
auto json_val = boost::json::parse(R"({"x":5})");
auto a = boost::json::value_to<A>(json_val); // << exception is here
cout << "a.x=" << *a.x << endl;
}
catch (exception& e) {
cout << e.what() << endl;
}
// error
try {
auto json_val =
boost::json::parse(R"({"x":5,"y":"Hello world!","z":3.1})");
auto a = boost::json::value_to<A>(json_val); // << exception is here
cout << "a.x=" << *a.x << ", a1.y=" << *a.y << endl;
}
catch (exception& e) {
cout << e.what() << endl;
}
}
the output is
[it#test-dev refl1]$ make
g++ -g -O0 -std=c++20 -I/home/it/Snb/boost/1.81.0/include -c -o test1.o test1.cpp
g++ -o test1 test1.o
[it#test-dev refl1]$ ./test1
a.x=5, a1.y=Hello world!
array size does not match target size [boost.json:31 at /home/it/Snb/boost/1.81.0/include/boost/json/detail/value_to.hpp:533:9 in function 'boost::json::result<T> boost::json::detail::value_to_impl(boost::json::try_value_to_tag<T>, const boost::json::value&, boost::json::detail::described_class_conversion_tag)']
array size does not match target size [boost.json:31 at /home/it/Snb/boost/1.81.0/include/boost/json/detail/value_to.hpp:533:9 in function 'boost::json::result<T> boost::json::detail::value_to_impl(boost::json::try_value_to_tag<T>, const boost::json::value&, boost::json::detail::described_class_conversion_tag)']
I want to use fast-rtps to publish video(streams data) to subscriber. While I publish ten consecutive jpg file successfully, every picture received by subscriber wastes a lot of time to processing because I use function get_byte_value get a pixel one by one.
Do anyone know how to publish and subscribe more efficiently by fast-rtps midleware? (Create a new type? other?)
Below is my publisher's and subscriber's code:
Publisher.cpp
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// Hpshboss modifys code from eprosima's github example;
// Licensed under the Apache License, Version 2.0 (the "License");
/**
* #file PicturePublisher.cpp
*
*/
#include "Publisher.h"
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/attributes/PublisherAttributes.h>
#include <fastrtps/publisher/Publisher.h>
#include <fastrtps/Domain.h>
#include <fastrtps/types/DynamicTypeBuilderFactory.h>
#include <fastrtps/types/DynamicDataFactory.h>
#include <fastrtps/types/DynamicTypeBuilder.h>
#include <fastrtps/types/DynamicTypeBuilderPtr.h>
#include <fastrtps/types/DynamicType.h>
#include <thread>
#include <time.h>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace eprosima::fastrtps::types;
// using namespace cv;
PicturePublisher::PicturePublisher()
: mp_participant(nullptr)
, mp_publisher(nullptr)
, m_DynType(DynamicType_ptr(nullptr))
{
}
bool PicturePublisher::init()
{
cv::Mat image = cv::imread("drone.jpg", 1);
std::vector<unsigned char> buffer;
cv::imencode(".jpg", image, buffer);
// Create basic builders
DynamicTypeBuilder_ptr struct_type_builder(DynamicTypeBuilderFactory::get_instance()->create_struct_builder());
DynamicType_ptr octet_type(DynamicTypeBuilderFactory::get_instance()->create_byte_type());
DynamicTypeBuilder_ptr sequence_type_builder(DynamicTypeBuilderFactory::get_instance()->create_sequence_builder(octet_type, 3873715));
DynamicType_ptr sequence_type = sequence_type_builder->build();
// Add members to the struct. By the way, id must be consecutive starting by zero.
struct_type_builder->add_member(0, "index", DynamicTypeBuilderFactory::get_instance()->create_uint32_type());
struct_type_builder->add_member(1, "size", DynamicTypeBuilderFactory::get_instance()->create_uint32_type());
struct_type_builder->add_member(2, "Picture", sequence_type);
struct_type_builder->set_name("Picture"); // Need to be same with topic data type
DynamicType_ptr dynType = struct_type_builder->build();
m_DynType.SetDynamicType(dynType);
m_DynHello = DynamicDataFactory::get_instance()->create_data(dynType);
m_DynHello->set_uint32_value(0, 0);
m_DynHello->set_uint32_value(buffer.size(), 1);
MemberId id;
// std::cout << "init: " << id << std::endl;
DynamicData* sequence_data = m_DynHello->loan_value(2);
for (int i = 0; i < buffer.size(); i++) {
if (i == buffer.size() - 1) {
std::cout << "Total Size: " << i + 1 << std::endl;
}
sequence_data->insert_byte_value(buffer[i], id);
}
m_DynHello->return_loaned_value(sequence_data);
ParticipantAttributes PParam;
PParam.rtps.setName("DynPicture_pub");
mp_participant = Domain::createParticipant(PParam, (ParticipantListener*)&m_part_list);
if (mp_participant == nullptr)
{
return false;
}
//REGISTER THE TYPE
Domain::registerDynamicType(mp_participant, &m_DynType);
//CREATE THE PUBLISHER
PublisherAttributes Wparam;
Wparam.topic.topicKind = NO_KEY;
Wparam.topic.topicDataType = "Picture";
Wparam.topic.topicName = "PictureTopic";
mp_publisher = Domain::createPublisher(mp_participant, Wparam, (PublisherListener*)&m_listener);
if (mp_publisher == nullptr)
{
return false;
}
return true;
}
PicturePublisher::~PicturePublisher()
{
Domain::removeParticipant(mp_participant);
DynamicDataFactory::get_instance()->delete_data(m_DynHello);
Domain::stopAll();
}
void PicturePublisher::PubListener::onPublicationMatched(
Publisher* /*pub*/,
MatchingInfo& info)
{
if (info.status == MATCHED_MATCHING)
{
n_matched++;
firstConnected = true;
std::cout << "Publisher matched" << std::endl;
}
else
{
n_matched--;
std::cout << "Publisher unmatched" << std::endl;
}
}
void PicturePublisher::PartListener::onParticipantDiscovery(
Participant*,
ParticipantDiscoveryInfo&& info)
{
if (info.status == ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " discovered" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::REMOVED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " removed" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::DROPPED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " dropped" << std::endl;
}
}
void PicturePublisher::runThread(
uint32_t samples,
uint32_t sleep)
{
uint32_t i = 0;
while (!stop && (i < samples || samples == 0))
{
if (publish(samples != 0))
{
uint32_t index;
m_DynHello->get_uint32_value(index, 0);
std::cout << "runThreading...; \tSample Index: " << index << "; \t";
uint32_t size;
m_DynHello->get_uint32_value(size, 1);
std::cout << "size: " << size << std::endl;
if (i == 9){
std::cout << "Structure message" << " with index: " << i + 1 << " SENT" << std::endl;
// Avoid unmatched condition impact subscriber receiving message
std::cout << "Wait within twenty second..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
++i;
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}
}
void PicturePublisher::run(
uint32_t samples,
uint32_t sleep)
{
stop = false;
std::thread thread(&PicturePublisher::runThread, this, samples, sleep);
if (samples == 0)
{
std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl;
std::cin.ignore();
stop = true;
}
else
{
std::cout << "Publisher running " << samples << " samples." << std::endl;
}
thread.join();
}
bool PicturePublisher::publish(
bool waitForListener)
{
// std::cout << "m_listener.n_matched: " << m_listener.n_matched << std::endl;
if (m_listener.firstConnected || !waitForListener || m_listener.n_matched > 0)
{
uint32_t index;
m_DynHello->get_uint32_value(index, 0);
m_DynHello->set_uint32_value(index + 1, 0);
mp_publisher->write((void*)m_DynHello);
return true;
}
return false;
}
In PicturePublisher::init() function
Subsciber.cpp
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// Hpshboss modifys code from eprosima's github example;
// Licensed under the Apache License, Version 2.0 (the "License");
/**
* #file Subscriber.cpp
*
*/
#include "Subscriber.h"
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/attributes/SubscriberAttributes.h>
#include <fastrtps/subscriber/Subscriber.h>
#include <fastrtps/Domain.h>
#include <fastrtps/types/DynamicTypeBuilderFactory.h>
#include <fastrtps/types/DynamicDataFactory.h>
#include <fastrtps/types/DynamicTypeBuilder.h>
#include <fastrtps/types/DynamicTypeBuilderPtr.h>
#include <fastrtps/types/DynamicType.h>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
#include <opencv2/opencv.hpp>
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace eprosima::fastrtps::types;
// using namespace cv;
PictureSubscriber::PictureSubscriber()
: mp_participant(nullptr)
, mp_subscriber(nullptr)
, m_DynType(DynamicType_ptr(nullptr))
{
}
struct timespec begin, end;
double elapsed;
std::vector<unsigned char> buffer;
bool PictureSubscriber::init()
{
ParticipantAttributes PParam;
PParam.rtps.setName("DynPicture_sub");
mp_participant = Domain::createParticipant(PParam, (ParticipantListener*)&m_part_list);
if (mp_participant == nullptr)
{
return false;
}
// Create basic builders
DynamicTypeBuilder_ptr struct_type_builder(DynamicTypeBuilderFactory::get_instance()->create_struct_builder());
DynamicTypeBuilder_ptr octet_builder(DynamicTypeBuilderFactory::get_instance()->create_byte_builder());
DynamicTypeBuilder_ptr sequence_type_builder(DynamicTypeBuilderFactory::get_instance()->create_sequence_builder(octet_builder.get(), 3873715));
DynamicType_ptr sequence_type = sequence_type_builder->build();
// Add members to the struct.
struct_type_builder->add_member(0, "index", DynamicTypeBuilderFactory::get_instance()->create_uint32_type());
struct_type_builder->add_member(1, "size", DynamicTypeBuilderFactory::get_instance()->create_uint32_type());
struct_type_builder->add_member(2, "Picture", sequence_type);
struct_type_builder->set_name("Picture");
DynamicType_ptr dynType = struct_type_builder->build();
m_DynType.SetDynamicType(dynType);
m_listener.m_DynHello = DynamicDataFactory::get_instance()->create_data(dynType);
//REGISTER THE TYPE
Domain::registerDynamicType(mp_participant, &m_DynType);
//CREATE THE SUBSCRIBER
SubscriberAttributes Rparam;
Rparam.topic.topicKind = NO_KEY;
Rparam.topic.topicDataType = "Picture";
Rparam.topic.topicName = "PictureTopic";
mp_subscriber = Domain::createSubscriber(mp_participant, Rparam, (SubscriberListener*)&m_listener);
if (mp_subscriber == nullptr)
{
return false;
}
return true;
}
PictureSubscriber::~PictureSubscriber()
{
Domain::removeParticipant(mp_participant);
DynamicDataFactory::get_instance()->delete_data(m_listener.m_DynHello);
Domain::stopAll();
}
void PictureSubscriber::SubListener::onSubscriptionMatched(
Subscriber* /*sub*/,
MatchingInfo& info)
{
if (info.status == MATCHED_MATCHING)
{
n_matched++;
std::cout << "Subscriber matched" << std::endl;
}
else
{
n_matched--;
std::cout << "Subscriber unmatched" << std::endl;
}
}
void PictureSubscriber::PartListener::onParticipantDiscovery(
Participant*,
ParticipantDiscoveryInfo&& info)
{
if (info.status == ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " discovered" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::REMOVED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " removed" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::DROPPED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " dropped" << std::endl;
}
}
void PictureSubscriber::SubListener::onNewDataMessage(
Subscriber* sub)
{
if (sub->takeNextData((void*)m_DynHello, &m_info))
{
if (m_info.sampleKind == ALIVE)
{
this->n_samples++;
// Print your structure data here.
uint32_t index;
m_DynHello->get_uint32_value(index, 0);
std::cout << "index: " << index << "; \t";
uint32_t size;
m_DynHello->get_uint32_value(size, 1);
std::cout << "size: " << size << std::endl;
DynamicType_ptr octet_type_temp(DynamicTypeBuilderFactory::get_instance()->create_byte_type());
DynamicTypeBuilder_ptr sequence_type_builder_temp(DynamicTypeBuilderFactory::get_instance()->create_sequence_builder(octet_type_temp, 3873715));
DynamicType_ptr sequence_type_temp = sequence_type_builder_temp->build();
DynamicData* sequence_data_temp = m_DynHello->loan_value(2);
for (int i = 0; i < size; i++) {
buffer.push_back(sequence_data_temp->get_byte_value(i));
}
m_DynHello->return_loaned_value(sequence_data_temp);
cv::Mat imageDecoded = cv::imdecode(buffer, 1);
cv::imwrite(std::to_string(index) + "_droneNew.jpg", imageDecoded);
}
}
}
void PictureSubscriber::run()
{
std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl;
std::cin.ignore();
}
void PictureSubscriber::run(
uint32_t number)
{
std::cout << "Subscriber running until " << number << "samples have been received" << std::endl;
while (number > this->m_listener.n_samples)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
In PictureSubscriber::SubListener::onNewDataMessage(Subscriber* sub) function
Here at eProsima, we have found some solutions to the problem you point out.
Firstly, please note that you don't need to use Dynamic Types to define the type that contains the image you are going to transmit. The easiest thing to do in your case is to define your type through an IDL file. Using the IDL file and the Fast-DDS-Gen tool you can generate the code for access to the data type elements, as well as automatically generate the data serialization and deserialization functions. In the Picture.idl file you will find the type defined in IDL format that best suits the data type you have created with dynamic types. Here you can find a guide on how to use the Fast-DDS-Gen tool. In this documentation you will also find a complete example of how an IDL file can be used to generate a complete DDS publisher/subscriber application, as well as the supported formats for the data. Also below are the files Publisher.cpp and Subscriber.cpp which have been modified according to the new data type.
We also recommend you to take a look at the example HelloWorldExample, as it is the one that best suits your needs. In this example you can also discover the new DDS API, included in the latest version of Fast DDS (2.1.0).
As an additional comment, we recommend that, instead of transmitting an octet vector, you encode the image in string base64 format before transmitting it since it's one of the most widespread formats for image transmission.
Picture.idl
struct Picture
{
unsigned long index;
unsigned long size;
sequence<octet> picture;
};
Publisher.cpp
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// Hpshboss modifys code from eprosima's github example;
// Licensed under the Apache License, Version 2.0 (the "License");
/**
* #file PicturePublisher.cpp
*
*/
#include "PicturePublisher.h"
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/attributes/PublisherAttributes.h>
#include <fastrtps/publisher/Publisher.h>
#include <fastrtps/Domain.h>
#include <fastrtps/types/DynamicTypeBuilderFactory.h>
#include <fastrtps/types/DynamicDataFactory.h>
#include <fastrtps/types/DynamicTypeBuilder.h>
#include <fastrtps/types/DynamicTypeBuilderPtr.h>
#include <fastrtps/types/DynamicType.h>
#include <thread>
#include <time.h>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace eprosima::fastrtps::types;
// using namespace cv;
PicturePublisher::PicturePublisher()
: mp_participant(nullptr)
, mp_publisher(nullptr)
{
}
bool PicturePublisher::init()
{
cv::Mat image = cv::imread("dog.jpg", cv::IMREAD_COLOR);
if(image.empty())
{
std::cout << "Could not read the image." << std::endl;
return false;
}
cv::imshow("Display window", image);
int k = cv::waitKey(0);
std::vector<unsigned char> buffer;
if(!cv::imencode(".jpg", image, buffer)){
printf("Image encoding failed");
}
m_Picture.index(0);
m_Picture.size(buffer.size());
m_Picture.picture(buffer);
ParticipantAttributes PParam;
PParam.rtps.setName("Picture_pub");
mp_participant = Domain::createParticipant(PParam, &m_part_list);
if (mp_participant == nullptr)
{
return false;
}
//REGISTER THE TYPE
Domain::registerType(mp_participant, &m_type);
// Domain::registerDynamicType(mp_participant, &m_DynType);
//CREATE THE PUBLISHER
PublisherAttributes Wparam;
Wparam.topic.topicKind = NO_KEY;
Wparam.topic.topicDataType = "Picture";
Wparam.topic.topicName = "PictureTopic";
mp_publisher = Domain::createPublisher(mp_participant, Wparam, (PublisherListener*)&m_listener);
if (mp_publisher == nullptr)
{
return false;
}
return true;
}
PicturePublisher::~PicturePublisher()
{
Domain::removeParticipant(mp_participant);
}
void PicturePublisher::PubListener::onPublicationMatched(
Publisher* /*pub*/,
MatchingInfo& info)
{
if (info.status == MATCHED_MATCHING)
{
n_matched++;
firstConnected = true;
std::cout << "Publisher matched" << std::endl;
}
else
{
n_matched--;
std::cout << "Publisher unmatched" << std::endl;
}
}
void PicturePublisher::PartListener::onParticipantDiscovery(
Participant*,
ParticipantDiscoveryInfo&& info)
{
if (info.status == ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " discovered" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::REMOVED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " removed" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::DROPPED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " dropped" << std::endl;
}
}
void PicturePublisher::runThread(
uint32_t samples,
uint32_t sleep)
{
uint32_t i = 0;
while (!stop && (i < samples || samples == 0))
{
if (publish(samples != 0))
{
std::cout << "runThreading...; \tSample Index: " << m_Picture.index() << "; \t";
std::cout << "size: " << m_Picture.size() << std::endl;
if (i == 9){
std::cout << "Structure message" << " with index: " << i + 1 << " SENT" << std::endl;
// Avoid unmatched condition impact subscriber receiving message
std::cout << "Wait within twenty second..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
++i;
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}
}
void PicturePublisher::run(
uint32_t samples,
uint32_t sleep)
{
stop = false;
std::thread thread(&PicturePublisher::runThread, this, samples, sleep);
if (samples == 0)
{
std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl;
std::cin.ignore();
stop = true;
}
else
{
std::cout << "Publisher running " << samples << " samples." << std::endl;
}
thread.join();
}
bool PicturePublisher::publish(
bool waitForListener)
{
// std::cout << "m_listener.n_matched: " << m_listener.n_matched << std::endl;
if (m_listener.firstConnected || !waitForListener || m_listener.n_matched > 0)
{
m_Picture.index(m_Picture.index() + 1);
mp_publisher->write((void*)&m_Picture);
return true;
}
return false;
}
Subscriber.cpp
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// Hpshboss modifys code from eprosima's github example;
// Licensed under the Apache License, Version 2.0 (the "License");
/**
* #file Subscriber.cpp
*
*/
#include "PictureSubscriber.h"
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/attributes/SubscriberAttributes.h>
#include <fastrtps/subscriber/Subscriber.h>
#include <fastrtps/Domain.h>
#include <fastrtps/types/DynamicTypeBuilderFactory.h>
#include <fastrtps/types/DynamicDataFactory.h>
#include <fastrtps/types/DynamicTypeBuilder.h>
#include <fastrtps/types/DynamicTypeBuilderPtr.h>
#include <fastrtps/types/DynamicType.h>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
#include <opencv2/opencv.hpp>
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace eprosima::fastrtps::types;
// using namespace cv;
PictureSubscriber::PictureSubscriber()
: mp_participant(nullptr)
, mp_subscriber(nullptr)
{
}
struct timespec begin, end;
double elapsed;
std::vector<unsigned char> buffer;
bool PictureSubscriber::init()
{
ParticipantAttributes PParam;
PParam.rtps.setName("Picture_sub");
mp_participant = Domain::createParticipant(PParam, &m_part_list);
if (mp_participant == nullptr)
{
return false;
}
//REGISTER THE TYPE
Domain::registerType(mp_participant, &m_type);
//CREATE THE SUBSCRIBER
SubscriberAttributes Rparam;
Rparam.topic.topicKind = NO_KEY;
Rparam.topic.topicDataType = "Picture";
Rparam.topic.topicName = "PictureTopic";
mp_subscriber = Domain::createSubscriber(mp_participant, Rparam, (SubscriberListener*)&m_listener);
if (mp_subscriber == nullptr)
{
return false;
}
return true;
}
PictureSubscriber::~PictureSubscriber()
{
Domain::removeParticipant(mp_participant);
}
void PictureSubscriber::SubListener::onSubscriptionMatched(
Subscriber* /*sub*/,
MatchingInfo& info)
{
if (info.status == MATCHED_MATCHING)
{
n_matched++;
std::cout << "Subscriber matched" << std::endl;
}
else
{
n_matched--;
std::cout << "Subscriber unmatched" << std::endl;
}
}
void PictureSubscriber::PartListener::onParticipantDiscovery(
Participant*,
ParticipantDiscoveryInfo&& info)
{
if (info.status == ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " discovered" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::REMOVED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " removed" << std::endl;
}
else if (info.status == ParticipantDiscoveryInfo::DROPPED_PARTICIPANT)
{
std::cout << "Participant " << info.info.m_participantName << " dropped" << std::endl;
}
}
void PictureSubscriber::SubListener::onNewDataMessage(
Subscriber* sub)
{
std::cout << "Data received." << std::endl;
if (sub->takeNextData((void*)&m_Picture, &m_info))
{
if (m_info.sampleKind == ALIVE)
{
this->n_samples++;
// Print your structure data here.
uint32_t index = m_Picture.index();
std::cout << "index: " << index << "; \t";
std::cout << "size: " << m_Picture.size() << std::endl;
cv::Mat imageDecoded = cv::imdecode(m_Picture.picture(), 1);
cv::imwrite(std::to_string(index) + "_dog_received.jpg", imageDecoded);
}
}
}
void PictureSubscriber::run()
{
std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl;
std::cin.ignore();
}
void PictureSubscriber::run(
uint32_t number)
{
std::cout << "Subscriber running until " << number << "samples have been received" << std::endl;
while (number > this->m_listener.n_samples)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
It's a bit weird to me that the code after a for loop doesn't execute but the compiler doesn't raise any warning:
#include <iostream>
#include <iterator>
bool isVowel(char ch)
{
char vowels[]{"aeiouAEIOU"};
char *p = std::find(std::begin(vowels), std::end(vowels), ch);
if (p != std::end(vowels))
{
std::cout << ch << " is a vowel" << '\n';
return true;
}
else
{
std::cout << ch << " is not a vowel" << '\n';
return false;
}
}
int main()
{
char name[]{"MollieU"};
int numVowels{0};
std::cout << name << '\n';
int length{std::size(name)};
for (char* ptr{name}; ptr < (name + length); ++ptr)
{
if (isVowel(*ptr))
++numVowels;
}
std::cout << name << " has " << numVowels << " vowels." << '\n';
return 0;
}
It has outputs like:
MollieU
M is not a vowel
o is a vowel
l is not a vowel
l is not a vowel
i is a vowel
e is a vowel
U is a vowel
But std::cout << name << " has " << numVowels << " vowels." << '\n'; is never run. Whatever code I put after the loop is never run. I am not sure if return 0 is run or not, but the file is compiled successfully. I am using g++ -std=c++2a on osx.
Try to use the following:
int length { std::size(name) - 1 };
Please help with this beginner's program for fetching gdk screen attributes. I have a small C++ program to find out the connected display units. I am using c++ on Linux Debian. gdk_screen_get_default() doesn't return Screen object. If I don't check for screen object then the following error occurs.
Error
(process:8023): Gdk-CRITICAL **: gdk_screen_get_monitor_geometry: assertion 'GDK_IS_SCREEN (screen)' failed
I went through related posts and referred to this for the below code snippet.
Thanks for your help. Any pointers/guidelines to resolve this would be helpful.
I have one monitor connected and the display settings are
$ echo $XDG_CURRENT_DESKTOP
GNOME
$ echo $DISPLAY
:0
CODE
#include <gdk/gdk.h>
#include <iostream>
/*
GTK version 3.14.5
g++ getScreenInfo.cpp -o getScreenInfo `pkg-config gtk+-3.0 --cflags --libs`
*/
int main()
{
GdkScreen *screen;
screen = gdk_screen_get_default();
int num_monitors;
int i;
if (screen)
{
num_monitors = gdk_screen_get_n_monitors(screen);
for (i = 0; i < num_monitors; i++)
{
GdkRectangle rect;
gdk_screen_get_monitor_geometry (screen, i, &rect);
std::cout << "monitor " << i << ": coordinates (" << rect.x << ","
<< rect.y << ", size (" << rect.width << "," << rect.height << ")"
<< std::endl;
}
}else
{
std::cout << "Couldn't obtain default screen object" << std::endl;
}
}
27 Apr 2017 EDIT: RESOLVED
#include <iostream>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
/*
GTK version 3.14.5
To compile:
g++ getScreenInfo.cpp -o getScreenInfo `pkg-config gtk+-3.0 --cflags --libs`
*/
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GdkScreen *screen = gdk_screen_get_default();
int num_monitors;
int i;
if (screen)
{
num_monitors = gdk_screen_get_n_monitors(screen);
for (i = 0; i < num_monitors; i++)
{
GdkRectangle rect;
gdk_screen_get_monitor_geometry (screen, i, &rect);
std::cout << "monitor " << i << ": offsets (" << rect.x << ","
<< rect.y << ", size (" << rect.width << "," << rect.height << ")"
<< std::endl;
}
}
else
{
std::cout << "Couldn't obtain default screen object" << std::endl;
}
// To query primary display properties
guint monitor = gdk_screen_get_primary_monitor(screen);
GdkRectangle screen_geometry = { 0, 0, 0, 0 };
gdk_screen_get_monitor_geometry(screen, monitor, &screen_geometry);
std::cout << screen_geometry.x << std::endl;
std::cout << screen_geometry.y << std::endl;
std::cout << screen_geometry.width << std::endl;
std::cout << screen_geometry.height << std::endl;
}
Answering my own question.
Finally, figured out the resolution. gtk_init( ) was missing before fetching the screen. Added that and respective include for gtk/gtk.h and now the code looks like
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv); // <---- added this
GdkScreen *screen = gdk_screen_get_default();
:
followed by rest of the code shared in the problem description above.
I'm very confused by a compiler error. My code was thoroughly working 4-5 h ago; the only feasible checkpoint along the way hasn't yielded any clues (i.e., I have not been able to get the error to disappear at one intermediate step). I don't see how the compiler error could be related to any of the changes I have made.
Compiling with
g++ -O3 -o a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp main.cpp Rdraws.cpp SimPars.cpp
the following error appears
Undefined symbols:
"Simulation::runTestEpidSim()", referenced from:
_main in ccmcSY5M.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I create and manipulate Simulation objects in main. My only changes to the code were (1) to create a new member function, Simulation::runTestEpidSim(), which is called in main, and (2) to write some new global input/output processing functions, which I've since unwrapped and inserted directly into main in order to debug what's going on.
I have not changed any cpp files, includes, header files, libraries, or compiler commands.
I'm not a professional programmer. How would the pros go about debugging this kind of problem?
Not sure how best to cut and paste my code, but here's an excerpt--
class Simulation
{
public:
Simulation( int trt, int sid, SimPars * spPtr );
~Simulation();
// MEMBER FUNCTION PROTOTYPES
void runDemSim( void );
void runEpidSim( void );
double runTestEpidSim( void );
...
}
int main() {
for ( int trt = 0; trt < NUM_TREATMENTS; trt++ ) {
double treatment = TREATMENTS[ trt ];
....
cout << "Treatment #" << trt + 1 << " of " << NUM_TREATMENTS << ":" << endl;
int matchAttempts = 0;
double prevError = 1.0 + PREV_ERROR_THOLD;
double thisBeta = 0.0;
while ( matchAttempts < MAX_MATCH_ATTEMPTS && prevError > PREV_ERROR_THOLD ) {
cout << " Attempt #" << matchAttempts + 1;
SimPars thesePars;
SimPars * spPtr = &thesePars;
Simulation thisSim( trt, 1, spPtr );
thisSim.runDemSim();
prevError = thisSim.runTestEpidSim() - TARGET_PREV;
cout << ", error=" << prevError << endl;
if ( prevError > PREV_ERROR_THOLD ) {
....
return 0;
}
I had previously been executing runEpidSim() with no problem.
Update
I have the full code for the implementation of Simulation::runTestEpidSim()--I have no idea how best to present this!
double Simulation::runTestEpidSim( void ) {
if ( allHosts.size() == 0 ) {
cerr << "No hosts remaining for epidemiological simulation. Cancelling." << endl;
assert(false);
}
cout << " Entering test simulation at t=" << demComplete << "." << endl;
double percentDone = 0.0;
// Initialize host population with infections
demOutputStrobe = t;
epidOutputStrobe = t;
seedInfections();
EventPQ::iterator eventIter = currentEvents.begin();
double nextTimeStep = t + EPID_DELTA_T;
double prevalences[ NUM_TEST_SAMPLES ]; // holds prevalences at strobing periods
for ( int p = 0; p < NUM_TEST_SAMPLES; p++ ) {
prevalences[ p ] = 0.0;
}
double prevYear = DEM_SIM_LENGTH + TEST_EPID_SIM_LENGTH - NUM_TEST_SAMPLES; // first simulation year to start sampling
int prevSamples = 0;
while ( t < TEST_EPID_SIM_LENGTH + demComplete )
{
#ifdef DEBUG
cout << "time step = " << t << " (" << allHosts.size() << " hosts; " << currentEvents.size() << " events queued)" << endl;
assert( currentEvents.size()>0);
#endif
// Calculate new infections for every host and add events to stack
#ifdef DEBUG
cout << "Adding infections for this time step: " << endl;
#endif
calcSI();
eventIter = currentEvents.begin();
#ifdef DEBUG
cout << "Executing events off stack (currentEvents.size()=" << currentEvents.size() << "): " << endl;
#endif
while ( ( *eventIter ).time < nextTimeStep ) {
while ( demOutputStrobe < t ) {
writeDemOutput();
demOutputStrobe += STROBE_DEM;
}
while ( epidOutputStrobe < t ) {
writeEpidOutput();
epidOutputStrobe += STROBE_EPID;
}
if ( prevYear < t ) {
prevalences[ prevSample ] = calcPrev();
cout << "\tOutputting prevalence sample #" << prevSamples+1 << "; prevalence under 5 is " << prevalences[ prevSample ] << endl;
prevSample++;
}
while ( percentDone/100.0 < ( t - demComplete )/EPID_SIM_LENGTH ) {
cout << "\t" << percentDone << "% of this test component complete." << endl;
percentDone += PROGRESS_INTERVAL;
}
// Execute events off stack
Event thisEvent = *eventIter;
#ifdef DEBUG
assert( thisEvent.time >= t );
if ( thisEvent.time < t ) {
cout << "Trying to execute event scheduled for time " << thisEvent.time << ", though sim time is " << t << endl;
assert( thisEvent.time >= t );
}
#endif
t = thisEvent.time;
#ifdef DEBUG
cout << "\tt=" << t << endl;
// cout << "\tAbout to execute event ID " << (*eventIter).eventID << " at time " << (*eventIter).time << " for host ID " << (*eventIter).hostID << endl;
cout << "\tAbout to execute event ID " << thisEvent.eventID << " at time " << thisEvent.time << " for host ID " << thisEvent.hostID << endl;
#endif
executeEvent( thisEvent );
eventCtr++;
currentEvents.erase( eventIter ); // Check that if event added to top of currentEvents, will not invalidate itr
eventIter = currentEvents.begin();
#ifdef DEBUG
cout << "\tcurrentEvents.size() after pop is " << currentEvents.size() << endl;
#endif
}
t = nextTimeStep;
nextTimeStep += EPID_DELTA_T;
}
double meanPrev = 0.0;
double sumPrev = 0.0;
int totSamples = 0;
for ( int p = 0; p < NUM_TEST_SAMPLES; p++ ) {
if ( prevalences[ p ] > 0 ) { // in cae
sumPrev += prevalences[ p ];
totSamples++;
}
}
cout << "Counted " << totSamples << " total prevalence samples." << endl;
meanPrev = sumPrev/(double)totSamples;
return( meanPrev );
}
How would the pros go about debugging
this kind of problem?
You should start with the error message:
Undefined symbols:"Simulation::runTestEpidSim()"
You've added a prototype for runTestEpidSim, but you haven't shown the definition of this function (presumably it should be in Simulation.cpp)
Here's what I'd look for, to start...
Have you defined it at all?
Have you defined it as a member of class Simulation?
Have you defined it with exactly the same parameters?
Have you defined it with exactly the same return type?
Is the definition accidentally commented or #ifdef'd out?
Update
Thanks for posting the definition. What you've posted looks fine, and passes the first four tests above - but you can see how a mismatched #ifdef DEBUG could mess things up for you...
In addition...
Have you actually compiled and linked with the file containing the definition?
The linker error message says that you don't have a definition for run*Test*EpidSim, which you need as you are calling this function inside main. Your description matches this problem: you have declared this new method, but you haven't implemented it anywhere. You need to provide the actual source code of this test function.
It looks like you declared function but not implemented it
Where did you define the runTestEpidSim? Did you define it wit the correct signature in the same file containing main? If it is defined in some other file: did you include that file in the build process?
double
Simulation::runTestEpidSim(void)
{
...
}
The code you gave contains only the declaration, so where's the definition?