Skip to content

RSDK-13546- compute jacobian from model table#17

Merged
Nick Franczak (nfranczak) merged 22 commits into
mainfrom
20260420-RSDK-13546-Jacobian
Jun 26, 2026
Merged

RSDK-13546- compute jacobian from model table#17
Nick Franczak (nfranczak) merged 22 commits into
mainfrom
20260420-RSDK-13546-Jacobian

Conversation

@nfranczak

@nfranczak Nick Franczak (nfranczak) commented May 27, 2026

Copy link
Copy Markdown
Contributor

tcp-trajex will access jacobian code through a callback

@nfranczak Nick Franczak (nfranczak) changed the title 20260420 rsdk 13546 jacobian RSDK-13546- compute jacobian from model table May 27, 2026
Comment thread src/viam/trajex/jacobian/jacobian.cpp
Comment thread src/viam/trajex/jacobian/jacobian.cpp
@nfranczak Nick Franczak (nfranczak) marked this pull request as ready for review June 9, 2026 18:45

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some general comments, but this needs to be reworked to avoid a dependency on the C++ SDK inside the totg library. We can't do that per our goal of using trajex by way of cgo inside the RDK.

Comment thread CMakeLists.txt Outdated
xtensor
xtl
PRIVATE
viam-cpp-sdk::viamsdk

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, creating this dependency edge is pretty much not permissible for viam-trajex-totg. It would mean dragging the C++ SDK and all of its transitive dependencies in when we link trajex into the RDK. Worse, for a static build, it would require producing a link line which explicitly referenced all of those libraries.

@@ -0,0 +1,450 @@
// Tests for the simplified jacobian module (Option B: plain-return API,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to teach your claude that it shouldn't reference ephemeral state of local information in code it produces. It is hard: it really likes to do this, but Option B doesn't mean anything.

// Joint-type encodings for column 9 of the model-table tensor.
// These match viam::sdk::JointType: revolute=0, continuous=1,
// prismatic=2, fixed=3.
constexpr double kRev = 0.0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style in our C++ is k_rev not kRev.


} // namespace

// ============================================================================

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need these block comments. You can just comment on the BOOST_AUTO_TEST_SUITE itself, since that naturally forms a scope:

// The tests in this suite validate that `J * q_dot` produces the expected Cartesian velocity
BOOST_AUTO_TEST_SUITE(jacobian_velocity_tests)

Comment thread src/viam/trajex/jacobian/jacobian.hpp Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm approving this to unblock things, but I have some high-level reservations, and I'd like us to agree to revisit it in the future:

  • The duplicated understanding of the model table format between this repo and the C++ SDK is a problem. It is better than the alternative, but it isn't great.
  • I find the mixing of std::array / vec3 and xtensor a little troubling. It looks to me like there could be a much simpler implementation living entirely in xtensor space.
  • I feel like there is a lot of "manual work", where the capabilities of xtensor aren't really being leveraged.

Please take a pass through on the comments I left, they are mostly small, and then lets get this merged, but agree to revisit it later.

Comment thread src/viam/trajex/jacobian/jacobian.hpp Outdated
// Evaluates the forward kinematics at joint positions q, capturing the
// per-joint quantities the Jacobian assemblies need. Throws
// std::invalid_argument on q-size mismatch.
chain_state compute_chain_state(const xt::xarray<double>& q) const;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The private function should have a trailing _ as well.

Comment thread src/viam/trajex/jacobian/jacobian.hpp Outdated
// URDF joint type, restricted to arm-relevant joints. Underlying values
// are the column-9 wire encoding accepted by `from`, and match
// viam::sdk::ModelTable::JointType.
enum class joint_type : std::uint8_t {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is private, so joint_type_ with a trailing _

Comment thread src/viam/trajex/jacobian/jacobian.hpp Outdated
// Evaluates the forward kinematics at joint positions q, capturing the
// per-joint quantities the Jacobian assemblies need. Throws
// std::invalid_argument on q-size mismatch.
chain_state compute_chain_state(const xt::xarray<double>& q) const;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto trailing _: compute_chain_state_

Comment thread src/viam/trajex/jacobian/jacobian.cpp Outdated
const joint_row& row = rows_[i];
switch (row.type) {
case joint_type::k_revolute:
if (dot(row.axis, row.axis) < 1e-24) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this number and not some other?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed it to zero since if any row axis is zero that'll be the result

Comment thread src/viam/trajex/jacobian/jacobian.cpp Outdated
}

xt::xarray<double> identity4() {
xt::xarray<double> t = xt::zeros<double>({std::size_t{4}, std::size_t{4}});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just xt::eye<double>(4) I think.

return t;
}

xt::xarray<double> matmul4(const xt::xarray<double>& a, const xt::xarray<double>& b) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disappointing that xtensor pushed the linalg stuff into xtensor-blas.

return t;
}

xt::xarray<double> matmul4(const xt::xarray<double>& a, const xt::xarray<double>& b) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you doing this as explicitly 4 so that a and b can be larger than 4 and you just do 4x4 sub-view? If so, probably better to just write this as a general matrix multiplier, and then pass in views into the things you want to multiply.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you doing this as explicitly 4 so that a and b can be larger than 4 and you just do 4x4 sub-view?

With respect to jacobians, a and b will always be 4x4.
Although I see where you are coming from.
Technically the inputs to this function do not have to be a 4 by 4 matrix.

I think cleaning up this function should be deferred to future work when we can pull in an actual math library. That way we can get rid of the duplicated model table code and refactor the linear algebra all in one go.

I will add a comment for clarity.

Comment on lines +15 to +29
using vec3 = std::array<double, 3>;

double dot(const vec3& a, const vec3& b) {
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
}
vec3 cross(const vec3& a, const vec3& b) {
return {(a[1] * b[2]) - (a[2] * b[1]), (a[2] * b[0]) - (a[0] * b[2]), (a[0] * b[1]) - (a[1] * b[0])};
}
double norm(const vec3& a) {
return std::sqrt(dot(a, a));
}
vec3 normalized(const vec3& a) {
const double n = norm(a);
return {a[0] / n, a[1] / n, a[2] / n};
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'm OK with it to start, but I guess I'd have hoped to see this whole thing work in xtensor space.

Comment on lines +108 to +109
std::vector<vec3> axes;
std::vector<vec3> positions;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sort of what makes me wonder about why these aren't xtensor arrays., since a vector of vec3 sure looks like a 2d array to me

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while yes this is true, not enitrely feasible until we have said math library.

Comment thread src/viam/trajex/jacobian/jacobian.cpp Outdated
state.axes.reserve(actuated_count_);
state.positions.reserve(actuated_count_);

xt::xarray<double> T = identity4();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better name than T?

@nfranczak Nick Franczak (nfranczak) left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@nfranczak Nick Franczak (nfranczak) merged commit ebaa7d5 into main Jun 26, 2026
10 checks passed
@nfranczak Nick Franczak (nfranczak) deleted the 20260420-RSDK-13546-Jacobian branch June 29, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants