dqrobotics / cpp Goto Github PK
View Code? Open in Web Editor NEWThe DQ Robotics library in C++
Home Page: https://dqrobotics.github.io
License: GNU Lesser General Public License v3.0
The DQ Robotics library in C++
Home Page: https://dqrobotics.github.io
License: GNU Lesser General Public License v3.0
Bug description
Hello, @bvadorno,
I am currently working with the DQ_WholeBody serializing two legs in order to perform a walking algorithm. One of my steps is to calculate the center of mass of the serialized chain. My approach for such calculation starts with the intermediate transformations of each link of the serialized chain. However, when I use functionality fkm(q,joint) it does not work properly.
To Reproduce
I used the code in the two_legs_example to create a minimal example.
Code
% Include the DQ namespace to use i_ instead of DQ.i, etc.
include_namespace_dq
% The legs are composed of two KUKA LWR4 robots coupled together
right_leg = KukaLwr4Robot.kinematics();
right_leg.name = 'Right leg';
left_leg = KukaLwr4Robot.kinematics();
left_leg.name = 'Left leg';
% The left foot will be located 20 cm to the left, along the x axis,
% but with the z-axis pointing downwards.
left_foot = (1 - E_ * 0.5 * 0.2 * i_) * i_;
% The right foot will be located 20 cm to the right, along the x axis,
% but with the z-axis pointing downwards.
right_foot = (1 + E_ * 0.5 * 0.2 * i_) * i_;
% Physically place the left leg in the workspace
x_0_to_left_effector = left_leg.fkm(zeros(7,1));
new_base_frame = left_foot .* T(x_0_to_left_effector);
left_leg.set_base_frame(new_base_frame);
% Physically place the right leg in the workspace
x_0_to_right_effector = right_leg.fkm(zeros(7,1));
new_base_frame = right_foot .* T(x_0_to_right_effector);
right_leg.set_base_frame(new_base_frame);
%% Initializes the robot serially coupled kinematic chain from the mobile base
left_to_right = DQ_WholeBody(left_leg, 'reversed');
% The base frame is the left foot. The reference frame, also located at
% the left foot, provides the transformation with respect to the global
% frame. Therefore, any element in the chain will be given with respect
% to the global frame.
left_to_right.set_reference_frame(left_foot);
left_to_right.set_base_frame(left_foot);
% Determines the rigid transformation between the base frames of the
% two legs
base_left_to_base_right = left_leg.base_frame'*right_leg.base_frame;
% Add this constant transformation to the chain
left_to_right.add(base_left_to_base_right);
% Finally, add the right frame
left_to_right.add(right_leg);
q = zeros(14,1);
x1 = left_to_right.fkm(q,1)
x2 = left_to_right.fkm(q,2)
x3 = left_to_right.fkm(q,3)
x4 = left_to_right.fkm(q,4)
x5 = left_to_right.fkm(q,5)
x6 = left_to_right.fkm(q,6)
Output
x1 =
(1i) + E*(0.1 + 0.55j)
x2 =
(1i) + E*( - 0.1 + 0.55j)
x3 =
(1i) + E*( - 0.1)
Index exceeds matrix dimensions.
Error in DQ_WholeBody/raw_fkm (line 170)
if isa(obj.chain{i}, 'DQ_Kinematics')
Error in DQ_WholeBody/fkm (line 142)
x = obj.reference_frame * raw_fkm(obj,q,ith);
Error in issue_FKM_minimal_example (line 52)
x4 = left_to_right.fkm(q,4)
Expected behavior
Expected output
This is the output of the left leg frames without serialization.
x1 =
(0.70711 + 0.70711i) + E*(0.1096j + 0.1096k)
x2 =
(1) + E*(0.155k)
x3 =
(0.70711 - 0.70711i) + E*( - 0.25102j + 0.25102k)
x4 =
(1) + E*(0.355k)
x5 =
(0.70711 + 0.70711i) + E*(0.38891j + 0.38891k)
x6 =
(1) + E*(0.55k)
Environment:
Context: There are several utility functions that might be useful in the current development as they increase code readability, brevity, and interoperability between DQ objects and standard types.
For instance, suppose that we have a DQ object dq
such that dq = 1.5
. If a given function accepts double
parameters, instead of doing dq.q(1)
in Matlab (or dq.q(0)
in C++), it is more appropriate to cast that object to double (i.e.,double(dq)
). In addition to providing a cleaner code, we end up with an exact code for both Matlab and C++ without having to worry about indexes, which are different across different languages. (This link shows how to overload typecasts in C++).
For sure, such a cast only makes sense (at least from a semantic point of view), if the DQ objectdq
corresponds to a 'strict' real number; that is, a real number with imaginary part equal to zero and dual part equal to zero too. Therefore, in order to increase readability we should also implement functions to verify if a dual quaternion is real, pure, a quaternion, etc.
Suggestion:
double
is_pure
(1 if real part is 0 and 0 otherwise)is_real
(1 if imaginary part is 0 and 1 otherwise)is_real_number
(1 if imaginary and dual parts are 0 and 0 otherwise)is_quaternion
(1 if dual part is 0 and 0 otherwise)is_pure_quaternion
(1 if is_pure
and is_quaternion
, 0 otherwise)is_line
(1 if is_pure
and is_unit
, 0 otherwise)is_plane
(1 if is_unit
and is_real(D(x))
)Hi @mmmarinho, I spotted a small typo. I'm certain that I will forget about it if I don't write about it here.
Bug description
There is a small typo in DQ_QuadraticProgrammingController.cpp (line 70). It is written "feedoforward" instead of "feedforward".
Current:
throw std::runtime_error("Incompatible sizes between task error and feedoforward in compute_tracking_control_signal");
Instead of:
throw std::runtime_error("Incompatible sizes between task error and feedforward in compute_tracking_control_signal");
Code
DQ_QuadraticProgrammingController.cpp
Environment:
Hi, @mmmarinho,
The variable is_stable_
and the method is_stable()
in DQ_KinematicController
are not appropriate as 'stability' is an expression in control theory with a very precise meaning. To reflect in C++ the renaming of those variable and method that I did in Matlab, could you please change them to system_reached_stable_region_
and system_reached_stable_region()
, respectively?
Cheers,
Bruno
Hello @mmmarinho, I am having the following bug.
Bug description
To Reproduce
Code
issue_get_task_variable.cpp
#include <iostream>
#include <vector>
#include <dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include "Jaco.h"
#include <dqrobotics/robot_control/DQ_QuadraticProgrammingController.h>
#include <dqrobotics/robot_control/DQ_ClassicQPController.h>
#include <dqrobotics/solvers/DQ_CPLEXSolver.h>
using namespace DQ_robotics;
void test_issue()
{
// Measured joint angles
VectorXd qm(6);
qm << 7.60284, 3.46782, 1.38851, 3.56359, 11.2361, -4.54074;
DQ_SerialManipulator jaco = Jaco::kinematics();
// Constrained QP controller
DQ_CPLEXSolver cplex_solver;
DQ_ClassicQPController controller(&jaco, &cplex_solver);
controller.set_stability_threshold(0.0001);
controller.set_damping(0.01);
controller.set_control_objective(ControlObjective::DistanceToPlane);
controller.set_stability_counter_max(100);
// Target plane
DQ p_plane1;
p_plane1 = -0.4897*DQ_robotics::k_;
const double phi_plane1 = 0.0;
const DQ n_plane1(0.0, 1.0, 1.0, 1.0);
const DQ r_plane1 = cos(phi_plane1/2) + n_plane1*sin(phi_plane1/2);
const DQ kplane1 = r_plane1 + DQ_robotics::E_*(0.5)*p_plane1*r_plane1;
const DQ plane1 = Adsharp(kplane1,DQ_robotics::k_);
controller.set_target_primitive(plane1);
const DQ task_variable = controller.get_task_variable(qm);
// Task reference
const DQ task_reference(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
std::cout << "task_variable " << controller.get_task_variable(qm) << "\n";
std::cout << "task_variable DQ " << task_variable << "\n";
const VectorXd u_qdot = controller.compute_setpoint_control_signal(qm, VectorXd::Zero(1));
}
int main(void)
{
test_issue();
return 0;
}
Jaco.cpp
#ifndef DQ_ROBOTICS_JACO_DH_H
#define DQ_ROBOTICS_JACO_DH_H
#include "Jaco.h"
#include<dqrobotics/utils/DQ_Constants.h>
namespace DQ_robotics
{
DQ_SerialManipulator Jaco::kinematics()
{
const double pi2 = pi/2.0;
// Parameters reference:
// https://www.kinovarobotics.com/sites/default/files/ULWS-RA-JAC-UG-INT-EN%20201804-1.0%20%28KINOVA%E2%84%A2%20Ultra%20lightweight%20robotic%20arm%20user%20guide%29_0.pdf
double D1 = 0.2755;
double D2 = 0.4100;
double D3 = 0.2073;
double D4 = 0.0741;
double D5 = 0.0741;
double D6 = 0.1600;
double e2 = 0.0098;
double aa = (30.0*pi)/180.0;
double sa = sin(aa);
double s2a = sin(2*aa);
double d4b = D3 + (sa/s2a)*D4;
double d5b = (sa/s2a)*D4 + (sa/s2a)*D5;
double d6b = (sa/s2a)*D5 + D6;
Matrix<double,4,6> jaco_dh(4,6);
jaco_dh << 0, pi2, pi2, 0, 0, 0,
-0.1188, 0, 0, -0.252, -0.079, -0.04,
0, -0.41, 0, 0, 0, 0,
-pi2, -pi, -pi2, -0.3056*pi, 0.3056*pi, pi;
DQ_SerialManipulator jaco(jaco_dh,"standard");
return jaco;
}
}
#endif
Jaco.h
#ifndef DQ_ROBOTS_JACO_H
#define DQ_ROBOTS_JACO_H
#include<dqrobotics/robot_modeling/DQ_SerialManipulator.h>
namespace DQ_robotics
{
class Jaco
{
public:
static DQ_SerialManipulator kinematics();
};
}
#endif
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(issue_get_task_variable)
# find_package (Threads REQUIRED)
set (CMAKE_CXX_STANDARD 11)
# add_compile_options(-std=c++14)
set( CPLEX_PATH /opt/ibm/ILOG/CPLEX_Studio129 )
add_definitions(-DIL_STD)
link_directories(
${CPLEX_PATH}/cplex/lib/x86-64_linux/static_pic
${CPLEX_PATH}/concert/lib/x86-64_linux/static_pic
${CPLEX_PATH}/bin/glnxa64
)
include_directories(
${CPLEX_PATH}/concert/include
${CPLEX_PATH}/cplex/include
)
add_executable(${PROJECT_NAME} issue_get_task_variable.cpp)
add_library(Jaco
Jaco.cpp
)
target_link_libraries(${PROJECT_NAME}
# pthread
# Threads::Threads
Jaco
-ldqrobotics
ilocplex
cplex
concert
m
pthread
${CMAKE_DL_LIBS}
# dl
)
Output
task_variable 0
task_variable DQ 0 0i 0j 0k +E( 0 0i 0j 0k )
Going to solve quadratic program!
Expected behavior
Since the ControlObjective::DistanceToPlane is being used, the get_task_variable() should return a VectorXd with a size of 1. The returning value should be the point_to_plane_distance() between the robot effector and the target_primitive_. This is expected, as it can be seen in the get_task_variable() method in DQ_KinematicController.cpp.
However, I tried different values of p_plane1
and the get_task_variable() is always returning zero for the given qm
.
Expected output
task variable <value possibly different from zero>
task_variable DQ <non-zero DQ>
Going to solve quadratic program!
Environment:
Best regards,
Marcos
Hello @mmmarinho, would it be possible to add the DistanceToPlane control objective to the C++ implementation?
Describe the missing/unexpected functionality
The DistanceToPlane control objective is missing on the C++ implementation.
Matlab behavior (if applicable)
No execution errors occur.
MATLAB SCRIPT
clc
close all
clear all
include_namespace_dq
kuka = KukaLwr4Robot.kinematics();
solver = DQ_QuadprogSolver;
plane = k_;
controller = DQ_ClassicQPController(kuka,solver);
controller.set_gain(10);
controller.set_stability_threshold(0.0001);
controller.set_damping(0.01);
controller.set_control_objective(ControlObjective.DistanceToPlane);
controller.set_max_stability_counter(100);
controller.set_target_primitive(plane);
MATLAB OUTPUT
<No output expected>
C++ behavior (if applicable)
The control objective DistanceToPlane is not found.
The method set_max_stability_counter is not found.
The method set_target_primitive is not found.
C++ Code
#include <iostream>
#include <dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include <dqrobotics/robots/KukaLw4Robot.h>
#include <dqrobotics/robot_control/DQ_QuadraticProgrammingController.h>
#include <dqrobotics/robot_control/DQ_ClassicQPController.h>
#include <dqrobotics/solvers/DQ_CPLEXSolver.h>
using namespace DQ_robotics;
void test_issue()
{
const DQ plane = DQ_robotics::k_;
DQ_SerialManipulator robot = KukaLw4Robot::kinematics();
// Constrained QP controller
DQ_CPLEXSolver cplex_solver;
DQ_ClassicQPController controller(&robot, &cplex_solver);
controller.set_control_objective(ControlObjective::DistanceToPlane);
controller.set_gain(10.0);
controller.set_damping(0.01);
controller.set_max_stability_counter(100);
controller.set_target_primitive(plane);
}
int main(void)
{
test_issue();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(issue_DistanceToPlane)
# find_package (Threads REQUIRED)
set (CMAKE_CXX_STANDARD 11)
# add_compile_options(-std=c++14)
set( CPLEX_PATH /opt/ibm/ILOG/CPLEX_Studio129 )
add_definitions(-DIL_STD)
link_directories(
${CPLEX_PATH}/cplex/lib/x86-64_linux/static_pic
${CPLEX_PATH}/concert/lib/x86-64_linux/static_pic
${CPLEX_PATH}/bin/glnxa64
)
include_directories(
${CPLEX_PATH}/concert/include
${CPLEX_PATH}/cplex/include
)
add_executable(${PROJECT_NAME} issue_DistanceToPlane.cpp)
target_link_libraries(${PROJECT_NAME}
# pthread
# Threads::Threads
-ldqrobotics
ilocplex
cplex
concert
m
pthread
${CMAKE_DL_LIBS}
# dl
)
C++ OUTPUT
The compilation throws the following errors.
issue_DistanceToPlane.cpp:20:56: error: ‘DistanceToPlane’ is not a member of ‘DQ_robotics::ControlObjective’
controller.set_control_objective(ControlObjective::DistanceToPlane);
...
issue_DistanceToPlane.cpp:23:16: error: ‘class DQ_robotics::DQ_ClassicQPController’ has no member named ‘set_max_stability_counter’
controller.set_max_stability_counter(100);
...
issue_DistanceToPlane.cpp:24:16: error: ‘class DQ_robotics::DQ_ClassicQPController’ has no member named ‘set_target_primitive’; did you mean ‘attached_primitive_’?
controller.set_target_primitive(plane);
^~~~~~~~~~~~~~~~~~~~
attached_primitive_
Environment:
Additional context
The DistanceToPlane control objective was recently added to the DQ Robotics in Matlab.
The DistanceToPlane is defined on the DQ_KinematicController.m, but it is not defined on the DQ_KinematicController.h.
Bug description
To Reproduce
Code
robot_interface_node.cpp
...
#include <dqrobotics/DQ.h>
#include <dqrobotics/robot_modeling/DQ_Kinematics.h>
#include <dqrobotics/robots/KukaLw4Robot.h>
...
ROS_INFO_STREAM("TEST");
DQ_SerialManipulator robot_kinematics = KukaLw4Robot::kinematics();
ROS_INFO_STREAM("TEST");
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(robot_interface)
## Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++14)
...
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
...
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node src/robot_interface_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
-ldqrobotics
)
Output
rosrun robot_interface robot_interface_node
[ INFO] [1563287024.186883840]: TEST
robot_interface_node: /usr/local/include/Eigen/src/Core/DenseStorage.h:109: Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array() [with T = double; int Size = 8; int MatrixOrArrayOptions = 0]: Assertion `(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (15)) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
Aborted (core dumped)
Expected behavior
Expected output
[ INFO] [1563287024.186883840]: TEST
[ INFO] [1563287024.186883840]: TEST
Environment:
Additional context
Reading symbols from ./devel/lib/robot_interface/robot_interface_node...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/robot_interface/robot_interface_node
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff0019700 (LWP 25634)]
[New Thread 0x7fffef818700 (LWP 25635)]
[New Thread 0x7fffef017700 (LWP 25636)]
[New Thread 0x7fffee816700 (LWP 25637)]
[ WARN] [1563292402.495467043]: Robot interface initializing...
[ INFO] [1563292402.500789607]: TESTE
robot_interface_node: /usr/local/include/Eigen/src/Core/DenseStorage.h:109: Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array() [with T = double; int Size = 8; int MatrixOrArrayOptions = 0]: Assertion `(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (15)) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
Thread 1 "robot_interface" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff5c6d801 in __GI_abort () at abort.c:79
#2 0x00007ffff5c5d39a in __assert_fail_base (fmt=0x7ffff5de47d8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
assertion=assertion@entry=0x7ffff7aa5910 "(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (15)) == 0 && \"this assertion is explained here: \" \"http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.htm"...,
file=file@entry=0x7ffff7aa58d8 "/usr/local/include/Eigen/src/Core/DenseStorage.h", line=line@entry=109,
function=function@entry=0x7ffff7aa5b20 <Eigen::internal::plain_array<double, 8, 0, 16>::plain_array()::__PRETTY_FUNCTION__> "Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array() [with T = double; int Size = 8; int MatrixOrArrayOptions = 0]")
at assert.c:92
#3 0x00007ffff5c5d412 in __GI___assert_fail (
assertion=0x7ffff7aa5910 "(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (15)) == 0 && \"this assertion is explained here: \" \"http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.htm"...,
file=0x7ffff7aa58d8 "/usr/local/include/Eigen/src/Core/DenseStorage.h", line=109,
function=0x7ffff7aa5b20 <Eigen::internal::plain_array<double, 8, 0, 16>::plain_array()::__PRETTY_FUNCTION__> "Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array() [with T = double; int Size = 8; int MatrixOrArrayOptions = 0]") at assert.c:101
#4 0x00007ffff79cf0b9 in Eigen::internal::plain_array<double, 8, 0, 16>::plain_array() ()
from /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/libdq_robotics.so
#5 0x00007ffff79ce790 in Eigen::DenseStorage<double, 8, 8, 1, 0>::DenseStorage() ()
from /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/libdq_robotics.so
#6 0x00007ffff79cd9da in Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 1, 0, 8, 1> >::PlainObjectBase() ()
from /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/libdq_robotics.so
#7 0x00007ffff79cd240 in Eigen::Matrix<double, 8, 1, 0, 8, 1>::Matrix() ()
from /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/libdq_robotics.so
#8 0x00007ffff79c0dfa in DQ_robotics::DQ::DQ(double const&, double const&, double const&, double const&, double const&, double const&, double const&, double const&) () from /home/marcos/git/mastermsp/manipulation-planning-v2/catkin_ws/devel/lib/libdq_robotics.so
---Type <return> to continue, or q <return> to quit---
#9 0x00007ffff6aed704 in DQ_robotics::DQ_Kinematics::DQ_Kinematics (this=0x7fffffffcf50)
at /usr/src/dqrobotics/robot_modeling/DQ_Kinematics.cpp:32
#10 0x00007ffff6af4439 in DQ_robotics::DQ_SerialManipulator::DQ_SerialManipulator (this=0x7fffffffcf50, dh_matrix=...,
convention="standard") at /usr/src/dqrobotics/robot_modeling/DQ_SerialManipulator.cpp:51
#11 0x00007ffff6afe909 in DQ_robotics::KukaLw4Robot::kinematics () at /usr/src/dqrobotics/robots/KukaLw4Robot.cpp:41
#12 0x00005555555a6b58 in ControllingNode::ROSControlLoop(int) ()
#13 0x00005555555ae4f0 in main ()
I followed the instructions on how to run the cpp-examples and the performance evaluation example worked without errors. It also uses the DQ_SerialManipulator. However, as you know, it includes the DQ header from the source code and not from the PPA.
Bug description
To Reproduce
Code
#include <Eigen/Dense>
#include <dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include <dqrobotics/utils/DQ_LinearAlgebra.h>
#include <iostream>
#include <cmath>
using namespace DQ_robotics;
int main()
{
// robot definition
Matrix<double, 4, 7> kuka_dh;
kuka_dh << 0, 0, 0, 0, 0, 0, 0, // theta
0.3105, 0, 0.4, 0, 0.39, 0, 0, // d
0, 0, 0, 0, 0, 0, 0, // a
0, M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, M_PI_2, -M_PI_2; // alpha
DQ_SerialManipulator kuka(kuka_dh,"modified");
int num_dof = kuka.get_dim_configuration_space();
VectorXd q(num_dof), q_dot(num_dof);
q << 0., 0.5, 0., -1.2, 0., 0., 0.;
q_dot << 0, 0, 0, 0, 0, 0, 0;
Eigen::MatrixXd J = kuka.pose_jacobian(q);
Eigen::MatrixXd N(8,num_dof);
DQ x = kuka.fkm(q);
VectorXd q_desired(num_dof);
q_desired << 0., 0.5, 0.5, -1.2, 0., 0., 0.;
DQ xd = kuka.fkm(q_desired);
DQ x_til = x.conj()*xd;
double k = 5;
double sampling_time = 0.005;
int i = 0;
// initialize rotation angle
double phi = 0.;
while (i < 2000) {
++i;
x = kuka.fkm(q);
J = kuka.pose_jacobian(q);
// invariant error
x_til = x.conj()*xd;
// check rotation angle
phi = x_til.rotation_angle();
if (std::isnan(phi)) {
std::cout << "phi is not real" << std::endl;
std::cout << "phi = " << phi << std::endl;
std::cout << "is unit: " << is_unit(x_til) << std::endl;
std::cout << "real: " << Re(P(x_til)) << std::endl;
return 1;
}
// first order kinematic control
N = haminus8(xd)*C8()*J;
q_dot = pinv(N)*(k*vec8(1-x_til));
q = sampling_time*q_dot + q;
// error
std::cout << (1 - x.conj()*xd).vec8().norm() << std::endl;
}
// exit program
return 0;
}
Output
phi = nan
Expected behavior
Expected output
phi = 0
Environment:
Additional context
Context: In the class DQ_kinematics
, the method set_base
is always given with respect to the identity frame (i.e., the global reference one). This has been used to define the physical location of the robot with respect to the global reference frame (in Matlab, for instance, set_base
is extensively used in the function plot()
, but the issue I'll describe below is independent of the programming language). This is particularly important when we have several robots in the workspace and we want to determine their physical location with respect to a common frame, but we want to perform motion control on a local frame (for example, each robot uses the frame located at its base as the reference frame).
Therefore, sometimes it is useful to use a reference frame that does not coincide with the base frame, which means that the robot is physically located in one place, but the reference frame can be another one (e.g., for example, a camera reference frame). This is particularly important in serially coupled kinematic chains (i.e., complete kinematic chains coupled together to form a larger one) because a particular kinematic chain's end-effector pose is given with respect to the previous kinematic chain's end-effector, not with respect to the global reference frame.
Proposed solution: Use two distinct variables, namely base_frame
and reference_frame
, where the former is used to physically determine the robot in the workspace and the latter is the reference frame used to determine the end-effector pose. Furthermore, we need to implement the methods
set_reference_frame(reference_frame)
;set_base_frame(base_frame)
.Since both fkm()
and pose_jacobian()
methods use the transformation given by base_frame
, they should be adapted accordingly to use reference_frame
instead.
Side-effects: Small, but we need to implement the deprecated function set_base
, which must refer to set_reference_frame
.
I already implemented all those changes in the mobile_base branch. I intend to merge them with the master branch after we decide on the naming conventions related to this issue and issue #8.
Cheers,
Bruno
Context: Directory structure should be the same across all DQ Robotics languages.
The current Matlab folder structure is given as follows:
Folder name | Description |
---|---|
@DQ |
Contains the DQ class and all the associated methods spread across different files. Since this class is quite complex and have several methods and mathematical operations, in Matlab we need to use the @-type folder to split the methods across different files. |
examples | Contains several examples on how to use DQ Robotics in Matlab. The internal folder structure depends on the language because some examples do not make so much sense in some languages (for instance, plot function usage). |
legacy | Legacy classes and methods that will be removed in the next major library improvement. |
robot_control | Classes for robot control. Since the architecture of the DQ_KinematicController will be changed in the future, such that we have one abstract superclass and several concrete subclasses, each one implementing a specific controller, it is a good idea to place all of them in a specific folder. |
robot_modeling | Classes for robot modeling. Since now we have several robot classes, and not only Serial Manipulators anymore, it is a good idea to place all of them in one separate directory. I used the American spelling for 'modeling'. Currently, the C++ version is written in British spelling. I suggest we stick with just one. 😃 |
robots | Robot definitions currently supported by DQ Robotics |
utils | Utility functions and classes. |
vrep_interface | V-Rep classes |
Suggestion: Replicate this directory structure in C++.
I am unable to compile at Ubuntu 14.04 due to minimum cmake version requirement.
It was quite simple to solve. I just changed from 3.4 to 2.8 as show bellow and worked just fine.
Line 1 in c2154c0
To
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
Then I tested using travis for manual compilation with something like:
language: generic
matrix:
include:
- name: "Trusty indigo"
dist: trusty
- name: "Trusty jade"
dist: trusty
- name: "Xenial kinetic"
dist: xenial
before_script:
- sudo apt-get install -y cmake libeigen3-dev # DQRobotics
script:
- mkdir build
- cd build
- cmake ..
- make
To ensure it would not have any trouble.
I finished the implementation of DQ_MobileBase
, DQ_HolonomicBase
, DQ_DifferentialDriveRobot
, and DQ_WholeBody
in Matlab (branch mobile_base).
Could you please implement those classes in C++?
Thanks,
Bruno
Bug description
DQ_Geometry.cpp
, function line_to_line_squared_distance
, the squared distance only works for non-parallel lines. It lacks the implementation of Eq. (46) of M. M. Marinho, B. V. Adorno, K. Harada, and M. Mitsuishi, “Dynamic Active Constraints for Surgical Robots using Vector Field Inequalities,” Apr. 2018.Furthermore, according to Eq. (41), line 131 should be
return std::pow(static_cast<double>(b/a),2);
instead of
return std::pow(static_cast<double>(a/b),2);
Cheers,
Bruno
Hello,
I would like to know if there is a way to get the ith link x(pose) of a DQ_SerialManipulatorDH during runtime.
(In the case of 7th link manipulator, I would like to get 2th link x or 5th link x.)
I know to get top pose from fkm.
Thank you
Murilo sensei, I think having these jacobians can make many problems simpler. I wish these methods could be added if you have any time and are pleased to do so. :>
static MatrixXd point_to_line_segment_squared_distance_jacobian(const MatrixXd& robot_point_jacobian,
const DQ& robot_point,
const DQ& workspace_line,
const DQ& workspace_point_1,
const DQ& workspace_point_2)
{
DQ projection_point = workspace_point_1 + P(workspace_line) * dot(P(workspace_line), (robot_point - workspace_point_1));
double d_projection_point_to_line_point1 = norm(vec3(projection_point - workspace_point_1));
double d_projection_point_to_line_point2 = norm(vec3(projection_point - workspace_point_2));
double line_segment_length = norm(vec3(workspace_point_1 - workspace_point_2));
if (d_projection_point_to_line_point1 <= line_segment_length && d_projection_point_to_line_point2 <= line_segment_length)
// line_state = body
return DQ_Kinematics::point_to_line_distance_jacobian(robot_point_jacobian, robot_point, workspace_line);
else if (d_projection_point_to_line_point1 < d_projection_point_to_line_point2)
// point 1
return DQ_Kinematics::point_to_point_distance_jacobian(robot_point_jacobian, robot_point, workspace_point_1);
else
// point 2
return DQ_Kinematics::point_to_point_distance_jacobian(robot_point_jacobian, robot_point, workspace_point_2);
}
static MatrixXd line_segement_to_point_squared_distance_jacobian(const MatrixXd& robot_line_jacobian,
const MatrixXd& robot_point_1_translation_jacobian,
const MatrixXd& robot_point_2_translation_jacobian,
const DQ& robot_line,
const DQ& robot_point_1,
const DQ& robot_point_2,
const DQ& workspace_point)
{
DQ projection_point = robot_point_1 + P(robot_line) * dot(P(robot_line), (workspace_point - robot_point_1));
double d_projection_point_to_line_point1 = norm(vec3(projection_point - robot_point_1));
double d_projection_point_to_line_point2 = norm(vec3(projection_point - robot_point_2));
double line_segment_length = norm(vec3(robot_point_1 - robot_point_2));
if (d_projection_point_to_line_point1 <= line_segment_length && d_projection_point_to_line_point2 <= line_segment_length)
// line_state = body
return DQ_Kinematics::line_to_point_distance_jacobian(robot_line_jacobian, robot_line, workspace_point);
else if (d_projection_point_to_line_point1 < d_projection_point_to_line_point2)
// point 1
return DQ_Kinematics::point_to_point_distance_jacobian(robot_point_1_translation_jacobian, robot_point_1, workspace_point);
else
// point 2
return DQ_Kinematics::point_to_point_distance_jacobian(robot_point_2_translation_jacobian, robot_point_2, workspace_point);
}
Bug description
To Reproduce
Code
robot_interface_node.cpp
...
// For example the DQ_Kinematics.h
#include <dqrobotics/robot_modeling/DQ_Kinematics.h>
...
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(robot_interface)
## Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++14)
...
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
...
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node src/robot_interface_node.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES}
-ldqrobotics
)
Compilation command
catkin_make
Output
fatal error: dqrobotics/robot_modeling/DQ_Kinematics.h: No such file or directory
#include <dqrobotics/robot_modeling/DQ_Kinematics.h>
Expected behavior
Environment:
Additional context
sudo add-apt-repository ppa:dqrobotics-dev/release
sudo apt-get update
sudo apt-get install libdqrobotics
When I run the install command line, the following appears and indicate the libdqrobotics is installed:
Reading package lists... Done
Building dependency tree
Reading state information... Done
libdqrobotics is already the newest version (0.1-0~69~ubuntu18.04.1).
0 upgraded, 0 newly installed, 0 to remove and 12 not upgraded.
Hi Murilo,
I realized that the cooperative dual space framework is implemented on Matlab (@DQ_cdts) but is not available for C++. It is possible add this functionality in the C++ version?
Cheers,
Juancho.
Hi, Murilo
I've just implemented the function raw_jacobian
on Matlab and adapted the Jacobian function accordingly. The raw_jacobian
calculates the Jacobian matrix without taking into consideration any constant base and end-effector displacements. In addition, following Juancho's request (Ticket 27 on SourceForge), now we have the option to use robot.jacobian(q, ith)
, which calculates the Jacobian up to the i-th link. Could you please implement those functionalities in C++?
Cheers,
Bruno
Hello,
I would like to know if there is a way to get the finite line from Plucker line.
I image not to collide like between just only real shaft part (line) and other real shaft part (line).
double DQ_Geometry::line_to_line_squared_distance(const DQ& line1, const DQ& line2)
Thank you !
Bug description
To Reproduce
Code
#include <Eigen/Dense>
#include <dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include <dqrobotics/utils/DQ_LinearAlgebra.h>
#include <iostream>
#include <cmath>
using namespace DQ_robotics;
int main()
{
// robot definition
Matrix<double, 4, 7> kuka_dh;
kuka_dh << 0, 0, 0, 0, 0, 0, 0, // theta
0.3105, 0, 0.4, 0, 0.39, 0, 0, // d
0, 0, 0, 0, 0, 0, 0, // a
0, M_PI_2, -M_PI_2, -M_PI_2, M_PI_2, M_PI_2, -M_PI_2; // alpha
DQ_SerialManipulator kuka(kuka_dh,"modified");
int num_dof = kuka.get_dim_configuration_space();
VectorXd q(num_dof), q_dot(num_dof);
q << 0., 0.5, 0., -1.2, 0., 0., 0.;
q_dot << 0, 0, 0, 0, 0, 0, 0;
Eigen::MatrixXd J = kuka.pose_jacobian(q);
Eigen::MatrixXd N(8,num_dof);
DQ x = kuka.fkm(q);
VectorXd q_desired(num_dof);
q_desired << 0., 0.5, 0.5, -1.2, 0., 0., 0.;
DQ xd = kuka.fkm(q_desired);
DQ x_til = x.conj()*xd;
double k = 5;
double sampling_time = 0.005;
int i = 0;
// initialize rotation angle
DQ test;
while (i < 2000) {
++i;
x = kuka.fkm(q);
J = kuka.pose_jacobian(q);
// invariant error
x_til = x.conj()*xd;
// check log
test = log(x_til);
if (std::isnan(test.q(0))) {
std::cout << test << std::endl;
return 1;
}
// first order kinematic control
N = haminus8(xd)*C8()*J;
q_dot = pinv(N)*(k*vec8(1-x_til));
q = sampling_time*q_dot + q;
// error
std::cout << (1 - x.conj()*xd).vec8().norm() << std::endl;
}
// exit program
return 0;
}
Output
nan nani nanj nank +E( 0 0i -2.26944e-09j 0k )
Expected behavior
Expected output
0 0i 0j 0k +E( 0 0i -2.26944e-09j 0k )
Environment:
Additional Information:
log
function in C++ is using the acos
function instead of rotation_angle
.Following the discussion https://github.com/orgs/dqrobotics/teams/developers/discussions/1, we must implement the abstract class DQ_Kinematics
, change the name of DQ_kinematics
to DQ_SerialManipulator
and adapt it according to the new architecture. The implementation in Matlab is currently in branch _mobile_base. I suggest creating a new branch in C++ to implement those functionalities in order to ensure that the master branch remains stable.
Cheers,
Bruno
Hello,
I would like to know if there is a way to change the robot of a DQ_SerialManipulator during runtime.
Something like:
DQ_SerialManipulator robot_serial_manipulator();
...
robot_serial_manipulator = KukaLw4Robot::kinematics();
...
robot_serial_manipulator = AnotherRobot::kinematics();
...
robot_serial_manipulator = MyOtherRobot::kinematics();
...
This yields an error of the following type
error: cannot convert ‘DQ_robotics::DQ_SerialManipulator’ to ‘DQ_robotics::DQ_SerialManipulator()’ in assignment
My goal is to be able to use the robot_serial_manipulator overall in the code without having to declare a DQ_SerialManipulator for each robot. I want to use the same code for different robots chosen during runtime.
Stable PPA
DQ Robotics version: 19.10.0-0201910030916ubuntu18.04.1
Thank you,
Marcos
Context: Signature parameters are unnecessarily verbose, the implementation is not "language-proof", and utility functions should be used to obtain a cleaner code.
Suggestions:
robot_point_translation
to robot_point
.return dq.q(0)
, use the casting to double proposed in #14 to obtain a "language-proof" solution.is_pure_quaternion(dq)
).point_to_plane_distance_jacobian
, it is not necessary to compute const DQ d = D(workspace_plane)
;plane_to_point_distance_jacobian
does not need the robot_plane
argument. Furthermore, DQ n_pi = P(robot_plane)
and DQ d_pi = D(robot_plane)
can be removed;Specific Points (I may edit the issue in the very near future to accommodate other bugs, in case I encounter more of them):
q(0)
instead of q(1)
, right?). The casting to double will prevent those kinds of minor-but-very-annoying mistakes.line_to_line_distance_jacobian
currently only implements the Jacobian for the case where the lines are not parallel.line_to_line_residual
currently only implements the residual for the case where the lines are not parallel.Hi Murilo,
I've just implemented the function jacobian_dot
to calculate the time derivative of the Jacobian matrix in Matlab (Ticket 30 of Sourceforge). I also implemented an example (jacobian_time_derivative.m) to compare the analytical expression with a numerical one. Could you please implement the jacobian_dot
method, which in the Matlab version is inside @DQ_kinematics
, and also a simple example like the one I mentioned?
Thanks,
Bruno
Hi @mmmarinho and @bvadorno !
There are plans (in the very near future) to include the geometric primitives Jacobians (line-line, point-line, plane-point...etc, as described in the paper Active Constraints Using Vector Field Inequalities for Surgical Robots in the DQ Robotics (For Matlab, C++ and Python)?
I have my personal implementation on Matlab but I want to use the Python version.
Best regards!
Juancho
Context: Naming convention should follow the Google Python Style Guide, but currently in both C++ and Matlab, functions for creating robots are not following the convention.
For instance, in C++, a KUKA robot is currently declared as DQ_kinematics kuka = KukaKinematics()
and in Matlab it is declared as kuka = DQ_KUKA
.
Suggestion: Use the following convention for functions used to create new robots:
new_robotname_robot
Therefore, a Kuka robot in C++ would be declared as DQ_kinematics kuka = new_kuka_robot()
and in Matlab as kuka = new_kuka_robot
.
Cheers,
Bruno
Bug description
To Reproduce
Code
CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(issue_get_task_variable)
# find_package (Threads REQUIRED)
set (CMAKE_CXX_STANDARD 11)
# add_compile_options(-std=c++14)
set( CPLEX_PATH /opt/ibm/ILOG/CPLEX_Studio129 )
add_definitions(-DIL_STD)
link_directories(
${CPLEX_PATH}/cplex/lib/x86-64_linux/static_pic
${CPLEX_PATH}/concert/lib/x86-64_linux/static_pic
${CPLEX_PATH}/bin/glnxa64
)
include_directories(
${CPLEX_PATH}/concert/include
${CPLEX_PATH}/cplex/include
)
add_executable(${PROJECT_NAME} issue_get_task_variable.cpp)
add_library(Jaco
Jaco.cpp
)
target_link_libraries(${PROJECT_NAME}
# pthread
# Threads::Threads
Jaco
-ldqrobotics
ilocplex
cplex
concert
m
pthread
${CMAKE_DL_LIBS}
# dl
)
Jaco.h
#ifndef DQ_ROBOTS_JACO_H
#define DQ_ROBOTS_JACO_H
#include<dqrobotics/robot_modeling/DQ_SerialManipulator.h>
namespace DQ_robotics
{
class Jaco
{
public:
static DQ_SerialManipulator kinematics();
};
}
#endif
Jaco.cpp
#ifndef DQ_ROBOTICS_JACO_DH_H
#define DQ_ROBOTICS_JACO_DH_H
#include "Jaco.h"
#include<dqrobotics/utils/DQ_Constants.h>
namespace DQ_robotics
{
DQ_SerialManipulator Jaco::kinematics()
{
const double pi2 = pi/2.0;
// Parameters reference:
// https://www.kinovarobotics.com/sites/default/files/ULWS-RA-JAC-UG-INT-EN%20201804-1.0%20%28KINOVA%E2%84%A2%20Ultra%20lightweight%20robotic%20arm%20user%20guide%29_0.pdf
double D1 = 0.2755;
double D2 = 0.4100;
double D3 = 0.2073;
double D4 = 0.0741;
double D5 = 0.0741;
double D6 = 0.1600;
double e2 = 0.0098;
double aa = (30.0*pi)/180.0;
double sa = sin(aa);
double s2a = sin(2*aa);
double d4b = D3 + (sa/s2a)*D4;
double d5b = (sa/s2a)*D4 + (sa/s2a)*D5;
double d6b = (sa/s2a)*D5 + D6;
Matrix<double,4,6> jaco_dh(4,6);
jaco_dh << 0, pi2, pi2, 0, 0, 0,
-0.1188, 0, 0, -0.252, -0.079, -0.04,
0, -0.41, 0, 0, 0, 0,
-pi2, -pi, -pi2, -0.3056*pi, 0.3056*pi, pi;
DQ_SerialManipulator jaco(jaco_dh,"standard");
return jaco;
}
}
#endif
issue_get_task_variable.cpp
#include <iostream>
#include <vector>
#include <dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include "Jaco.h"
#include <dqrobotics/robot_control/DQ_QuadraticProgrammingController.h>
#include <dqrobotics/robot_control/DQ_ClassicQPController.h>
#include <dqrobotics/solvers/DQ_CPLEXSolver.h>
using namespace DQ_robotics;
void test_issue()
{
// Measured joint angles
VectorXd qm(6);
qm << 2.17982, 3.65219, 1.456, 3.50779, 5.10436, -3.73721;
DQ_SerialManipulator jaco = Jaco::kinematics();
// Constrained QP controller
DQ_CPLEXSolver cplex_solver;
DQ_ClassicQPController controller(&jaco, &cplex_solver);
controller.set_control_objective(ControlObjective::Plane);
controller.set_primitive_to_effector(DQ_robotics::k_);
controller.set_gain(10.0);
controller.set_damping(0.001);
const DQ task_variable = controller.get_task_variable(qm);
// Task reference
const DQ task_reference(1, 0, 0, 0, 0, 0.1, 0.1, 0.1);
std::cout << "task_variable " << controller.get_task_variable(qm) << "\n";
std::cout << "task_variable DQ " << task_variable << "\n";
const VectorXd u_qdot = controller.compute_setpoint_control_signal(qm, vec8(task_reference));
}
int main(void)
{
test_issue();
return 0;
}
Output
./issue_get_task_variable
task_variable 0
-0.000112916
0.000183813
1
task_variable DQ 0 -0.000112916i 0.000183813j 1k +E( 0 0i 0j 0k )
terminate called after throwing an instance of 'std::runtime_error'
what(): Incompatible sizes between task variable and task reference in compute_setpoint_control_signal
Aborted (core dumped)
Expected behavior
Environment:
Additional context
qm
, but the same problem occurs.By submitting this report you automatically agree that you've read and accepted the following conditions.
Bug description
@dqrobotics/developers
Hi @mmmarinho, the method DQ_SerialWholeBody::pose_jacobian
returns a result that is different from the Matlab implementation. I think this is related to the use of raw_methods
since the bug is present only when I set the reference frame to a value different from DQ(1).
Minimal Example
#include <iostream>
#include <dqrobotics/robot_modeling/DQ_SerialWholeBody.h>
#include <dqrobotics/robot_modeling/DQ_SerialManipulatorMDH.h>
#include <dqrobotics/robots/FrankaEmikaPandaRobot.h>
#include <memory>
#include <iomanip>
using namespace DQ_robotics;
using namespace Eigen;
int main()
{
auto arm = std::make_shared<DQ_SerialManipulatorMDH>(FrankaEmikaPandaRobot::kinematics());
DQ_SerialWholeBody robot = DQ_SerialWholeBody(arm);
robot.set_reference_frame(1 + 0.5*E_*k_);
VectorXd q = VectorXd::Zero(robot.get_dim_configuration_space());
MatrixXd J = robot.pose_jacobian(q);
std::cout<<std::fixed<<std::setprecision(4)<<J<<std::endl;
return 0;
}
Output
0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
0.5000 0.0000 0.5000 -0.0000 0.5000 -0.0000 -0.5000
0.0000 -0.5000 0.0000 0.5000 -0.0000 0.5000 0.0000
-0.0000 -0.0650 -0.0000 -0.0930 -0.0000 -0.2850 -0.0000
-0.2315 0.0000 -0.2315 -0.0000 -0.2315 0.0000 0.2315
0.0000 -0.0117 0.0000 -0.0296 0.0000 0.0117 -0.0000
-0.0117 -0.0000 -0.0117 0.0000 -0.0117 0.0000 -0.0323
Expected behavior (Matlab)
clear all
close all
clc
robot = DQ_SerialWholeBody(FrankaEmikaPandaRobot.kinematics());
robot.set_reference_frame(1 + 0.5*DQ.E*DQ.k);
q = zeros(robot.get_dim_configuration_space());
J = robot.pose_jacobian(q)
Expected output
J =
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0.5000 0.0000 0.5000 -0.0000 0.5000 -0.0000 -0.5000
0.0000 -0.5000 0.0000 0.5000 0 0.5000 0
-0.0000 0.1850 -0.0000 -0.3430 -0.0000 -0.5350 0.0000
-0.4815 -0.0000 -0.4815 0.0000 -0.4815 0.0000 0.4815
-0.0000 -0.0117 0.0000 -0.0296 -0.0000 0.0117 0.0000
-0.0117 0.0000 -0.0117 -0.0000 -0.0117 -0.0000 -0.0323
Environment:
Professor Murilo, every time I use these two functions in conjunction with DQ_Kinematics::line/plane_to_point_(squared)_distance, I always have to remind myself to switch the positions of the point and the line/plane. During such moments, I can't help but think how convenient it would be if there were functions named line_to_point_squared_distance and plane_to_point_distance. I am wondering if you have time and are interested in adding these two delegation functions to improve coding efficiency and readability. :)
@dqrobotics/developers
Bug description
I think that this bug is responsible for the bug reported here.
Code
#include <iostream>
#include <dqrobotics/DQ.h>
#include <dqrobotics/robot_modeling/DQ_SerialWholeBody.h>
#include <dqrobotics/robots/KukaLw4Robot.h>
#include <dqrobotics/robot_modeling/DQ_SerialManipulatorDH.h>
#include <memory>
#include <Eigen/Dense>
using namespace DQ_robotics;
int main()
{
//-----------Robot definition------------------------------------------------------
auto arm1 = std::make_shared<DQ_SerialManipulatorDH>(KukaLw4Robot::kinematics());
auto arm2 = std::make_shared<DQ_SerialManipulatorDH>(KukaLw4Robot::kinematics());
DQ_SerialWholeBody super_arm(std::static_pointer_cast<DQ_Kinematics>(arm1));
super_arm.add(std::static_pointer_cast<DQ_Kinematics>(arm2));
//---------------------------------------------------------------------------------
int n = arm1->get_dim_configuration_space()+arm2->get_dim_configuration_space();
VectorXd q = VectorXd::Zero(n);
for (int i=0; i<n; i++)
{
std::cout << "x"<<i<<": "<<super_arm.fkm(q,i)<<std::endl;
}
return 0;
}
CmakeLists.
cmake_minimum_required(VERSION 3.5)
project(serial_whole_body LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package (Threads REQUIRED)
FIND_PACKAGE(Eigen3 REQUIRED)
INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
add_executable(serial_whole_body main.cpp)
TARGET_LINK_LIBRARIES(${PROJECT_NAME}
pthread
dqrobotics
)
Output
x0: 0.707107 + 0.707107i + E*(0.109602j + 0.109602k)
x1: 1 + E*(0.155k)
x2: 0.707107 - 0.707107i + E*( - 0.251023j + 0.251023k)
x3: 1 + E*(0.355k)
x4: 0.707107 + 0.707107i + E*(0.388909j + 0.388909k)
x5: 1 + E*(0.55k)
x6: 1 + E*(0.55k)
terminate called after throwing an instance of 'std::runtime_error'
what(): Tried to access link index 7 which is unnavailable.
Expected behavior
clear all
close all
clc
arm1 = KukaLwr4Robot.kinematics();
arm2 = KukaLwr4Robot.kinematics();
super_arm = DQ_SerialWholeBody(arm1);
super_arm.add(arm2);
n = arm1.get_dim_configuration_space() + arm2.get_dim_configuration_space();
q = zeros(n,1);
for i=1:n
super_arm.fkm(q, i)
end
Expected output
ans =
(0.70711 + 0.70711i) + E*(0.1096j + 0.1096k)
ans =
(1) + E*(0.155k)
ans =
(0.70711 - 0.70711i) + E*( - 0.25102j + 0.25102k)
ans =
(1) + E*(0.355k)
ans =
(0.70711 + 0.70711i) + E*(0.38891j + 0.38891k)
ans =
(1) + E*(0.55k)
ans =
(1) + E*(0.55k)
ans =
(0.70711 + 0.70711i) + E*(0.49851j + 0.49851k)
ans =
(1) + E*(0.705k)
ans =
(0.70711 - 0.70711i) + E*( - 0.63993j + 0.63993k)
ans =
(1) + E*(0.905k)
ans =
(0.70711 + 0.70711i) + E*(0.77782j + 0.77782k)
ans =
(1) + E*(1.1k)
ans =
(1) + E*(1.1k)
Environment:
Leave these in your question, read, and check them.
dqrobotics-cpp
? cpp
just sounds too generic.Hi Murilo!
The pseudoinverse method (MatrixXd pseudoInverse( const MatrixXd& matrix)) is implemented in the current version. It is a very useful function. But there is no option to compute the pseudoinverse with damped factor. It is possible to add it?
Thanks!
Juancho.
Leave these in your bug report, read, and check them.
Hello guys,
Describe the missing/unexpected functionality
The matrices Q4 and Q8 are not implemented in the DQ class as they are implemented in the MATLAB version of the DQ class for Matlab.
Would it be possible for you to implement them? Or should I implement them and do a pull request?
Environment:
Kind regards,
Marcos Pereira
Question description
To Reproduce
Code
mkdir issue22
cd issue22
cat <<EOT >> issue22.cpp
#include<iostream>
#include<dqrobotics/robot_modeling/DQ_SerialManipulator.h>
#include<dqrobotics/robots/KukaLw4Robot.h>
using namespace DQ_robotics;
int main(void)
{
DQ_SerialManipulator robot;
DQ_SerialManipulator kuka = KukaLw4Robot::kinematics();
std::cout << "Number of links = " << kuka.get_dim_configuration_space() << std::endl;
return 0;
}
EOT
g++ -o issue22 issue22.cpp -ldqrobotics
./issue22
Output
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libdqrobotics.so: undefined reference to `DQ_robotics::DQ_KinematicController::compute_tracking_control_signal(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&)'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libdqrobotics.so: undefined reference to `DQ_robotics::DQ_TaskspaceQuadraticProgrammingController::compute_tracking_control_signal(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&)'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libdqrobotics.so: undefined reference to `typeinfo for DQ_robotics::DQ_KinematicController'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libdqrobotics.so: undefined reference to `vtable for DQ_robotics::DQ_KinematicController'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libdqrobotics.so: undefined reference to `DQ_robotics::DQ_KinematicController::compute_setpoint_control_signal(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&)'
collect2: error: ld returned 1 exit status
Expected behavior
Expected output
Number of links = 7
Environment:
Hello @mmmarinho,
Would it be possible for you to add the line_to_line_angle_jacobian() method to the DQ Robotics C++ library? The method is not available at the DQ_Kinematics.cpp.
It is already available at the DQ_Kinematics.m.
I am looking forward to use it in C++.
Thanks
Murilo, I've just implemented the sharp conjugation operation in Matlab (matlab/@DQ/transpose.m). Could you please add it to the C++ code?
See Eq. (2.5.3) from Adorno, B. V. (2017). Robot Kinematic Modeling and Control Based on Dual Quaternion Algebra -- Part I: Fundamentals, which can be found here
Hi, @mmmarinho
I suggest some changes in the file DQ_Geometry
.
Following the same reasoning that we used when designing DQ_Kinematics
, I think it's better to make DQ_Geometry
a class with static methods instead of just a file with functions inside the namespace DQ_Robotics
. The reasons for doing so are threefold: first, Matlab does not have the same namespace mechanism as C++; second, we maintain consistency (in terms of our adopted development conventions) inside the overall library; third, we know exactly where those functions are coming from, which helps in the maintainability.
For all squared distances, instead of doing something like pow((vec4(cross(point,l)-m).norm()),2);
, it is more efficient writing something like
new_point = cross(point,l)-m;
vec4(new_point)'*vec4(new_point);
Leave these in your bug report, read, and check them.
Bug description
To Reproduce
#include
part of your code as wellimport
part of your code as wellCode
code here
Output
output here
Expected behavior
Expected output
expected output here
Environment:
Additional context
Hi, Dear Dev!
When I did
git clone https://github.com/dqrobotics/cpp.git dqrobotics
cd dqrobotics
mkdir build
cd build
cmake ..
make
CMake does not pick up the include path of my Eigen3. I have to modify
build/CMakeFiles/dqrobotics.dir/flags.make
to make it work, replacing
dqrobotics/EIGEN3_INCLUDE_DIR
with my Eigen3 path. Here's what CMake gave me
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/lib/ccache/cc
-- Check for working C compiler: /usr/lib/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib/ccache/c++
-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/mujin/Repos/dqrobotics/build
so it seems to me your CMakeLists.txt does not pick up the Eigen3's directory.
Also it appears that the unit test is no longer working, as you seem to have removed/moved some "legacy" controller files. I would like to get the unit test working again, so that I could learn the usage of your double quaternion functions. Thank you!
Hi, @mmmarinho,
I've edited this message in order to reflect #13 (comment).
General suggestion: for all Jacobians, put the associated bibliographic reference.
List of things to review:
line_jacobian
plane_jacobian
line_jacobian
The comments of DQ_Kinematics::line_jacobian()
are outdated as they do not reflect the signature established in dqrobotics/matlab#12 (comment).
Furthermore, I suggest changing
haminus4(line_direction*conj(xr))*Jr + hamiplus4(xr*line_direction)*C4()*Jr
to
(haminus4(line_direction*conj(xr)) + hamiplus4(xr*line_direction)*C4())*Jr
.
The former has three matrix multiplications and 1 matrix addition; the latter has 1 matrix addition and only two matrix multiplications. 🤓
plane_jacobian
The comments of DQ_Kinematics::plane_jacobian()
are outdated as they do not reflect the signature established in dqrobotics/matlab#12 (comment).
Analogously to the line_jacobian
, I also suggest changing
Jnz = haminus4(plane_normal*conj(xr))*Jr + hamiplus4(xr*plane_normal)*C4()*Jr
to
Jnz = (haminus4(plane_normal*conj(xr)) + hamiplus4(xr*plane_normal)*C4())*Jr
;
Cheers,
Bruno
Bug description
To Reproduce
Code
#include <iostream>
#include <Eigen/Dense>
#include <dqrobotics/DQ.h>
#include <iostream>
using namespace DQ_robotics;
int main()
{
Eigen::VectorXd force(6);
force << 1, 2, 3, 4, 5, 6;
std::cout << DQ(force) << std::endl;
return 0;
}
Output
1 2i 3j 4k +E( 5 6i 0j 0k )
Expected behavior
Expected output
0 1i 2j 3k +E( 0 4i 5j 6k )
Environment:
Additional context
Murilo,
Could you please generate the Doxygen documentation files and make them available as an online HTML page? The idea is to automatically update this documentation HTML page at each push. Please see an example here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.