我目前正在将rospy IMU驱动程序翻译成roscpp,并且难以确定这段代码的作用以及我如何翻译它。
def ReqConfiguration(self):
"""Ask for the current configuration of the MT device.
Assume the device is in Config state."""
try:
masterID, period, skipfactor, _, _, _, date, time, num, deviceID,\
length, mode, settings =\
struct.unpack('!IHHHHI8s8s32x32xHIHHI8x', config)
except struct.error:
raise MTException("could not parse configuration.")
conf = {'output-mode': mode,
'output-settings': settings,
'length': length,
'period': period,
'skipfactor': skipfactor,
'Master device ID': masterID,
'date': date,
'time': time,
'number of devices': num,
'device ID': deviceID}
return conf
我必须承认,我之前从未使用过ros或python。 这不是来自源代码的1:1代码,我删除了我认为我知道他们做了什么的行,但特别是try-block是我不明白的。我真的很感激帮助,因为我非常珍惜时间。
如果有人好奇(背景原因):我要翻译的文件是mtdevice.py,mtnode.py和mtdef.py,可以找到googleing的文件名+关键字ROS IMU Driver
提前多多感谢。
答案 0 :(得分:2)
这段代码解包C结构的字段,即masterID,句点,跳过因子,_,_,_,日期,时间,数字,设备ID,长度,模式,设置,将它们存储在Python字典中并返回那个词典作为通话结果。下划线是结构中未使用的部分的占位符。
另请参阅:https://docs.python.org/2/library/struct.html,例如有关格式字符串('!IHHHHI8s8s32x32xHIHHI8x')的描述,它告诉解包函数结构是什么样的。
语法a,b,c,d = f()意味着该函数在Python中返回一个名为元组的东西。通过将元组分配给多个变量,它将被分割为其字段。
示例:
t = (1, 2, 3, 4)
a, b, c, d = t
# At this point a == 1, b == 2, c == 3, d == 4
用C ++替换这段代码不应该太难,因为C ++的结构很像C.所以requestConfiguration最简单的C ++实现就是返回那个结构。如果您想更接近Python功能,您的函数可以将结构的字段放入C ++ STL映射并返回。格式字符串+链接指向的文档,告诉您结构中的数据类型以及位置。
请注意,它是保存数据的第二个解包参数,第一个参数只包含有关第二个参数布局(格式)的信息,如链接中所述。第二个参数看起来像Python它是一个字符串,但它实际上是一个C结构。第一个参数告诉Python在哪里找到该结构中的内容。
因此,如果您阅读格式字符串上的文档,则可以找到第二个参数(C struct)的布局。但也许你不需要。这取决于你的函数的调用者。它可能只是期望普通的C结构。
根据您添加的评论,我了解您的功能中的代码比您显示的代码多。结构的字段分配给类的属性。
如果您知道C struct(config)的字段名称,那么可以将它们直接分配给C ++类的属性。
// Pointer 'this' isn't needed but inserted for clarity
this->mode = config.mode;
this->settings = config.settings;
this->length = config.length;
我认为配置结构的字段名称确实是模式,设置,长度等,但您必须验证它。可能在某些C头文件(或文档)中声明了此结构的布局。
答案 1 :(得分:1)
要使用C ++执行相同的操作,您需要使用各种参数声明struct
:
struct DeviceRecord {
uint32_t masterId;
uint16_t period, skipfactor, _a, _b;
uint32_t _c;
char date[8];
char time[8];
char padding[64];
uint16_t num;
uint32_t deviceID;
uint16_t length, mode;
uint32_t settings;
char padding[8];
};
(可能这个结构已经在某处被声明;它也可能使用" unsigned int"而不是" uint32_t"和" unsigned short"而不是" uint16_t"和_a,_b,_c可能有实名。)
获得结构后,问题是如何获取数据。这取决于数据的位置。如果它在文件中,您可以执行以下操作:
DeviceRecord rec; // An instance of the struct, whatever it's called
std::ifstream fin("yourfile.txt", std::ios::binary);
fin.read(reinterpret_cast<char*>(&rec), sizeof(rec));
// Now you can access rec.masterID etc
另一方面,如果它在内存中的某个地方(即你有一个char *或void *),那么你只需要施放它:
void* data_source = get_data(...); // You'd get this from somewhere
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(stat_source);
// Now you can access rec_ptr->masterID etc
如果您有std::vector
,则可以轻松获得指针:
std::vector<uint8_t> data_source = get_data(...); // As above
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(data_source.data());
// Now you can access rec_ptr->masterID etc, provided data_source remains in scope. You should probably also avoid modifying data_source.
这里还有一个问题。您收到的数据是big-endian,但除非您有PowerPC或其他不寻常的处理器,否则您可能使用的是小端机器。因此,在访问数据之前,需要进行一些字节交换。您可以使用以下功能执行此操作。
template<typename Int>
Int swap_int(Int n) {
if(sizeof(Int) == 2) {
union {char c[2]; Int i;} swapper;
swapper.i = n;
std::swap(swapper.c[0], swapper.c[1]);
n = swapper.i;
} else if(sizeof(Int) == 4) {
union {char c[4]; Int i;} swapper;
swapper.i = n;
std::swap(swapper.c[0], swapper.c[3]);
std::swap(swapper.c[1], swapper.c[2]);
n = swapper.i;
}
return n;
}
这些返回交换的值而不是就地更改它,因此现在您可以使用swap_int(rec->num)
之类的内容访问您的数据。注意:上面的字节交换代码未经测试;我稍后会尝试编译它并在必要时修复它。
如果没有更多信息,我无法为您提供明确的方法,但这可能足以帮助您自己解决问题。