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

[FakeSlave] Extend slaves to provide period data for properly testing PDOs #178

Merged
merged 20 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
2 changes: 1 addition & 1 deletion canopen_fake_slaves/config/simple_slave.eds
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,4 @@ PDOMapping=1
ParameterName=UNSIGNED32 sent from slave
DataType=0x0007
AccessType=rwr
PDOMapping=1
PDOMapping=1
Xi-HHHM marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 24 additions & 1 deletion canopen_fake_slaves/include/canopen_fake_slaves/basic_slave.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,19 @@ class SimpleSlave : public canopen::BasicSlave
{
public:
using BasicSlave::BasicSlave;
~SimpleSlave()
{
if (message_thread.joinable())
{
message_thread.join();
}
}

protected:
std::thread message_thread;
Xi-HHHM marked this conversation as resolved.
Show resolved Hide resolved
/**
* @brief This function is called when a value is written to the local object dictionary by an SDO
* or RPDO. Also copies the RPDO value to TPDO.
* or RPDO. Also copies the RPDO value to TPDO. A function from the class Device
* @param idx The index of the PDO.
* @param subidx The subindex of the PDO.
*/
Expand All @@ -49,6 +57,21 @@ class SimpleSlave : public canopen::BasicSlave
uint32_t val = (*this)[idx][subidx];
(*this)[0x4001][0] = val;
this->TpdoEvent(0);
// Publish periodic message
message_thread = std::thread(std::bind(&SimpleSlave::fake_periodic_messages, this));
Xi-HHHM marked this conversation as resolved.
Show resolved Hide resolved
}

void fake_periodic_messages()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please add a short docstring for this method.

{
// If ros is running, send messages
while (rclcpp::ok())
{
uint32_t val = 0x1122;
(*this)[0x4004][0] = val;
this->TpdoEvent(0);
// 40 ms sleep - 25 Hz
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <string>
#include <vector>
#include <queue>

#include "canopen_core/device_container.hpp"
#include "canopen_proxy_driver/proxy_driver.hpp"
Expand Down Expand Up @@ -140,6 +141,38 @@ struct CanopenNodeData

WORos2ControlCoData rsdo; // write-only
WORos2ControlCoData wsdo; // write-only

// Define a FIFO queue for read-only data
std::queue<RORos2ControlCOData> rpdo_data_queue;

// Push data to the queue - FIFO
void set_rpdo_data(ros2_canopen::COData d)
{
RORos2ControlCOData rpdo_data_tmp;
rpdo_data_tmp.set_data(d);
rpdo_data_queue.push(rpdo_data_tmp);
}

// Clear the queue
void clear_rpdo_data()
{
std::queue<RORos2ControlCOData> empty;
std::swap(rpdo_data_queue, empty);
}

// Pop data from the queue
RORos2ControlCOData get_rpdo_data()
{
// If there is nothing new in the queue, return the old data
if (rpdo_data_queue.empty())
{
return rpdo_data;
}
RORos2ControlCOData rpdo_data_tmp;
rpdo_data_tmp = rpdo_data_queue.front();
rpdo_data_queue.pop();
return rpdo_data_tmp;
}
};

class CanopenSystem : public hardware_interface::SystemInterface
Expand Down
16 changes: 13 additions & 3 deletions canopen_ros2_control/src/canopen_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ void CanopenSystem::initDeviceContainer()
// register callback
proxy_driver->register_nmt_state_cb(nmt_state_cb);

// The id here refer to the node id
auto rpdo_cb = [&](ros2_canopen::COData data, uint8_t id)
{ canopen_data_[id].rpdo_data.set_data(data); };
{ canopen_data_[id].set_rpdo_data(data); };
// register callback
proxy_driver->register_rpdo_cb(rpdo_cb);

Expand Down Expand Up @@ -246,8 +247,17 @@ hardware_interface::return_type CanopenSystem::read(

// nmt state is set via Ros2ControlNmtState::set_state within nmt_state_cb

// rpdo is set via RORos2ControlCOData::set_data within rpdo_cb

// rpdo has a queue of messages, we read the latest one
for (auto it = canopen_data_.begin(); it != canopen_data_.end(); ++it)
{
const auto rpdo_data = it->second.get_rpdo_data();

// Assign the latest rpdo data to the state interface
it->second.rpdo_data.index = rpdo_data.index;
it->second.rpdo_data.subindex = rpdo_data.subindex;
it->second.rpdo_data.data = rpdo_data.data;
}

return hardware_interface::return_type::OK;
}

Expand Down
71 changes: 67 additions & 4 deletions canopen_tests/config/canopen_system/simple.eds
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Granularity=1
DynamicChannelsSupported=0
GroupMessaging=0
NrOfRxPDO=1
NrOfTxPDO=1
NrOfTxPDO=2
LSS_Supported=1

[DummyUsage]
Expand Down Expand Up @@ -49,7 +49,7 @@ SupportedObjects=3
3=0x1018

[OptionalObjects]
SupportedObjects=11
SupportedObjects=13
1=0x1003
2=0x1005
3=0x1014
Expand All @@ -60,14 +60,17 @@ SupportedObjects=11
8=0x1400
9=0x1600
10=0x1800
11=0x1A00
11=0x1801
12=0x1A00
13=0x1A01

[ManufacturerObjects]
SupportedObjects=4
SupportedObjects=5
1=0x4000
2=0x4001
3=0x4002
4=0x4003
5=0x4004

[1000]
ParameterName=Device type
Expand Down Expand Up @@ -248,6 +251,49 @@ ParameterName=SYNC start value
DataType=0x0005
AccessType=rw

[1801]
SubNumber=7
ParameterName=TPDO communication parameter 2
ObjectType=0x09

[1801sub0]
ParameterName=highest sub-index supported
DataType=0x0005
AccessType=const
DefaultValue=6

[1801sub1]
ParameterName=COB-ID used by TPDO 2
DataType=0x0007
AccessType=rw
DefaultValue=$NODEID+0x280

[1801sub2]
ParameterName=transmission type 2
DataType=0x0005
AccessType=rw
DefaultValue=0xFF

[1801sub3]
ParameterName=inhibit time 2
DataType=0x0006
AccessType=rw

[1801sub4]
ParameterName=reserved
DataType=0x0005
AccessType=rw

[1801sub5]
ParameterName=event timer 2
DataType=0x0006
AccessType=rw

[1801sub6]
ParameterName=SYNC start value 2
DataType=0x0005
AccessType=rw

[1A00]
ParameterName=TPDO mapping parameter
ObjectType=0x08
Expand All @@ -259,6 +305,17 @@ CompactSubObj=1
NrOfEntries=1
1=0x40010020

[1A01]
ParameterName=TPDO mapping parameter 2
ObjectType=0x08
DataType=0x0007
AccessType=rw
CompactSubObj=1

[1A01Value]
NrOfEntries=1
1=0x40040020

[4000]
ParameterName=UNSIGNED32 received by slave
DataType=0x0007
Expand All @@ -280,3 +337,9 @@ AccessType=rw
ParameterName=INTEGER16 test
DataType=0x0003
AccessType=rw

[4004]
ParameterName=UNSIGNED32 sent from slave 2
DataType=0x0007
AccessType=rwr
PDOMapping=1