Repository navigation
Fix OMPL config structure, FK units, firmware query buffer and CAN renaming #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1c85ed1
3ba430c
04fc8b1
56c3708
edbcd47
6b4c490
273c997
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ | |
| namespace piper_cpp | ||
| { | ||
|
|
||
| static constexpr double MILLIDEG2RAD = 0.001 * 3.14 / 180; | ||
| static constexpr double MILLIDEG2RAD = 0.001 * M_PI / 180; | ||
|
|
||
| // Implementation of the PiperInterfaceV2 methods | ||
| PiperInterfaceV2::PiperInterfaceV2( | ||
|
|
@@ -439,8 +439,11 @@ void PiperInterfaceV2::parseCANFrame(const struct can_frame &frame, double times | |
| } | ||
| case ArmMsgType::FirmwareRead: | ||
| { | ||
| // The reply to one query is a few frames; anything beyond this is noise, not the tag. | ||
| static constexpr size_t kMaxFirmwareBytes = 256; | ||
| std::lock_guard<std::mutex> lock(firmware_data_mutex_); | ||
| firmware_data_.insert(firmware_data_.end(), msg.firmware_data.begin(), msg.firmware_data.end()); | ||
| if (firmware_data_.size() < kMaxFirmwareBytes) | ||
| firmware_data_.insert(firmware_data_.end(), msg.firmware_data.begin(), msg.firmware_data.end()); | ||
| break; | ||
| } | ||
| case ArmMsgType::InstructionResponseConfig: | ||
|
|
@@ -940,6 +943,12 @@ bool PiperInterfaceV2::sendFirmwareQuery() | |
| std::vector<uint8_t> data{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
| uint16_t can_id = 0x4AF; | ||
|
|
||
| { | ||
| // Each query gets its own reply buffer, so a re-query after a firmware update cannot | ||
| // keep reporting the old tag. | ||
| std::lock_guard<std::mutex> lock(firmware_data_mutex_); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Medium · Old firmware replies appear current When a previous reply is still in flight or callers issue overlapping firmware queries, Associate firmware reply frames with their query, or prevent a new query until the previous reply is fully received. Also at Prompt for AI agentsIn `piper_cpp/src/interface/piper_interface_v2.cpp` at line 949:
**Old firmware replies appear current**
When a previous reply is still in flight or callers issue overlapping firmware queries, `sendFirmwareQuery()` clears the buffer, but `parseCANFrame()` appends firmware frames without identifying their query. `getFirmwareVersion()` can therefore return the previous query's first complete `S-V` tag as the new result, even after the new reply arrives.
Associate firmware reply frames with their query, or prevent a new query until the previous reply is fully received.
Also at `piper_cpp/src/interface/piper_interface_v2.cpp:446`, `piper_cpp/src/interface/piper_interface_v2.cpp:950`. |
||
| firmware_data_.clear(); | ||
| } | ||
| if (!arm_can_->sendCanMessage(can_id, data)) | ||
| { | ||
| std::cerr << "Error: Failed to send firmware query CAN message.\n"; | ||
|
|
@@ -966,8 +975,10 @@ std::optional<std::string> PiperInterfaceV2::getFirmwareVersion() const | |
| { | ||
| if (std::memcmp(firmware_data_.data() + i, marker, marker_len) == 0) | ||
| { | ||
| const size_t end = std::min(i + version_len, firmware_data_.size()); | ||
| return std::string(firmware_data_.begin() + i, firmware_data_.begin() + end); | ||
| // The tag spans frames; report it only once it is all here. | ||
| if (i + version_len > firmware_data_.size()) | ||
| return std::nullopt; | ||
| return std::string(firmware_data_.begin() + i, firmware_data_.begin() + i + version_len); | ||
| } | ||
| } | ||
| return std::nullopt; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #include "piper_cpp/fk.h" | ||
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| using piper_cpp::PiperForwardKinematics; | ||
|
|
||
| // The manufacturer's SDK quotes the home pose of the default (offset) DH set in mm and | ||
| // degrees; the FK must reproduce it at zero joint angles, which pins the output units. The | ||
| // non-offset set's quoted pose is rounded to the millimetre, so it is not asserted. | ||
| TEST(ForwardKinematics, ZeroJointsGiveTheHomePoseInMillimetresAndDegrees) | ||
| { | ||
| PiperForwardKinematics fk; | ||
| const auto pose = fk.calcFK({0, 0, 0, 0, 0, 0}).back(); | ||
| for (int i = 0; i < 6; ++i) | ||
| EXPECT_NEAR(pose[i], fk.init_pos[i], 0.001) << "component " << i; | ||
| } | ||
|
|
||
| TEST(ForwardKinematics, InputIsRadians) | ||
| { | ||
| PiperForwardKinematics fk; | ||
| // A quarter turn of joint 1 swings the home position from +x onto +y. | ||
| const auto pose = fk.calcFK({PiperForwardKinematics::PI / 2, 0, 0, 0, 0, 0}).back(); | ||
| EXPECT_NEAR(pose[0], 0.0, 0.01); | ||
| EXPECT_NEAR(pose[1], fk.init_pos[0], 0.01); | ||
| EXPECT_NEAR(pose[2], fk.init_pos[2], 0.01); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '35,170p' piper_cpp/src/can_utils.cppRepository: justagist/piper_cpp
Length of output: 4785
🏁 Script executed:
Repository: justagist/piper_cpp
Length of output: 5737
🏁 Script executed:
Repository: justagist/piper_cpp
Length of output: 8867
Choose a free temporary interface name before the first rename.
The generated
prefix + "tmp" + indexname is not checked for collisions. A failed temporary rename leaves the original name incurrent, and the second pass can then find its target still occupied. The code only logs both failures and starts the interfaces under the wrong names.Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents