Program Listing for File trossen_arm_type.hpp
↰ Return to documentation for file (include/libtrossen_arm/trossen_arm_type.hpp)
// Copyright 2025 Trossen Robotics
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef LIBTROSSEN_ARM__TROSSEN_ARM_TYPE_HPP_
#define LIBTROSSEN_ARM__TROSSEN_ARM_TYPE_HPP_
#include <cstdint>
#include <array>
#include <functional>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
namespace trossen_arm
{
enum class LogLevel : uint8_t {
trace,
debug,
info,
warn,
error,
critical,
};
using LogCallback =
std::function<void(LogLevel level, const std::string & name, const std::string & message)>;
enum class Mode : uint8_t {
idle,
position,
velocity,
external_effort,
effort,
};
enum class IPMethod : uint8_t {
manual,
dhcp,
};
enum class Model : uint8_t {
wxai_v0,
vxai_v0_right,
vxai_v0_left,
};
enum class InterpolationSpace : uint8_t {
joint,
cartesian,
};
struct JointCharacteristic
{
double effort_correction{1.0};
double friction_transition_velocity{0.0};
double friction_constant_term{0.0};
double friction_coulomb_coef{0.0};
double friction_viscous_coef{0.0};
double position_offset{0.0};
};
struct Link
{
double mass{0.0};
std::array<double, 9> inertia{};
std::array<double, 3> origin_xyz{};
std::array<double, 3> origin_rpy{};
};
struct Joint
{
std::array<double, 6> axis{};
std::array<double, 3> origin_xyz{};
std::array<double, 3> origin_rpy{};
};
struct EndEffector
{
Link palm{};
Link finger_left{};
Link finger_right{};
double offset_finger_left{0.0};
double offset_finger_right{0.0};
double pitch_circle_radius{0.0};
std::array<double, 6> t_flange_tool{};
};
struct JointLimit
{
double position_min{0.0};
double position_max{0.0};
double position_tolerance{0.0};
double velocity_max{0.0};
double velocity_tolerance{0.0};
double effort_max{0.0};
double effort_tolerance{0.0};
};
struct PIDParameter
{
double kp{0.0};
double ki{0.0};
double kd{0.0};
double imax{0.0};
};
struct MotorParameter
{
PIDParameter position{};
PIDParameter velocity{};
};
struct AlgorithmParameter
{
double singularity_threshold{0.0};
};
struct RobotOutput
{
struct Header
{
uint32_t id{0};
uint64_t timestamp{0};
} header{};
struct Joint
{
struct All
{
std::vector<double> positions{};
std::vector<double> velocities{};
std::vector<double> accelerations{};
std::vector<double> efforts{};
std::vector<double> external_efforts{};
std::vector<double> compensation_efforts{};
std::vector<double> rotor_temperatures{};
std::vector<double> driver_temperatures{};
} all{};
struct Arm
{
std::vector<double> positions{};
std::vector<double> velocities{};
std::vector<double> accelerations{};
std::vector<double> efforts{};
std::vector<double> external_efforts{};
std::vector<double> compensation_efforts{};
std::vector<double> rotor_temperatures{};
std::vector<double> driver_temperatures{};
} arm{};
struct Gripper
{
double position{0.0};
double velocity{0.0};
double acceleration{0.0};
double effort{0.0};
double external_effort{0.0};
double compensation_effort{0.0};
double rotor_temperature{0.0};
double driver_temperature{0.0};
} gripper{};
} joint{};
struct Cartesian
{
// TODO(Shiming-Liang): Add helper functions to convert rotations
std::array<double, 6> positions{};
std::array<double, 6> velocities{};
std::array<double, 6> accelerations{};
std::array<double, 6> external_efforts{};
} cartesian{};
};
class LogicError : public std::logic_error
{
public:
using std::logic_error::logic_error;
};
class RuntimeError : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
class QuinticHermiteInterpolator;
class EthernetManager;
class AlgorithmInterface;
class Logger;
struct StandardEndEffector
{
// clang-format off
static constexpr EndEffector wxai_v0_base_20250509{
.palm = {
.mass = 0.53780000,
.inertia = {
0.00079919, -0.00000049, 0.00000010,
-0.00000049, 0.00047274, 0.00000004,
0.00000010, 0.00000004, 0.00105293
},
.origin_xyz = {0.04572768, -0.00000726, 0.00001402},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.05945000,
.inertia = {
0.00001875, 0.00000309, -0.00000149,
0.00000309, 0.00002614, -0.00000124,
-0.00000149, -0.00000124, 0.00002995
},
.origin_xyz = {0.00169016, -0.00592796, -0.00365701},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.05945000,
.inertia = {
0.00001930, -0.00000309, 0.00000359,
-0.00000309, 0.00002670, -0.00000064,
0.00000359, -0.00000064, 0.00002995
},
.origin_xyz = {0.00169015, 0.00592793, 0.00201818},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.0227,
.offset_finger_right = -0.0227,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector wxai_v0_base_20260626{
.palm = {
.mass = 0.55984146,
.inertia = {
0.00083660, -0.00000073, 0.00000358,
-0.00000073, 0.00038094, -0.00000017,
0.00000358, -0.00000017, 0.00097121
},
.origin_xyz = {0.04530754, -0.00004231, 0.00021128},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.07283511,
.inertia = {
0.00002514, 0.00000487, -0.00000253,
0.00000487, 0.00003633, -0.00000144,
-0.00000253, -0.00000144, 0.00004148
},
.origin_xyz = {0.00300468, -0.00699875, -0.00383403},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.07283530,
.inertia = {
0.00002578, -0.00000487, 0.00000496,
-0.00000487, 0.00003697, -0.00000055,
0.00000496, -0.00000055, 0.00004148
},
.origin_xyz = {0.00300470, 0.00699864, 0.00244362},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.02449818,
.offset_finger_right = -0.02450182,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector wxai_v0_leader_20250509{
.palm = {
.mass = 0.59570000,
.inertia = {
0.00117653, -0.00000040, -0.00005492,
-0.00000040, 0.00085696, 0.00000074,
-0.00005492, 0.00000074, 0.00107685
},
.origin_xyz = {0.04454388, 0.00000506, -0.00694150},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.06380000,
.inertia = {
0.00003556, -0.00000249, 0.00000167,
-0.00000249, 0.00002700, 0.00000217,
0.00000167, 0.00000217, 0.00001726
},
.origin_xyz = {-0.00423580, -0.00167541, -0.01050810},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.06380000,
.inertia = {
0.00004133, 0.00000250, 0.00000517,
0.00000250, 0.00003277, -0.00000592,
0.00000517, -0.00000592, 0.00001727
},
.origin_xyz = {-0.00423309, 0.00167373, -0.00451087},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.0179,
.offset_finger_right = -0.0179,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector wxai_v0_leader_20260626{
.palm = {
.mass = 0.65411940,
.inertia = {
0.00141948, -0.00000068, -0.00008034,
-0.00000068, 0.00097213, 0.00000008,
-0.00008034, 0.00000008, 0.00100814
},
.origin_xyz = {0.04351475, -0.00003630, -0.01014018},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.06566254,
.inertia = {
0.00004150, -0.00000254, 0.00000037,
-0.00000254, 0.00003063, 0.00000328,
0.00000037, 0.00000328, 0.00001893
},
.origin_xyz = {-0.00510623, -0.00176708, -0.01245444},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.06566254,
.inertia = {
0.00004970, 0.00000254, 0.00000415,
0.00000254, 0.00003882, -0.00000767,
0.00000415, -0.00000767, 0.00001893
},
.origin_xyz = {-0.00510588, 0.00176675, -0.00547648},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.01859818,
.offset_finger_right = -0.01860182,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector wxai_v0_follower_20250509{
.palm = {
.mass = 0.64230000,
.inertia = {
0.00108484, 0.00000063, -0.00004180,
0.00000063, 0.00075170, -0.00001558,
-0.00004180, -0.00001558, 0.00110994
},
.origin_xyz = {0.04699592, 0.00045936, 0.00827772},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.05945000,
.inertia = {
0.00001875, 0.00000309, -0.00000149,
0.00000309, 0.00002614, -0.00000124,
-0.00000149, -0.00000124, 0.00002995
},
.origin_xyz = {0.00169016, -0.00592796, -0.00365701},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.05945000,
.inertia = {
0.00001930, -0.00000309, 0.00000359,
-0.00000309, 0.00002670, -0.00000064,
0.00000359, -0.00000064, 0.00002995
},
.origin_xyz = {0.00169015, 0.00592793, 0.00201818},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.0227,
.offset_finger_right = -0.0227,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector wxai_v0_follower_20260626{
.palm = {
.mass = 0.67244176,
.inertia = {
0.00115274, -0.00000008, -0.00001266,
-0.00000008, 0.00067665, -0.00001573,
-0.00001266, -0.00001573, 0.00101644
},
.origin_xyz = {0.04557269, 0.00040888, 0.00893526},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.07283511,
.inertia = {
0.00002514, 0.00000487, -0.00000253,
0.00000487, 0.00003633, -0.00000144,
-0.00000253, -0.00000144, 0.00004148
},
.origin_xyz = {0.00300468, -0.00699875, -0.00383403},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.07283530,
.inertia = {
0.00002578, -0.00000487, 0.00000496,
-0.00000487, 0.00003697, -0.00000055,
0.00000496, -0.00000055, 0.00004148
},
.origin_xyz = {0.00300470, 0.00699864, 0.00244362},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.02449818,
.offset_finger_right = -0.02450182,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.156062, 0.0, 0.0, 0.0, 0.0, 0.0}
};
static constexpr EndEffector vxai_v0_base_20250509{
.palm = {
.mass = 0.57903811,
.inertia = {
0.00135277, -0.00000006, -0.00009912,
-0.00000006, 0.00077371, 0.00000049,
-0.00009912, 0.00000049, 0.00085992
},
.origin_xyz = {-0.01847211, -0.00000697, -0.08476049},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.08127100,
.inertia = {
0.00004094, -0.00000169, 0.00000204,
-0.00000169, 0.00003574, -0.00000422,
0.00000204, -0.00000422, 0.00002563
},
.origin_xyz = {-0.00365705, -0.00592794, -0.00169016},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.08127100,
.inertia = {
0.00004094, -0.00000087, -0.00000491,
-0.00000087, 0.00003650, 0.00000422,
-0.00000491, 0.00000422, 0.00002639
},
.origin_xyz = {0.00201821, 0.00592796, -0.00169015},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.0227,
.offset_finger_right = -0.0227,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {-0.021, 0, -0.200062, 0.0, 0.0, 0.0}
};
static constexpr EndEffector no_gripper_20250509{
.palm = {
.mass = 0.0,
.inertia = {
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0
},
.origin_xyz = {0.0, 0.0, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_left = {
.mass = 0.0,
.inertia = {
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0
},
.origin_xyz = {0.0, 0.0, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
},
.finger_right = {
.mass = 0.0,
.inertia = {
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0
},
.origin_xyz = {0.0, 0.0, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
},
.offset_finger_left = 0.0179,
.offset_finger_right = -0.0179,
.pitch_circle_radius = 0.00875,
.t_flange_tool = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}
};
// clang-format on
static inline const EndEffector & wxai_v0_base{wxai_v0_base_20260626};
static inline const EndEffector & wxai_v0_leader{wxai_v0_leader_20260626};
static inline const EndEffector & wxai_v0_follower{wxai_v0_follower_20260626};
static inline const EndEffector & vxai_v0_base{vxai_v0_base_20250509};
static inline const EndEffector & no_gripper{no_gripper_20250509};
};
struct StandardMotorParameters
{
// clang-format off
static inline const std::vector<std::map<Mode, MotorParameter>> wxai_v0_20250509 {
{ // Joint 0
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::position,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.004, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 1
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 27.0}
}
},
{
Mode::position,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.004, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 2
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::position,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.004, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 3
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.001, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 4
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.001, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 5
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.001, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 6
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 0.05, .ki = 0.0005, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.001, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
};
static inline const std::vector<std::map<Mode, MotorParameter>> wxai_v0_20260317 {
{ // Joint 0
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::position,
{
.position = {.kp = 16.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 1
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 27.0}
}
},
{
Mode::position,
{
.position = {.kp = 16.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 2
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.04, .kd = 0.0, .imax = 9.0}
}
},
{
Mode::position,
{
.position = {.kp = 16.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 120.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 8.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 3
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 80.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 4
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 5
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.01, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 40.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
{ // Joint 6
{
Mode::idle,
{
.position = {.kp = 0.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 0.05, .ki = 0.0005, .kd = 0.0, .imax = 3.0}
}
},
{
Mode::position,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::velocity,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::external_effort,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
{
Mode::effort,
{
.position = {.kp = 20.0, .ki = 0.0, .kd = 0.0, .imax = 0.0},
.velocity = {.kp = 1.0, .ki = 0.0, .kd = 0.0, .imax = 0.0}
}
},
},
};
// clang-format on
static inline const std::vector<std::map<Mode, MotorParameter>> & wxai_v0_latest{
wxai_v0_20260317
};
static inline const std::vector<std::map<Mode, MotorParameter>> & wxai_v0_default{
wxai_v0_20260317
};
};
struct StandardLinks
{
static inline const std::vector<Link> wxai_v0_20250509{
{// Base link
.mass = 0.45000000,
.inertia =
{0.00040781,
0.00000011,
-0.00000444,
0.00000011,
0.00043949,
-0.00000076,
-0.00000444,
-0.00000076,
0.00020951},
.origin_xyz = {-0.00014175, -0.00005228, 0.03175177},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 1
.mass = 0.14930000,
.inertia =
{0.00018096,
-0.00000187,
-0.00001404,
-0.00000187,
0.00008172,
-0.00000127,
-0.00001404,
-0.00000127,
0.00018791},
.origin_xyz = {-0.00011075, 0.00171176, 0.02044592},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 2
.mass = 1.18560000,
.inertia =
{0.00105519,
-0.00000328,
-0.00002754,
-0.00000328,
0.01784952,
-0.00000198,
-0.00002754,
-0.00000198,
0.01844965},
.origin_xyz = {-0.13121451, -0.00292583, 0.00021345},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 3
.mass = 0.69280000,
.inertia =
{0.00065456,
0.00009210,
-0.00052467,
0.00009210,
0.00552297,
0.00001169,
-0.00052467,
0.00001169,
0.00566525},
.origin_xyz = {0.18083602, -0.00094090, 0.05554937},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 4
.mass = 0.47700000,
.inertia =
{0.00056085,
0.00000719,
-0.00018922,
0.00000719,
0.00068897,
0.00000754,
-0.00018922,
0.00000754,
0.00043873},
.origin_xyz = {0.05797842, 0.00027145, 0.05884447},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 5
.mass = 0.36400000,
.inertia =
{0.00018761,
-0.00000045,
0.00000089,
-0.00000045,
0.00031805,
0.00000003,
0.00000089,
0.00000003,
0.00026536},
.origin_xyz = {0.00412447, -0.00001138, -0.04283184},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 6
.mass = 0.58390000,
.inertia =
{0.00086769,
-0.00000054,
0.00000011,
-0.00000054,
0.00051326,
0.00000004,
0.00000011,
0.00000004,
0.00114318},
.origin_xyz = {0.04572768, -0.00000726, 0.00001402},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger left
.mass = 0.05945000,
.inertia =
{0.00001875,
0.00000309,
-0.00000149,
0.00000309,
0.00002614,
-0.00000124,
-0.00000149,
-0.00000124,
0.00002995},
.origin_xyz = {0.00169016, -0.00592796, -0.00365701},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger right
.mass = 0.05945000,
.inertia =
{0.00001930,
-0.00000309,
0.00000359,
-0.00000309,
0.00002670,
-0.00000064,
0.00000359,
-0.00000064,
0.00002995},
.origin_xyz = {0.00169015, 0.00592793, 0.00201818},
.origin_rpy = {0.0, 0.0, 0.0}
}
};
static inline const std::vector<Link> wxai_v0_20260626{
{// Base link
.mass = 0.46273356,
.inertia =
{0.00022947,
0.00000013,
-0.00000488,
0.00000013,
0.00026286,
-0.00000028,
-0.00000488,
-0.00000028,
0.00023167},
.origin_xyz = {-0.00020063, -0.00003382, 0.03051419},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 1
.mass = 0.15008228,
.inertia =
{0.00018088,
-0.00000118,
-0.00001396,
-0.00000118,
0.00008194,
-0.00000042,
-0.00001396,
-0.00000042,
0.00018797},
.origin_xyz = {-0.00018072, 0.00138124, 0.02037991},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 2
.mass = 1.13581111,
.inertia =
{0.00064547,
-0.00000050,
-0.00001069,
-0.00000050,
0.01736392,
-0.00000063,
-0.00001069,
-0.00000063,
0.01753333},
.origin_xyz = {-0.13172378, -0.00180325, 0.00008127},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 3
.mass = 0.67178383,
.inertia =
{0.00053201,
0.00008141,
-0.00053779,
0.00008141,
0.00543866,
0.00001195,
-0.00053779,
0.00001195,
0.00545384},
.origin_xyz = {0.18204373, -0.00049130, 0.05541290},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 4
.mass = 0.47899686,
.inertia =
{0.00045072,
0.00001099,
-0.00019411,
0.00001099,
0.00058606,
0.00001185,
-0.00019411,
0.00001185,
0.00045456},
.origin_xyz = {0.05845470, 0.00047346, 0.05984125},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 5
.mass = 0.36818897,
.inertia =
{0.00019188,
-0.00000044,
0.00000121,
-0.00000044,
0.00019906,
-0.00000010,
0.00000121,
-0.00000010,
0.00014673},
.origin_xyz = {0.00357317, -0.00006705, -0.04271537},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Link 6
.mass = 0.65411940,
.inertia =
{0.00141948,
-0.00000068,
-0.00008034,
-0.00000068,
0.00097213,
0.00000008,
-0.00008034,
0.00000008,
0.00100814},
.origin_xyz = {0.04351475, -0.00003630, -0.01014018},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger left
.mass = 0.06566254,
.inertia =
{0.00004150,
-0.00000254,
0.00000037,
-0.00000254,
0.00003063,
0.00000328,
0.00000037,
0.00000328,
0.00001893},
.origin_xyz = {-0.00510623, -0.00176708, -0.01245444},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger right
.mass = 0.06566254,
.inertia =
{0.00004970,
0.00000254,
0.00000415,
0.00000254,
0.00003882,
-0.00000767,
0.00000415,
-0.00000767,
0.00001893},
.origin_xyz = {-0.00510588, 0.00176675, -0.00547648},
.origin_rpy = {0.0, 0.0, 0.0}
}
};
};
struct StandardJoints
{
static inline const std::vector<Joint> wxai_v0_20250509{
{// Joint 0
.axis = {0.0, 0.0, 1.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.0, 0.0, 0.05725},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 1
.axis = {0.0, 1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.02, 0.0, 0.04625},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 2
.axis = {0.0, -1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {-0.264, 0.0, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 3
.axis = {0.0, -1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.245, 0.0, 0.06},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 4
.axis = {0.0, 0.0, -1.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.06775, 0.0, 0.0455},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 5
.axis = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.02895, 0.0, -0.0455},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger left
.axis = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0},
.origin_xyz = {0.078, 0.01485, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger right
.axis = {0.0, 0.0, 0.0, 0.0, -1.0, 0.0},
.origin_xyz = {0.078, -0.01485, 0.0},
.origin_rpy = {0.0, 0.0, 0.0}
}
};
static inline const std::vector<Joint> wxai_v0_20260626{
{// Joint 0
.axis = {0.0, 0.0, 1.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.00000000, 0.00000000, 0.05725000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 1
.axis = {0.0, 1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.02000000, 0.00000000, 0.04625000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 2
.axis = {0.0, -1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {-0.26400000, 0.00000000, 0.00000000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 3
.axis = {0.0, -1.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.24500000, 0.00000000, 0.06000000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 4
.axis = {0.0, 0.0, -1.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.06775000, -0.00005000, 0.04550000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Joint 5
.axis = {1.0, 0.0, 0.0, 0.0, 0.0, 0.0},
.origin_xyz = {0.02895000, 0.00000000, -0.04550000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger left
.axis = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0},
.origin_xyz = {0.08650000, 0.01859818, 0.00000000},
.origin_rpy = {0.0, 0.0, 0.0}
},
{// Finger right
.axis = {0.0, 0.0, 0.0, 0.0, -1.0, 0.0},
.origin_xyz = {0.08650000, -0.01860182, 0.00000000},
.origin_rpy = {0.0, 0.0, 0.0}
}
};
};
enum class Notice : uint8_t {
default_motor_parameters_20260317
};
enum class ErrorState : uint8_t {
none,
ethernet_init_failed,
can_init_failed,
joint_command_failed,
joint_feedback_failed,
joint_clear_error_failed,
joint_enable_failed,
joint_disable_failed,
joint_set_home_failed,
joint_disabled_unexpectedly,
joint_overheated,
invalid_mode,
invalid_robot_command,
invalid_configuration_address,
robot_input_mode_mismatch,
joint_limit_exceeded,
robot_input_infinite
};
inline const std::map<ErrorState, std::string> ERROR_INFORMATION = {
{ErrorState::none, "No error"},
{ErrorState::ethernet_init_failed, "Controller's Ethernet manager failed to initialize"},
{ErrorState::can_init_failed, "Controller's CAN interface failed to initialize"},
{ErrorState::joint_command_failed, "Controller's CAN interface failed to send a message"},
{ErrorState::joint_feedback_failed, "Controller's CAN interface failed to receive a message"},
{ErrorState::joint_clear_error_failed, "Joint clear error command failed"},
{ErrorState::joint_enable_failed, "Joint enable command failed"},
{ErrorState::joint_disable_failed, "Joint disable command failed"},
{ErrorState::joint_set_home_failed, "Joint home calibration command failed"},
{ErrorState::joint_disabled_unexpectedly, "Joint disabled unexpectedly"},
{ErrorState::joint_overheated, "Joint overheated"},
{ErrorState::invalid_mode, "Invalid mode command received"},
{ErrorState::invalid_robot_command, "Invalid robot command indicator received"},
{ErrorState::invalid_configuration_address, "Invalid configuration address"},
{ErrorState::robot_input_mode_mismatch,
"Robot input with modes different than configured modes received"},
{ErrorState::joint_limit_exceeded, "Joint limit exceeded"},
{ErrorState::robot_input_infinite, "Robot input with infinite values received"}
};
inline const std::map<Model, std::string> MODEL_NAME = {
{Model::wxai_v0, "wxai_v0"},
{Model::vxai_v0_right, "vxai_v0_right"},
{Model::vxai_v0_left, "vxai_v0_left"},
};
inline const std::map<Mode, std::string> MODE_NAME = {
{Mode::idle, "idle"},
{Mode::position, "position"},
{Mode::velocity, "velocity"},
{Mode::external_effort, "external_effort"},
{Mode::effort, "effort"},
};
struct DiscoverResult
{
std::string ip{};
Model model{Model::wxai_v0};
std::string firmware_version{};
ErrorState error_state{ErrorState::none};
};
} // namespace trossen_arm
#endif // LIBTROSSEN_ARM__TROSSEN_ARM_TYPE_HPP_