-
Notifications
You must be signed in to change notification settings - Fork 1
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
Working to obtain a good movement in the Cartesian space #3
Comments
Things to improve first:
Any suggestion is welcome 😃 |
The old two-limb cartesian controller will be superseded by a brand new trajectory generator, see roboticslab-uc3m/kinematics-dynamics#134. Sadly, the old code is unmaintained and will probably break at current develop.
You can't achieve this with profiled paths such as |
Thanks for your aportations @PeterBowman
My problem is that I can't calculate the inverse kinematics with the solver... (The maximum number of iterations is exceeded) In this example, I am only trying to get the IK from the FW: [success] Acquired rightArmIEncoders interface
[success] Encoder values of right-arm: (31.282951 -14.042175 -10.790863 52.636204 -81.528992 88.488579 )
-> FK of right-arm: (-0.313215 0.032358 0.257216 1.216977 -1.195232 -0.792099 )
[error] ICartesianSolverImpl.cpp:155 invKin(): -5: The maximum number of iterations is exceeded
[ERROR] invKin failed.
-> IK of right-arm: (0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ) Any way to configure the solver to increase the number of iterations or some possible solution? |
|
You could increase it at the cost of spending more time in each waypoint, and perhaps not even reaching a convergent solution. That's actually the main motivation behind introducing a fast IK solver. I was tempted to try the solution described in roboticslab-uc3m/kinematics-dynamics#119 (comment), which should be easier to implement. |
Clarification: I meant here that current BasicTwoLimbCartesianControl and TwoLimbCartesianControlServer controller/server devices are unmaintaned and may undergo notable changes, perhaps even get reworked from scratch. |
@rsantos88 BTW, since you are directly using the solver, you're essentially developing a controller. Therefore, your device or program should be in charge of getting the joint limits from the robot to configure the solver. Here's how it is done in |
Added kinematic limits (right and left arms): roboticslab-uc3m/teo-configuration-files@3c7b1b1 [success] Acquired rightArmIEncoders interface
[success] Encoder values of right-arm: (-22.917389 2.636204 31.810192 15.905096 -22.302277 22.671352 )
[success] Acquired leftArmIEncoders interface
[success] Encoder values of left-arm: (22.917389 -2.636204 -31.810192 -15.905096 22.302277 -22.671352 )
-> FK of right-arm: (-0.118218 -0.380733 -0.184653 -0.011106 1.326649 -0.202441 )
-> FK of left-arm: (-0.118218 0.380733 -0.184653 0.011106 1.326649 0.202441 )
calculating IK...
[error] ICartesianSolverImpl.cpp:155 invKin(): -5: The maximum number of iterations is exceeded
[ERROR] invKin failed.
-> IK of right-arm: (0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ) The values of the KdlSolver are: #define DEFAULT_KINEMATICS "none.ini" // string
#define DEFAULT_NUM_LINKS 1 // int
#define DEFAULT_EPSILON 0.005 // Precision tolerance
#define DEFAULT_DURATION 20 // For Trajectory
#define DEFAULT_MAXVEL 7.5 // unit/s
#define DEFAULT_MAXACC 0.2 // unit/s^2
#define DEFAULT_EPS 1e-9
#define DEFAULT_MAXITER 10000000 //max value: 100000000 I've tried to put a bigger value of |
|
((edited second comment)) |
After doing multiple tests, I have identified the problem... [success] Acquired rightArmIEncoders interface
[success] Encoder values of right-arm: (31.282900 -14.042100 -10.790800 52.636200 -81.528900 88.488500 )
[success] Acquired leftArmIEncoders interface
[success] Encoder values of left-arm: (-31.282900 14.042100 10.790800 -52.636200 81.528900 -88.488500 )
-> FK of right-arm: (0.367654 -0.242313 0.167621 -1.238838 -1.020247 1.369499 )
-> FK of left-arm: (0.367654 0.242313 0.167621 1.238838 -1.020247 -1.369499 )
calculating right-arm IK...
[error] ICartesianSolverImpl.cpp:155 invKin(): -5: The maximum number of iterations is exceeded
[ERROR] invKin failed.
-> IK of right-arm: (0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 ) If I use >>stat
Response: [ccnc] 0.367653642389892 -0.242313427959188 0.167620650405435 -1.23883784251295 -1.02024656675129 1.36949948133935 When I try to do the IK using the >>inv 0.367653642389892 -0.242313427959188 0.167620650405435 -1.23883784251295 -1.02024656675129 1.36949948133935
Response: 31.2829 -14.0421 -10.7908 52.6362 -81.5289 88.4885 on the other hand: >>inv 0.367654 -0.242313 0.167621 -1.238838 -1.020247 1.369499
Response: [fail] and the corresponding message of [debug] RpcResponder.cpp:46 respond(): Got: inv 0.367654 -0.242313 0.167621 -1.238838 -1.020247 1.369499
[error] ICartesianSolverImpl.cpp:155 invKin(): -5: The maximum number of iterations is exceeded
[error] ICartesianControlImpl.cpp:47 inv(): invKin failed. |
Are you sure you're not truncating the numeric result of |
I think not but maybe I'm missing something ... bool BodyExecution::getRightArmFwdKin(std::vector<double> *currentX)
{
/** ----- Obtain current joint position ----- **/
int rightArmAxes;
rightArmIPositionControl2->getAxes(&rightArmAxes);
if (!rightArmDevice.view(rightArmIEncoders) ) { // connecting our device with "IEncoders" interface
printf("[warning] Problems acquiring rightArmIEncoders interface\n");
return false;
} else printf("[success] Acquired rightArmIEncoders interface\n");
std::vector<double> currentQ(rightArmAxes);
if ( ! rightArmIEncoders->getEncoders( currentQ.data() ) ){
printf("[ERROR] getEncoders failed\n");
return false;
}
else
{
printf("[success] Encoder values of right-arm: (");
for(int i=0; i<rightArmAxes; i++)
printf("%f ",currentQ[i]);
printf(")\n ");
}
/** ----- Obtain current cartesian position ---------- **/
if ( ! rightArmICartesianSolver->fwdKin(currentQ, *currentX) ) {
printf("[ERROR] Forward Kinematic failed.\n");
return false;
}
return true;
} |
maybe I'm doing something wrong... because I've also tried to put directly the values obtained of the std::vector<double> vector {0.367653642389892, -0.242313427959188, 0.167620650405435, -1.23883784251295, -1.02024656675129, 1.36949948133935};
if ( ! rightArmICartesianSolver->invKin(vector, desireX, desireQ) ) {
printf("[ERROR] invKin failed.\n");
}
printf("-> IK of right-arm: (");
for(int i=0; i<desireX.size(); i++)
printf("%f ",desireX[i]);
printf(")\n "); it shows the same error message... |
Even if the cartesian-space input values are equal ( |
Thanks a lot for your help. |
Soon, we'll make this simpler so that both algorithms could be loaded (not at once, obviously) without having to recompile the device. See roboticslab-uc3m/kinematics-dynamics#155. |
At the moment, the demonstration allow us to move the tray using dual arms in the three cartesian axes position moving it in two modalities:
The result can be seen in the following video with simulation and the real robot. The biggest problem is that not all the joints end at the same time, avoiding a perfect linear movement. |
This is an interesting problem :). Just laying out what I would do, perhaps you can find some of these ideas useful:
As you can see, this recipe is essentially the same one as described in the "beatiful scheme". |
Thank you for all of your contributions. @PeterBowman , I'm sure that I can improve my code (I know you are very purist with this 😅), but I think I'm on the right track. I've followed your steps and this is the function that contains all the concoction. The problem that I was finding was of overshoot due to a pretty big gain used to correct the error. I used Some curious observation: the CPU must be free of other process running at the same time, because otherwise, the behavior in the movement can vary a lot, possibly because the control does not perform it in the time it should do. Maybe it can be interesting to do the process in other different thread? After that, I did the same tests on the real robot, but the result was a big disorientation of TCPs. You can share your impressions!! |
Interesting! By the way,
There is no delay (
That's presumably the lack of a stop command (this won't work, as you noticed - see roboticslab-uc3m/yarp-devices#120). Try switching to position control mode (ref), but don't forget to get back to velocity before the next iteration. |
Thank you for all your reports @PeterBowman .
It's true. But I only have tested this last changes in the simulator. The difference are priceless.
Ok, I've fixed this obviousness here and here
Ok. My mistake was thinking that I need to refresh in each cycle the current position of the joints: rightArmCurrentQ and leftArmCurrentQ but I've noticed that I can put a delay that exactly takes the period of time that we want to make a correction. This was the problem that caused an excessive use of CPU (permanent checkpoint condition check).
Following this reference, I've change the period, doubling the value of resolution variable to
Yes! It's the best solution to be sure that the joints stop completely. I have helped myself with this change of mode, implementing the functions configAllDevicesToPosition and configAllDevicesToVelocity. The result in simulation is very cool! (smooth and without parkinson xD) but I don't know what wonders can happen in the real robot |
It's probably better to rename the
Just a word of caution: all these calculations take their time and you are currently not accounting for it in In a rapid recap, I noticed that this demo of short, linearly controlled trajectories - as it currently is - could be entirely implemented with a sequence of |
I wrote a script that should help you in obtaining the transformation matrix between the gripper and the tray center, for both arms. Launch TEO on the simulator and move the robot to the desired pose (e.g. via RPC). Then, run this: import yarp
import kinematics_dynamics
import numpy as np
import scipy.linalg as lin
yarp.Network.init()
options = yarp.Property()
options.put('device','CartesianControlClient')
options.put('cartesianRemote','/teoSim/leftArm/CartesianControl')
options.put('cartesianLocal','/cc/teoSim/leftArm')
ddLeft = yarp.PolyDriver(options)
options.put('cartesianRemote','/teoSim/rightArm/CartesianControl')
options.put('cartesianLocal','/cc/teoSim/rightArm')
ddRight = yarp.PolyDriver(options)
iccLeft = kinematics_dynamics.viewICartesianControl(ddLeft)
iccRight = kinematics_dynamics.viewICartesianControl(ddRight)
xLeft = yarp.DVector()
xRight = yarp.DVector()
iccLeft.stat(xLeft)
iccRight.stat(xRight)
# N: gripper
H_left_0_N = np.eye(4)
H_right_0_N = np.eye(4)
# https://stackoverflow.com/a/25709323
axis2dcm = lambda(axis): lin.expm3(np.cross(np.eye(3), axis))
H_left_0_N[:3,:3] = axis2dcm(xLeft[3:])
H_left_0_N[:3,3] = xLeft[:3]
H_right_0_N[:3,:3] = axis2dcm(xRight[3:])
H_right_0_N[:3,3] = xRight[:3]
# T: tray
H_left_0_T = np.eye(4)
H_right_0_T = np.eye(4)
H_left_0_T[:3,3] = [xLeft[0], 0, xLeft[2]]
H_right_0_T[:3,3] = [xRight[0], 0, xRight[2]]
H_left_N_T = np.dot(lin.inv(H_left_0_N), H_left_0_T)
H_right_N_T = np.dot(lin.inv(H_right_0_N), H_right_0_T)
# from yarp::math::dcm2axis
def dcm2axis(rot):
axis = np.array([rot[2,1] - rot[1,2], rot[0,2] - rot[2,0], rot[1,0] - rot[0,1]])
norm = lin.norm(axis)
return (1.0 / norm) * axis * np.arctan2(0.5 * norm, 0.5 * (rot.trace() - 1))
twist_left_N_T = np.append(H_left_N_T[:3,3], dcm2axis(H_left_N_T[:3,:3]))
twist_right_N_T = np.append(H_right_N_T[:3,3], dcm2axis(H_right_N_T[:3,:3]))
# update tool coordinates
iccLeft.tool(yarp.DVector(twist_left_N_T))
iccRight.tool(yarp.DVector(twist_right_N_T))
# perform FK
iccLeft.stat(xLeft)
iccRight.stat(xRight)
# sample output (rounded and prettified):
# xLeft = xRight = [0.368 0.0 0.168 0.0 0.0 0.0]
ddLeft.close()
ddRight.close()
yarp.Network.fini() Tested with:
For the record:
Same info in DCM format at #3 (comment). |
I have tweaked the keyboardController app from kin-dyn for use by TEO: roboticslab-uc3m/kinematics-dynamics@aeddf84. Now, cartesian commands (joint commands are disabled) will move both arms at once, assuming that their TCPs have been properly configured (see previous comment). |
Thank you so much @PeterBowman !! 😃😃👏👏 |
Add this to
...and this to
|
I'm sure it will be very useful. Thanks!! I've upload this changes upload here: roboticslab-uc3m/teo-configuration-files@c871771 |
I am going to update the state of this issue: Thanks to the improvements made in roboticslab-uc3m/kinematics-dynamics@d2afc5e the problem with joint limits was solved. Now, when a joint reaches its limit, the kinematic chain stops totally. Then, we tried to move the arm using movl because here there is a control loop closed. In the same way, @PeterBowman made an experimental implementation of this control over movv. The result improved when moving it on the Y axis but not on the X axis. On the other hand, @PeterBowman told me the possibility of trying the movement using streaming commands of movement like pose. I tried it in my application. The result was great in the simulator as usual, but the same problem in the real robot. Therefore, this is the issue. @PeterBowman and @jgvictores are working to solve this problems here: roboticslab-uc3m/kinematics-dynamics#166 and maybe in another opened issues. |
I've done some experiments with IPositionDirect to see the results. In the simulation, the movement is really good and fast behavior, depending on the number of points in which we divide our trajectory. [debug] IControlMode2Impl.cpp:55 setControlModes(): (6)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (0, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (1, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (2, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (3, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (4, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (5, 1685286768)
[WARNING]number of streaming intput messages to be read is 77 and can overflow
[WARNING]number of streaming intput messages to be read is 73 and can overflow
[WARNING]number of streaming intput messages to be read is 61 and can overflow
[WARNING]number of streaming intput messages to be read is 55 and can overflow
[WARNING]number of streaming intput messages to be read is 44 and can overflow
[WARNING]number of streaming intput messages to be read is 31 and can overflow
[debug] IControlMode2Impl.cpp:55 setControlModes(): (6)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (0, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (1, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (2, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (3, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (4, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (5, 1685286768)
[WARNING]number of streaming intput messages to be read is 38 and can overflow
[WARNING]number of streaming intput messages to be read is 56 and can overflow
[WARNING]number of streaming intput messages to be read is 49 and can overflow
[WARNING]number of streaming intput messages to be read is 37 and can overflow
[WARNING]number of streaming intput messages to be read is 25 and can overflow
[debug] IControlMode2Impl.cpp:55 setControlModes(): (6)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (0, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (1, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (2, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (3, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (4, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (5, 1685286768)
[WARNING]number of streaming intput messages to be read is 51 and can overflow
[WARNING]number of streaming intput messages to be read is 38 and can overflow
[WARNING]number of streaming intput messages to be read is 25 and can overflow
[debug] IControlMode2Impl.cpp:55 setControlModes(): (6)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (0, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (1, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (2, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (3, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (4, 1685286768)
[debug] IControlMode2Impl.cpp:44 setControlMode(): (5, 1685286768)
[WARNING]number of streaming intput messages to be read is 68 and can overflow
[WARNING]number of streaming intput messages to be read is 75 and can overflow
[WARNING]number of streaming intput messages to be read is 63 and can overflow
[WARNING]number of streaming intput messages to be read is 51 and can overflow
[WARNING]number of streaming intput messages to be read is 39 and can overflow
[WARNING]number of streaming intput messages to be read is 30 and can overflow We can achieve a smoother and slower movement, dividing even more the points of the trajectory, for example to 1000: I've tried to check what happen in the real robot. At the moment, when the movement is going to be executed, the arm hits a small blow, the drivers' LEDs can be seen in red and the arm suddenly falls and it loses the control. |
|
Ok, I've been doing different tests in order to check the correct PositionDirect operation and analyze the failures using this code: #include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <yarp/os/all.h>
#include <yarp/dev/all.h>
using namespace yarp::os;
using namespace yarp::dev;
int main(int argc, char *argv[]) {
printf("WARNING: requires a running instance of OneCanBusOneWrapper\n");
Network yarp;
if (!Network::checkNetwork()) {
printf("Please start a yarp name server first\n");
return(-1);
}
Property options;
options.put("device","remote_controlboard"); //remote_controlboard
options.put("remote","/wrapper0");
options.put("local","/local");
PolyDriver dd(options);
if(!dd.isValid()) {
printf("RaveBot device not available.\n");
dd.close();
Network::fini();
return 1;
}
IPositionDirect *posdir;
IVelocityControl2 *vel;
IEncodersTimed *enc;
IControlMode2 *mode;
bool ok = true;
ok &= dd.view(posdir);
ok &= dd.view(enc);
ok &= dd.view(mode);
if (!ok) {
printf("[warning] Problems acquiring robot interface\n");
return false;
} else printf("[success] acquired robot interface\n");
mode->setControlMode(0, VOCAB_CM_POSITION_DIRECT);
printf("test positionDirect\n");
for(float f=0.01; f<40; f+=0.5)
{
printf("moving position direct: (%f)\n",f);
posdir->setPosition(0,f);
yarp::os::Time::delay(0.05);
}
return 0;
} In it I try to configure the Ipos to On the other hand there is an instance of oneCanBusOneWrapper with the following configuration of the /// oneCanBusOneWrapper.ini ///
[devCan0]
device CanBusControlboard
canDevice /dev/pcan2
canBusType CanBusPeak
canBitrate 1000000
types TechnosoftIpos
ids 18
maxs 83.5
mins -32.9
trs 160
refAccelerations 10.0
refSpeeds 10.0
encoderPulsess 4096
[wrapper0]
device controlboardwrapper2
name /wrapper0
period 60
joints 1
networks (devCan0)
devCan0 0 0 0 0 It works great!! |
None of these options is the implemented solution. The iPos implementation is an intermediate solution, essentially a FIFO memory with 8 buffer positions (would have to check the iPos manual for the specific correct value). So, you start filling it in, once it is initially full you start running, and then continue feeding it targets (e.g. via CAN-bus) at the rate established by the fixed period.
Hence, best to feed it at the most precise rate possible. Take into account that a PeriodicThread (YARP's old In the current implementation, this is set when we instance the CanBusControlboard class and may be modified via --ptModeMs. I guess you'll be asking if there is a minimum threshold. The answer is yes, and this minimum should be estimated by the time consumed by CAN-bus communications to feed all the individual drivers per period. |
The only restriction on increment/time is velocity. The current line and comment says |
Please, refer to CanOpen Programming Manual (P091.063.CANopen.iPOS.UM), chapter 9.2. (P091.063.CANopen.iPOS.UM.pdf). |
From 9.2.8:
In our implementation, Sorry if I wasn't paying sufficient attention, @rsantos88, but to reproduce today's failed attemps:
Is that close to the observed behavior? |
Yes, totally like that. #include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <yarp/os/all.h>
#include <yarp/dev/all.h>
#define JOINT 3
using namespace yarp::os;
using namespace yarp::dev;
int main(int argc, char *argv[]) {
printf("WARNING: requires a running instance of launchManipulation\n");
Network yarp;
if (!Network::checkNetwork()) {
printf("Please start a yarp name server first\n");
return(-1);
}
Property options;
options.put("device","remote_controlboard"); //remote_controlboard
options.put("remote","/teo/rightArm");
options.put("local","/local");
PolyDriver rightArm(options);
if(!rightArm.isValid()) {
printf("RightArm device not available.\n");
rightArm.close();
Network::fini();
return 1;
}
IPositionDirect *posdir;
IPositionControl2 *pos;
IVelocityControl2 *vel;
IEncoders *enc;
IControlMode2 *mode;
bool ok = true;
ok &= rightArm.view(posdir);
ok &= rightArm.view(pos);
ok &= rightArm.view(enc);
ok &= rightArm.view(mode);
if (!ok) {
printf("[warning] Problems acquiring robot interface\n");
return false;
} else printf("[success] acquired robot interface\n");
/** Axes number **/
int numJoints;
printf("-- testing POSITION MODE --\n");
pos->getAxes(&numJoints);
std::vector<int> positionMode(numJoints,VOCAB_CM_POSITION);
if(! mode->setControlModes(positionMode.data())){
printf("[warning] Problems setting position control: POSITION \n");
return false;
}
printf("moving joint 0 to 10 degrees...\n");
pos->positionMove(JOINT, 10);
getchar();
printf("-- testing POSITION DIRECT --\n");
posdir->getAxes(&numJoints);
std::vector<int> positionDirectMode(numJoints,VOCAB_CM_POSITION_DIRECT);
if(! mode->setControlModes(positionDirectMode.data())){
printf("[warning] Problems setting position control: POSITION_DIRECT \n");
return false;
}
double encValue;
if ( ! enc->getEncoder(JOINT,&encValue) ){
printf("[ERROR] Failed getEncoders of right-arm\n");
return false;
}
printf("Current ENC value: %f\n", encValue);
getchar();
// vector with the degrees
std::vector<double> jointPosition(numJoints); // vector de 6 joints
while(encValue<=20)
{
encValue+=0.1;
jointPosition[JOINT] = encValue;
printf("-> Joint position of right-arm: (");
for(int i=0; i<jointPosition.size(); i++)
printf("%f ",jointPosition[i]);
printf(")\n ");
std::vector<double> jointPath(&jointPosition[0], &jointPosition[0]+7); //teoSim (+6) teo (+7)
posdir->setPositions(jointPath.data());
yarp::os::Time::delay(0.05); //0.05
}
return 0;
} Note: Don't take into account the use of |
This problem has been fixes now here roboticslab-uc3m/yarp-devices#197 |
More issues with the |
Okay, a "good" movement in the cartesian space has been achieved: This clip shows exampleScrewTheoryTrajectory run on real TEO. I generate a linear path following a trapezoidal velocity profile, much like with a point-to-point CMC-controlled Keep roboticslab-uc3m/yarp-devices#198 in mind when developing applications. For now, my keyboardController app has to be carefully instantiated due to a kinda faulty mode change. |
I would like to resume the use of this script to obtaining the transformation matrix between the gripper and the tray center, for both arms. The pose I'm leaving to get this data in joint position is:
When I run the python script, the result values calculated are: [ 0.23194013 0.01027258 -0.00223408 -1.77420782 1.72593331 1.79445854]
[ 0.23194013 -0.01027258 -0.00223408 1.77420782 1.72593331 -1.79445854] So, I've put it in my code using appendLink function to change the TCP in booth arms, but when I've checked the forward kinematic, It should show the same values for both arms (unifying the TCP). The values are the same but the signs do not match in some cases.. -> Origin Pose of left-arm: (0.365755 -0.000000 0.214345 -0.536150 0.529716 0.552422 )
-> Origin Pose of right-arm: (0.365755 0.000000 0.214345 0.536150 0.529716 -0.552422 ) |
@rsantos88 I've fixed that script, please check it again. |
Thank you so much @PeterBowman for fixing the script and for your explanations yesterday 😃 |
Due to the problems mentioned in velocity mode #3 (comment) , @smcdiaz told me to do a the test of commanding a joint in speed and check if it maintains the position. As you can see, the motor tries to maintain that speed (3 degrees per second) until it slows down as an effect of the force of gravity. If I apply a force in the direction of movement, the joint keeps moving. |
Our low level controllers have seen several improvements in the last two years, new control modes have been enabled and help can be found in examples and tutorials: roboticslab-uc3m/yarp-devices#254 (comment).
Coordinated dual-arm motion in cartesian space is now possible, see roboticslab-uc3m/kinematics-dynamics#190 (comment). I presume the original problem has been already solved. If that is not correct, I'd suggest to open a new issue on a single, specific topic. For the record, this script could be used in future demos: #3 (comment). |
At this moment, we've a bimanipulation demostration that works doing this things:
This is a video of the result, working with teoSim (openrave):
The text was updated successfully, but these errors were encountered: