I will start with talking about how to access robot status in real-time based on the interface provided by FrankX and libfranka.
https://github.com/pantor/frankx.git
The original version of this package does not provide a implementation on acquiring the state data while robot moving. You have to manually add the changes from Pull requests to your lib, which has instantiated a franka::RobotState asynchronous_state
. Get real-time robot state information by robot.get_state(read_once=False)
while drive it by move_async
. There’s a general limitation (far less than 1000Hz) of sampling rate of this method, it can’t reach the actual control looping frequency from robot, which is reasonable. So maybe it is only useful for just some entry application or without a strict demand on executing frequency.
<aside> ⛔
By the way, wired thing would happen when you try to print out the state information on your terminal after get_state(read_once=Flase)
, the obtained data would be totally random in this situation. You should change the read_once
to True
to get proper output, yet with a drastic decline on sampling rate.
</aside>
https://github.com/frankaemika/libfranka.git
The real-time commands on robot motion can only be generated and sent by Libfranka in its control loop. The motion generation module provided by FrankX is only a one-time thing, mostly used to drive the robot move along certain path points.
Realtime interfaces: motion generators and controllers
Realtime commands are UDP based and require a 1 kHz connection to Control. There are two types of real-time interfaces: a. Motion generators, which define a robot motion in joint or Cartesian space; b. Controllers, which define the torques to be sent to the robot joints. Details instruction to generate real-time commands from libfranka control loop is in here. I have no idea what does it actually mean here by external or internal, but fortunately, I don’t have to really figure it our temporarily. Just follow the instruction below:
try {
franka::Robot robot("<fci-ip>"); // build connect and instantiate the robot
Build a real-time loop (motion generator or controller) by directly defined a callback function in robot.control()
, which receives the robot state in real-time and return the specific types of commands interface.
robot.control(
[=, &time](const franka::RobotState&, franka::Duration period) -> franka::JointVelocities {
time += period.toSec();
double cycle = std::floor(std::pow(-1.0, (time - std::fmod(time, time_max)) / time_max));
double omega = cycle * omega_max / 2.0 * (1.0 - std::cos(2.0 * M_PI / time_max * time));
franka::JointVelocities velocities = {{0.0, 0.0, 0.0, omega, omega, omega, omega}};
if (time >= 2 * time_max) {
std::cout << std::endl << "Finished motion, shutting down example" << std::endl;
return franka::MotionFinished(velocities);
}
return velocities;
});
This registered control
method of the franka::Robot
class will then run the control loop automatically by executing the callback function at a 1 kHz frequency. All control loops are finished once the motion_finished
flag of a real-time command is set to true
. As in this example, it uses the joint velocity motion generator interface, as it returns a franka::JointVelocities
object. Note that if you use only a motion generator, the default controller is the internal joint impedance controller. We don’t actually have to care about this, according the demands so far from the previous page, the only thing left to do is to build another CartesianVelocities
based motion generator in control loop.
Before getting into the details, you need to first prepare the computer to connect with the Franka robot. I will skip some details here.