Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No support for dynamic data for writing/publishing of modified sample data #45

Open
pyphais opened this issue Oct 17, 2024 · 3 comments · May be fixed by #47
Open

No support for dynamic data for writing/publishing of modified sample data #45

pyphais opened this issue Oct 17, 2024 · 3 comments · May be fixed by #47

Comments

@pyphais
Copy link

pyphais commented Oct 17, 2024

It looks like the current topic replayer has no support for XTypes topics - I understand from our conversation here that it probably just hasn't been done yet, but I figured since you're working on PR #43 I might as well request/suggest XTypes support for the replayer as well.

@pyphais
Copy link
Author

pyphais commented Oct 21, 2024

I've attempted to add this myself, and also seemingly successfully added the reading dynamic data etc from this, on my own computer. I am not a dev and have no idea if any of that work would be useful to you guys. If it'd be useful for me to share/push these somewhere I definitely can - not sure if you guys ever have outside contributors to this project.

I am having some problems in the last step of publishing the modified sample data, and I don't think I have the skills to figure out what's going wrong (I've tried for a couple days). I'm assuming they're all stemming from the same problem/thing I'm probably doing wrong:

  • DynamicData::set_int16_value (and other data types) is returning RETCODE::UNSUPPORTED when trying to populate the cloned (and also original to check if just clone was failing) dynamicData sample, despite the get_int16_value and other get_*_value functions returning the correct values (ie correct memberId and datatypes). I'm not sure if I'm not accessing it properly and it's read-only or something, but I can't seem to figure it out.
  • Trying to write the dynamic sample (even without trying to edit the sample values) to the dynamic data writer is giving a serialization error:
    • (42232|15776) WARNING: DynamicSample::serialized_size: DynamicDataBase::serialized_size failed!
    • (42232|15776) ERROR: DataWriterImpl::serialize_sample: failed to serialize sample data
    • I'm assuming this stems from me not setting up the data writer properly?
  • Unsure if this is actually a problem or just how it's supposed to work but wondering if it's related - I've had this since before ever editing anything: if I open a topic in the monitor that doesn't have any existing publishers from other programs (only subscribers), create_topic in topic_monitor will fail. Not sure if this stems from some other problem with how topics are being created in other programs or not though. Because I setup the dynamic writer/publisher in the 'replayer' similarly to the dynamic publisher/talker in the topic_monitor, I have this same problem there as well.

These are the main changes I've made relating to this problem (removing most of my debug outputs, and removing changes I made to read dynamic data for recording/plotting which works - I can share that too if wanted):

void TablePage::on_publishButton_clicked()
{
  std::cout << "on_publishButton_clicked()" << std::endl;
    const std::shared_ptr<OpenDynamicData> sample = m_tableModel->commitSample();
    const DDS::DynamicData_var dynamicSample = m_tableModel->commitDynamicSample();
    if (dynamicSample) {
      std::cout << "Detected dynamicSample, attempting to publish" << std::endl;
      m_topicReplayer->publishSample(dynamicSample);
      revertButton->setEnabled(false);
    } else if (sample) {
      std::cout << "Detected NON-dynamic sample, attempting to publish" << std::endl;
      m_topicReplayer->publishSample(sample);
      revertButton->setEnabled(false);
    }
}

In TopicTableModel.cpp:

const DDS::DynamicData_var TopicTableModel::commitDynamicSample()
{
  // Reset the edited state
  for (size_t i = 0; i < m_data.size(); i++)
  {
    m_data.at(i)->edited = false;
  }

  // Create a new sample
  std::shared_ptr<TopicInfo> topicInfo = CommonData::getTopicInfo(m_topicName);
  if (!topicInfo || topicInfo->typeCode)
  {
    return nullptr;
  }

  // Create a copy of the current sample
  DDS::DynamicData_var newDynamicSample = m_dynamicsample->clone();
//  DDS::DynamicData_var newDynamicSample = m_dynamicsample;
  if(!newDynamicSample) {
    std::cout << "CLONE BAD" << std::endl;
  }

  // Populate the new sample from the user-edited changes
  for (size_t i = 0; i < m_data.size(); i++)
  {
    populateSample(newDynamicSample, m_data.at(i));
  }

  // Replace and delete the old sample
  setSample(newDynamicSample);
  return newDynamicSample;
}
bool TopicTableModel::populateSample(DDS::DynamicData_var memberData,
                                     DataRow* const dataInfo)
{
  bool pass = false;
  if (!memberData || !dataInfo)
  {
    return false;
  }

  const QString memberName = dataInfo->name.toUtf8().data();
  DDS::MemberId memberId = CommonData::getNestedMemberAndIdByFullName(memberData, memberName);//Custom function - seems to work, can share - it also updates memberData to be the final level of a complex member
  OpenDDS::XTypes::TypeKind tk = CommonData::getMemberTypeKindById(memberData, memberId);//Custom function - seems to work, can share
  std::cout << "tk: " << OpenDDS::XTypes::typekind_to_string(tk) << std::endl;
  if (!memberData)
  {
    std::cerr << "TopicTableModel::populateSample: "
              << "Unable to find member named "
              << memberName.toStdString()
              << std::endl;

    return false;
  }

  DDS::ReturnCode_t rc = DDS::RETCODE_INCONSISTENT_POLICY; //temporary, not actual error
  std::cout << "memberId: " << memberId << std::endl;
  switch (dataInfo->type)
  {
    case CORBA::tk_long:
    {
      int32_t tmpValue = dataInfo->value.toInt(&pass);
      if (pass)
      {
        rc = memberData->set_int32_value(memberId, tmpValue);
      }
      std::cout << dataInfo->type << " " << tmpValue << std::endl;
      break;
    }
    case CORBA::tk_short:
    {
      CORBA::Int16 tmpValue = dataInfo->value.toInt(&pass);
      short temp = 33;
      memberData->get_int16_value(temp, memberId);
      std::cout << "before: " << temp << std::endl;
      if (pass)
      {
        rc = memberData->set_int16_value(memberId, tmpValue);
        memberData->get_int16_value(temp, memberId);
        std::cout << "mid: " << temp << std::endl;
      }
      std::cout << dataInfo->type << " " << tmpValue << std::endl;
      break;
    }
///All the other switch cases exist here but they're all giving the same error so I've omitted them to shorten this comment
    default:
      std::cerr << "TopicTableModel::populateSample "
                << "Skipped "
                << memberName.toStdString()
                << std::endl;
      break;

  } // End child type switch
  std::cout << "Return code: " << rc << std::endl;
  return pass;

} // End TopicTableModel::populateSample

In TopicReplayer.cpp:

TopicReplayer::TopicReplayer(const QString& topicName) :
                             m_topicName(topicName),
                             m_typeCode(nullptr),
                             m_topic(nullptr),
                             m_replayer(nullptr)
{
    // Make sure we have an information object for this topic
    std::shared_ptr<TopicInfo> topicInfo = CommonData::getTopicInfo(topicName);
    if (topicInfo == nullptr)
    {
        std::cerr << "Unable to find topic information for "
                  << topicName.toStdString()
                  << std::endl;
        return;
    }

    //store extensibility
    m_extensibility = topicInfo->extensibility;

    OpenDDS::DCPS::Service_Participant* service = TheServiceParticipant;
    DDS::DomainParticipant* domainParticipant = CommonData::m_ddsManager->getDomainParticipant();

  if (topicInfo->typeCode) {
    // Existing code, but now only running if non-dynamic data
    m_typeCode = topicInfo->typeCode;
    m_topic = service->create_typeless_topic(domainParticipant,
        topicInfo->name.c_str(),
        topicInfo->typeName.c_str(),
        topicInfo->hasKey,
        topicInfo->topicQos,
        new GenericTopicListener,
        DDS::INCONSISTENT_TOPIC_STATUS);

    if (!m_topic)
    {
        std::cerr << "Failed to create typeless topic" << std::endl;
        return;
    }

    m_replayer = service->create_replayer(
        domainParticipant,
        m_topic,
        topicInfo->pubQos,
        topicInfo->writerQos,
        OpenDDS::DCPS::RcHandle<OpenDDS::DCPS::ReplayerListener>()
    );

    if (!m_replayer)
    {
        std::cerr << "Failed to created replayer" << std::endl;
        return;
    }
  } else {
    // Use DynamicDataWriter instead.

    m_topic = domainParticipant->create_topic(topicInfo->name.c_str(),
                                              topicInfo->typeName.c_str(),
                                              topicInfo->topicQos,
                                              0,
                                              0);
    if (!m_topic) {
      std::cerr << "Failed to create topic " << topicInfo->name << " in topic REPLAYER!!" << std::endl;
      return;
    }

    DDS::Publisher_var publisher = domainParticipant->create_publisher(topicInfo->pubQos,0,
                                                                       0);
    if (!publisher) {
      std::cerr << "Failed to create publisher for topic " << topicInfo->name << std::endl;
      return;
    }

    m_dw = publisher->create_datawriter(m_topic,
                                        topicInfo->writerQos,
                                        DDS::DataWriterListener::_nil(),
                                        OpenDDS::DCPS::DEFAULT_STATUS_MASK);
    if (!m_dw) {
      std::cerr << "Failed to create data writer for topic " << topicInfo->name << std::endl;
      return;
    }
  }
} // End TopicReplayer::TopicReplayer
void TopicReplayer::publishSample(const DDS::DynamicData_var sample)
{
  DDS::DynamicDataWriter_var w = DDS::DynamicDataWriter::_narrow(m_dw);
  if (!w) {
    std::cerr << "DataWriter narrowing failed, m_dw is invalid" << std::endl;
    return;
  }
  DDS::ReturnCode_t response = w->write(sample, DDS::HANDLE_NIL);
  if (response != DDS::RETCODE_OK) {

    std::cout << "write() failed; response: " << response << std::endl;
  }
}

If this isn't the kind of repository for these contributions or potential help with them I understand, but I figured I'd offer up the the work I did in case it's wanted/useful (though again I'm not technically a software dev so I'm not sure how useful it is, and it's not fully working due to the errors described).

@sonndinh
Copy link
Member

I haven't read all of this in detail but you can contribute by creating a pull request in GitHub for the changes you have. We can then review and give feedback on them.

@pyphais
Copy link
Author

pyphais commented Oct 22, 2024

I submitted #47, with the disclaimer that I still have those errors that I don't know how to solve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants