我正在尝试编写一个机器人以获取乐趣。我想添加一个自主循环,以便机器人可以遵循一组预设命令并自行驱动。问题是,机器人的每个子系统都是不同的类,我希望能够创建一个类似这样的函数:
DoFunctionForMe(start_time, end_time, function, start_arguments, end_arguments);
我想要
DoFunctionForMe
做的是在开始时间执行带有开始参数的函数,并在结束时间执行结束参数。
例如,我可以有以下内容,从时间 1 行驶到时间 8,并从时间 7 行驶到时间 9:
void Robot::AutoMainLoop(){
DoFunctionForMe(1,8,Drive,{12,12},{0,0});
DoFunctionForMe(7,9,Move,{1,0},{0,0});
}
这是我迄今为止的代码的近似值:
class Drivetrain{
public:
Drivetrain();
void Drive(int forward, int left){
drive(forward, left); // Drives the robot, more complex than this
}
}
class Mechanism{
public:
Mechanism();
void Move(int up, int down){
move(up, down); // Moves the arm, more complex than this
}
}
class Robot{
public:
void DrivenMainLoop(); // Operated by a person
void AutoMainLoop(); // Robot operates itself
private:
Drivetrain m_drivetrain{};
Mechanism m_mechanism{};
}
void Robot::DrivenMainLoop(){
m_drivetrain.Drive(2,12);
m_mechanism.Move(1,0);
}
void Robot::AutoMainLoop(){
// help
}
我有办法做到这一点吗?
我尝试过使用指向函数的指针,但我不太明白我在那里做什么,并且它给了我错误,例如
a pointer to a bound function may only be used to call the function
您的
Drive
和 Move
方法是单独类的非静态成员。您必须使用 std::bind()
+std::function
或 lambda,以便 DoFunctionForMe()
在不知道它们来自哪些对象的情况下调用它们,例如:
class Drivetrain{
public:
Drivetrain();
void Drive(int forward, int left){
...
}
};
class Mechanism{
public:
Mechanism();
void Move(int up, int down){
...
}
};
class Robot{
public:
void DrivenMainLoop(); // Operated by a person
void AutoMainLoop(); // Robot operates itself
private:
Drivetrain m_drivetrain{};
Mechanism m_mechanism{};
};
...
void DoFunctionForMe(int start_time, int end_time, std::function<void(int,int)> the_function, int[] start_arguments, int[] end_arguments) {
...
the_function(...);
...
}
/* or:
template<typename Callable>
void DoFunctionForMe(int start_time, int end_time, Callable the_function, int[] start_arguments, int[] end_arguments) {
...
the_function(...);
...
}
*/
void Robot::AutoMainLoop(){
using namespace std::placeholders;
auto drive = std::bind(&Drivetrain::Drive, &m_drivetrain, _1, _2);
DoFunctionForMe(1, 8, drive, ...);
auto move = std::bind(&Mechanism::Move, &m_mechanism, _1, _2);
DoFunctionForMe(7, 9, move, ...);
// or:
DoFunctionForMe(1, 8, [&](int arg1, int arg2){ m_drivetrain.Drive(arg1, arg2); }, ...);
DoFunctionForMe(7, 9, [&](int arg1, int arg2){ m_mechanism.Move(arg1, arg2); }, ...);
}
或者,您可以使
Drivetrain
和 Mechanism
继承自一个公共基类,该基类定义了它们都重写的 virtual
方法,然后您可以使 DoFunctionForMe()
通过多态性对该基类进行操作,例如:
class Actionable{
public:
virtual void DoAction(int arg1, int arg2) = 0;
};
class Drivetrain : public Actionable {
public:
Drivetrain();
void Drive(int forward, int left){
...
}
void DoAction(int arg1, int arg2) override{
Drive(arg1, arg2);
}
};
class Mechanism : public Actionable {
public:
Mechanism();
void Move(int up, int down){
...
}
void DoAction(int arg1, int arg1) override{
Move(arg1, arg2);
}
};
class Robot{
public:
void DrivenMainLoop(); // Operated by a person
void AutoMainLoop(); // Robot operates itself
private:
Drivetrain m_drivetrain{};
Mechanism m_mechanism{};
};
...
...
void DoFunctionForMe(int start_time, int end_time, Actionable *actionable, int[] start_arguments, int[] end_arguments) {
...
actionable->DoAction(...);
...
}
void Robot::AutoMainLoop(){
DoFunctionForMe(1, 8, &m_drivetrain, ...);
DoFunctionForMe(7, 9, &m_mechanism, ...);
}