RSDK-13546- compute jacobian from model table#17
Conversation
Andrew C. Morrow (acmorrow)
left a comment
There was a problem hiding this comment.
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.
| xtensor | ||
| xtl | ||
| PRIVATE | ||
| viam-cpp-sdk::viamsdk |
There was a problem hiding this comment.
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, | |||
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Style in our C++ is k_rev not kRev.
|
|
||
| } // namespace | ||
|
|
||
| // ============================================================================ |
There was a problem hiding this comment.
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)
Andrew C. Morrow (acmorrow)
left a comment
There was a problem hiding this comment.
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.
| // 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; |
There was a problem hiding this comment.
The private function should have a trailing _ as well.
| // 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 { |
There was a problem hiding this comment.
It is private, so joint_type_ with a trailing _
| // 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; |
There was a problem hiding this comment.
Ditto trailing _: compute_chain_state_
| const joint_row& row = rows_[i]; | ||
| switch (row.type) { | ||
| case joint_type::k_revolute: | ||
| if (dot(row.axis, row.axis) < 1e-24) { |
There was a problem hiding this comment.
Why this number and not some other?
There was a problem hiding this comment.
changed it to zero since if any row axis is zero that'll be the result
| } | ||
|
|
||
| xt::xarray<double> identity4() { | ||
| xt::xarray<double> t = xt::zeros<double>({std::size_t{4}, std::size_t{4}}); |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| 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}; | ||
| } |
There was a problem hiding this comment.
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.
| std::vector<vec3> axes; | ||
| std::vector<vec3> positions; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
while yes this is true, not enitrely feasible until we have said math library.
| state.axes.reserve(actuated_count_); | ||
| state.positions.reserve(actuated_count_); | ||
|
|
||
| xt::xarray<double> T = identity4(); |
There was a problem hiding this comment.
Is there a better name than T?
Nick Franczak (nfranczak)
left a comment
There was a problem hiding this comment.
.
tcp-trajex will access jacobian code through a callback