Skip to content

Commit bd85c6d

Browse files
imisaacwuvvarun77
andauthored
Servos & Steppers (#368)
* Add basic set requested motor power to _power_repeat_task * Add motor power request handling * Fix formatting * Update loops * Start adding device groups to CAN Motors * Update getMotorPos * Update the rest of the CAN Motor functions to use deviceid_t * Update real world interface with device groups * Fix stupid motor error * Update HindsightCAN * Add device groups * Fix merge errors * Revert HindsightCAN, remove unused global * Fix formatting * Fix formatting * Update drill serials * add quick fourbar (remove) * PWM scale updates * Remove motor power requests * Add four bar linkage encoder, update four bar as joints * Set encoder as potentiometer, fix linkage defs * Fix merge, update fourbar pot configs * Fix linkage get joint pos * Fix formatting * Update Serials * Fix Syntax * Servos * Set servo board as a motor, add servo functions to interface * Add PWM scale, error checking * Remove extra init * Add print packet, stepper fake can * Update pring, step packet * Fix servo request * Add CAN Packet * Add stepper control --------- Co-authored-by: Varun <vvijayababu4334@gmail.com>
1 parent a2c231c commit bd85c6d

20 files changed

Lines changed: 283 additions & 33 deletions

src/CAN/CAN.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,20 @@ void sendCANPacket(const CANPacket& packet) {
285285
}
286286
}
287287

288+
void printCANPacket(const CANPacket& packet) {
289+
std::stringstream ss;
290+
ss << "CAN: p" << std::hex << ((packet.id >> 10) & 0x1);
291+
ss << " g" << std::hex << ((packet.id & 0x03C0) >> 6);
292+
ss << " s" << std::hex << ((packet.id & 0x003F));
293+
ss << " pid" << std::hex << static_cast<uint>(packet.data[0]);
294+
ss << " data:";
295+
for (int i = 1; i < packet.dlc; i++) {
296+
ss << std::hex << static_cast<uint>(packet.data[i]) << " ";
297+
}
298+
299+
LOG_F(INFO, ss.str().c_str());
300+
}
301+
288302
robot::types::DataPoint<telemetry_t> getDeviceTelemetry(deviceid_t id, telemtype_t telemType) {
289303
std::shared_lock mapLock(telemMapMutex); // acquire read lock
290304
// find entry for device in map

src/CAN/CAN.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ void initCAN();
4343
*/
4444
void sendCANPacket(const CANPacket& packet);
4545

46+
// Print packet for debugging purposes
47+
void printCANPacket(const CANPacket& packet);
48+
4649
/**
4750
* @brief Get the latest telemetry from a CAN device.
4851
*

src/CAN/CANMotor.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {
1111
#include <HindsightCAN/CANCommon.h>
1212
#include <HindsightCAN/CANMotorUnit.h>
1313
#include <HindsightCAN/CANPacket.h>
14+
#include <HindsightCAN/CANScience.h>
1415
}
1516

1617
using namespace std::chrono_literals;
@@ -121,10 +122,16 @@ void setMotorPIDTarget(devicegroup_t group, deviceserial_t serial, int32_t targe
121122

122123
void setServoPos(devicegroup_t group, deviceserial_t serial, uint8_t servoNum, int32_t angle) {
123124
CANPacket p;
124-
AssemblePCAServoPacket(&p, static_cast<uint8_t>(group), serial, servoNum, angle);
125+
AssembleScienceServoPacket(&p, static_cast<uint8_t>(group), serial, servoNum, angle);
125126
sendCANPacket(p);
126127
}
127128

129+
void setStepperTurnAngle(devicegroup_t group, deviceserial_t serial, uint8_t stepper, int16_t angle) {
130+
CANPacket p;
131+
AssembleScienceStepperTurnAnglePacket(&p, static_cast<uint8_t>(group), serial, stepper, angle, 0x3);
132+
sendCANPacket(p);
133+
}
134+
128135
DataPoint<int32_t> getMotorPosition(devicegroup_t group, deviceserial_t serial) {
129136
return getDeviceTelemetry(std::make_pair(group, serial), telemtype_t::angle);
130137
}

src/CAN/CANMotor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,12 @@ void setMotorPIDTarget(devicegroup_t group, deviceserial_t serial, int32_t targe
148148
*
149149
* @param serial The CAN serial number of the motor board.
150150
* @param servoNum the servo number.
151-
* @param angle the angle of the servo in millidegrees.
151+
* @param position the position of the servo in degrees.
152152
*/
153153
void setServoPos(devicegroup_t group, deviceserial_t serial, uint8_t servoNum, int32_t angle);
154154

155+
void setStepperTurnAngle(devicegroup_t group, deviceserial_t serial, uint8_t stepper, int16_t angle);
156+
155157
/**
156158
* @brief Get the last reported position of a motor.
157159
*

src/CAN/FakeCANBoard.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <vector>
1313

1414
extern "C" {
15+
#include <HindsightCAN/CANPower.h>
1516
#include <HindsightCAN/CANScience.h>
1617
}
1718

@@ -28,14 +29,17 @@ enum class TestMode {
2829
Encoder,
2930
LimitSwitch,
3031
Telemetry,
31-
ScienceServos
32+
ScienceServos,
33+
Stepper,
34+
RawCAN
3235
};
3336

3437
std::unordered_set<int> modes = {
3538
static_cast<int>(TestMode::ModeSet), static_cast<int>(TestMode::PWM),
3639
static_cast<int>(TestMode::PID), static_cast<int>(TestMode::Encoder),
3740
static_cast<int>(TestMode::PIDVel), static_cast<int>(TestMode::LimitSwitch),
38-
static_cast<int>(TestMode::Telemetry), static_cast<int>(TestMode::ScienceServos)};
41+
static_cast<int>(TestMode::Telemetry), static_cast<int>(TestMode::ScienceServos),
42+
static_cast<int>(TestMode::Stepper), static_cast<int>(TestMode::RawCAN)};
3943

4044
int prompt(std::string_view message) {
4145
std::string str;
@@ -59,8 +63,6 @@ int prompt(std::string_view message) {
5963
int main() {
6064
can::initCAN();
6165

62-
CANPacket p;
63-
uint8_t science_group = static_cast<int>(can::devicegroup_t::science);
6466
std::stringstream ss("What are you testing?\n");
6567
ss << static_cast<int>(TestMode::ModeSet) << " for MODE SET\n";
6668
ss << static_cast<int>(TestMode::PWM) << " for PWM\n";
@@ -69,6 +71,8 @@ int main() {
6971
ss << static_cast<int>(TestMode::LimitSwitch) << " for LIMIT SWITCH\n";
7072
ss << static_cast<int>(TestMode::Telemetry) << " for TELEMETRY\n";
7173
ss << static_cast<int>(TestMode::ScienceServos) << " for SCIENCE SERVOS\n";
74+
ss << static_cast<int>(TestMode::Stepper) << " for STEPPER\n";
75+
ss << static_cast<int>(TestMode::RawCAN) << " for CAN\n";
7276
int test_type = prompt(ss.str().c_str());
7377
if (modes.find(test_type) == modes.end()) {
7478
std::cout << "Unrecognized response: " << test_type << std::endl;
@@ -287,10 +291,37 @@ int main() {
287291
} else if (testMode == TestMode::ScienceServos) {
288292
int servo_no = prompt("Enter servo no");
289293
int degrees = prompt("Enter degrees");
290-
// AssembleScienceServoPacket(&p, science_group, 0x0, (uint8_t)servo_no,
291-
// (uint8_t)degrees);
292-
AssembleScienceStepperTurnAnglePacket(&p, science_group, 0x3, (uint8_t) servo_no, degrees, 0x3);
294+
295+
CANPacket p;
296+
AssembleScienceServoPacket(&p, 0x7, 0x5, (uint8_t)servo_no,
297+
(uint8_t)degrees);
293298
can::sendCANPacket(p);
294-
}
299+
can::printCANPacket(p);
300+
} else if (testMode == TestMode::Stepper) {
301+
int stepper = prompt("Enter stepper");
302+
int angle = prompt("Enter angle");
303+
304+
CANPacket p;
305+
AssembleScienceStepperTurnAnglePacket(&p, 0x7, 0x4, stepper, angle, 0x3);
306+
can::sendCANPacket(p);
307+
can::printCANPacket(p);
308+
} else if (testMode == TestMode::RawCAN) {
309+
uint8_t pr = prompt("priority");
310+
uint8_t g = prompt("group");
311+
uint8_t s = prompt("serial");
312+
uint8_t pid = prompt("pid");
313+
uint8_t dlc = prompt("add'l. data bits");
314+
uint8_t data[dlc+1];
315+
data[0] = pid;
316+
317+
for (int i = 1; i <= dlc; i++) {
318+
data[i] = prompt("bit");
319+
}
320+
321+
CANPacket p;
322+
AssembleCANPacket(&p, pr, g, s, pid, dlc+1, data);
323+
can::sendCANPacket(p);
324+
can::printCANPacket(p);
325+
}
295326
}
296327
}

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ find_package(nlohmann_json 3.2.0 REQUIRED)
9494
FetchContent_Declare(
9595
HindsightCAN
9696
GIT_REPOSITORY https://github.com/huskyroboticsteam/HindsightCAN.git
97-
GIT_TAG 6ae5db46856cd1f745ad5e1745a6983f4fc372c1
97+
GIT_TAG ce04c1a2dced3eb0e5beaaf39b2fcc436655e790
9898
)
9999
FetchContent_MakeAvailable(HindsightCAN)
100100

src/control_interface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ void setJointPos(types::jointid_t joint, int32_t targetPos);
5050
*/
5151
types::DataPoint<int32_t> getJointPos(types::jointid_t joint);
5252

53+
void setScienceServoPos(uint8_t servoNum, int32_t angle);
5354
} // namespace robot

src/network/MissionControlMessages.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace net::mc {
44

55
// TODO: possibly use frozen::string for this so we don't have to use raw char ptrs
6+
67
// request keys
78
constexpr const char* EMERGENCY_STOP_REQ_TYPE = "emergencyStopRequest";
89
constexpr const char* OPERATION_MODE_REQ_TYPE = "operationModeRequest";
@@ -15,6 +16,8 @@ constexpr const char* CAMERA_STREAM_OPEN_REQ_TYPE = "cameraStreamOpenRequest";
1516
constexpr const char* CAMERA_STREAM_CLOSE_REQ_TYPE = "cameraStreamCloseRequest";
1617
constexpr const char* CAMERA_FRAME_REQ_TYPE = "cameraFrameRequest";
1718
constexpr const char* WAYPOINT_NAV_REQ_TYPE = "waypointNavRequest";
19+
constexpr const char* SERVO_POSITION_REQ_TYPE = "servoPositionRequest";
20+
constexpr const char* STEPPER_TURN_ANGLE_REQ_TYPE = "stepperTurnAngleRequest";
1821

1922
// report keys
2023
constexpr const char* CAMERA_STREAM_REP_TYPE = "cameraStreamReport";
@@ -23,5 +26,6 @@ constexpr const char* MOUNTED_PERIPHERAL_REP_TYPE = "mountedPeripheralReport";
2326
constexpr const char* JOINT_POSITION_REP_TYPE = "jointPositionReport";
2427
constexpr const char* ROVER_POS_REP_TYPE = "roverPositionReport";
2528
constexpr const char* ARM_IK_ENABLED_REP_TYPE = "armIKEnabledReport";
29+
constexpr const char* SERVO_POSITION_REP_TYPE = "servoPositionReport";
2630

2731
} // namespace net::mc

src/network/MissionControlProtocol.cpp

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,52 @@ void MissionControlProtocol::handleJointPowerRequest(const json& j) {
176176
}
177177
}
178178

179+
static bool validateJointPositionRequest(const json& j) {
180+
return validateJoint(j) && util::validateKey(j, "position", val_t::number_integer);
181+
}
182+
183+
static void handleJointPositionRequest([[maybe_unused]] const json& j) {
184+
// TODO: ignore this message if we are in autonomous mode.
185+
// std::string motor = j["joint"];
186+
// double position_deg = j["position"];
187+
// int32_t position_mdeg = std::round(position_deg * 1000);
188+
// TODO: actually implement joint position requests
189+
// setMotorPos(motor, position_mdeg);
190+
}
191+
192+
static bool validateServo(const json& j) {
193+
return util::validateKey(j, "servo", val_t::string);/* &&
194+
std::any_of(all_jointid_t.begin(), all_jointid_t.end(), [&](const auto& joint) {
195+
return j["joint"].get<std::string>() == util::to_string(joint);
196+
});*/
197+
}
198+
199+
static bool validateServoPositionRequest(const json& j) {
200+
return validateServo(j);// && util::validateKey(j, "position", val_t::number_integer);
201+
}
202+
203+
void MissionControlProtocol::handleServoPositionRequest(const json& j) {
204+
std::string servoName = j["servo"];
205+
int32_t position = j["position"];
206+
auto servo = name_to_servoid.find(util::freezeStr(servoName));
207+
if (servo != name_to_servoid.end()) {
208+
robot::setServoPos(servo->second, position);
209+
}
210+
}
211+
212+
static bool validateStepperTurnAngleRequest(const json& j) {
213+
return util::hasKey(j, "stepper");
214+
}
215+
216+
void MissionControlProtocol::handleStepperTurnAngleRequest(const json& j) {
217+
std::string stepperName = j["stepper"];
218+
int16_t angle = j["angle"];
219+
auto stepper = name_to_stepperid.find(util::freezeStr(stepperName));
220+
if (stepper != name_to_stepperid.end()) {
221+
robot::setRequestedStepperTurnAngle(stepper->second, angle);
222+
}
223+
}
224+
179225
static bool validateWaypointNavRequest(const json& j) {
180226
bool lat_is_unsigned = util::validateKey(j, "latitude", val_t::number_unsigned);
181227
bool lon_is_unsigned = util::validateKey(j, "longitude", val_t::number_unsigned);
@@ -202,19 +248,6 @@ void MissionControlProtocol::handleWaypointNavRequest(const json& j) {
202248
}
203249
}
204250

205-
static bool validateJointPositionRequest(const json& j) {
206-
return validateJoint(j) && util::validateKey(j, "position", val_t::number_integer);
207-
}
208-
209-
static void handleJointPositionRequest([[maybe_unused]] const json& j) {
210-
// TODO: ignore this message if we are in autonomous mode.
211-
// std::string motor = j["joint"];
212-
// double position_deg = j["position"];
213-
// int32_t position_mdeg = std::round(position_deg * 1000);
214-
// TODO: actually implement joint position requests
215-
// setMotorPos(motor, position_mdeg);
216-
}
217-
218251
static bool validateCameraStreamOpenRequest(const json& j) {
219252
// return util::validateKey(j, "camera", val_t::number_integer);
220253
return util::hasKey(j, "camera");
@@ -352,6 +385,14 @@ MissionControlProtocol::MissionControlProtocol(SingleClientWSServer& server)
352385
WAYPOINT_NAV_REQ_TYPE,
353386
std::bind(&MissionControlProtocol::handleWaypointNavRequest, this, _1),
354387
validateWaypointNavRequest);
388+
this->addMessageHandler(
389+
SERVO_POSITION_REQ_TYPE,
390+
std::bind(&MissionControlProtocol::handleServoPositionRequest, this, _1),
391+
validateServoPositionRequest);
392+
this->addMessageHandler(
393+
STEPPER_TURN_ANGLE_REQ_TYPE,
394+
std::bind(&MissionControlProtocol::handleStepperTurnAngleRequest, this, _1),
395+
validateStepperTurnAngleRequest);
355396
this->addConnectionHandler(std::bind(&MissionControlProtocol::handleConnection, this));
356397
this->addDisconnectionHandler(
357398
std::bind(&MissionControlProtocol::stopAndShutdownPowerRepeat, this, false));

src/network/MissionControlProtocol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class MissionControlProtocol : public WebSocketProtocol { // TODO: add documenta
5151
void handleWaypointNavRequest(const json& j);
5252
void handleDriveRequest(const json& j);
5353
void handleRequestArmIKEnabled(const json& j);
54+
void handleServoPositionRequest(const json& j);
55+
void handleStepperTurnAngleRequest(const json& j);
5456
void sendArmIKEnabledReport(bool enabled);
5557
void handleConnection();
5658
void handleHeartbeatTimedOut();

0 commit comments

Comments
 (0)